Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions .agent/context/20260908T113831Z-live-arc-subgraph.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Session Context: live Arc subgraph

## Date/time

- UTC: 2026-09-08T11:38:31Z

## User goal

Deploy a live OneShot Subgraph that indexes Arc Testnet USDC transfers and make
it available to the recovery path through The Graph Gateway and Subgraph MCP.

## Original prompt/request

The user confirmed that the Privy secret, Graph deploy key, and Graph Gateway
API key exist in Google Secret Manager and asked to continue connecting The
Graph. No credential values belong in the repository.

## Assumptions

- Arc Testnet `eip155:5042002` and its USDC interface remain the selected demo profile.
- The initial start block may intentionally precede the first OneShot demo transfer.
- The Graph results discover candidates only; Arc RPC remains authoritative.

## Plan

1. Commit and publish the independently buildable subgraph source.
2. Wait for a Graph Network indexer allocation to the published deployment.
3. Verify an immutable live query through Gateway and Subgraph MCP.
4. Wire the live MCP adapter without exposing credentials.

## Key decisions

- Index immutable USDC `Transfer` events with sender, recipient, amount, block,
log index, timestamp, and transaction hash.
- Pin the recovery path to the immutable manifest deployment instead of an
automatically moving Studio version label.
- Publish registration on Arbitrum One while the indexed data source remains Arc Testnet.

## Files/components touched

- `subgraph/`: manifest, ERC-20 ABI, schema, mapping, package metadata, lockfile,
candidate-query documentation, and generated/build ignores.

## Commands/checks

- `pnpm --dir subgraph codegen` - passed.
- `pnpm --dir subgraph build` - passed.
- Studio deployment `v0.1.0` - deployed and indexing live Arc events without errors.
- Studio GraphQL `_meta` and transfer query - passed with live data.
- Graph Gateway immutable-deployment query - publication visible, currently waiting on an Indexer allocation.
- `git diff --check` - passed before handoff preparation.

## External-doc findings

- The Graph CLI `0.98.1` uses the Studio deploy endpoint and supports publishing
the same Arc-indexing manifest through The Graph Network registration on Arbitrum One.
- Hosted Subgraph MCP queries published deployments through The Graph Gateway;
a Studio-only deployment is insufficient for that path.

## Unresolved questions

- Which of the two duplicate publication registrations should be the canonical Subgraph ID.
- When the first Indexer allocation will become available for the published deployment.

## Git and PR state

- Branch: `milestone/c06-live-subgraph`
- Base: `origin/develop` at `25a17d86b56822a7e7440d34c331b740cb6d7f04`
- Commit: uncommitted
- PR: not created
- CI: not run

## Review gates

- Gate A: NOT RUN; the user requested no review gates for this configuration/integration step.
- Gate B: NOT RUN; no PR exists.

## Handoff/next steps

1. Obtain the canonical public Subgraph ID from Graph Explorer/Studio.
2. Wait for allocation and verify the live deployment through Gateway and hosted Subgraph MCP.
3. Commit and push the focused branch, then implement the runtime adapter separately.
81 changes: 81 additions & 0 deletions .agent/context/20260908T122712Z-c06-qualification-demo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# C06 qualification demo context

- Branch: `milestone/c06-qualification-demo`
- Base: merged `origin/develop` at `1250dec79bc702939fe2a3b0fd00e66bb34128af`
- User correction: C06 starts from merged `develop`, not the C05 feature branch.
- Public target: `https://oneshot.kapustazh.dev/` currently serves
`apps/placeholder-frontend` through Wrangler.
- C06 will publish the recovery UI as a clearly labelled synthetic review demo,
add repeatable qualification/evidence checks, and preserve zero-submit safety.
- Live Privy, Arc Testnet, and Subgraph MCP evidence is absent at branch start.
Sponsor verdicts therefore remain `NOT VERIFIED`; fixtures and plans must not
be promoted into live evidence.
- No external wallet, policy, funding, deployment, or real-value mutation is in
scope without separate human provisioning and authorization.
- FreePi policy: use `/model free-pi/glm-5.3-flash` first; do not stream noisy
progress. If a quiet review is not practical, provide the exact prompt to the
user for manual relay.

## Implemented

- Wrangler now builds/deploys the recovery viewer instead of the placeholder.
- Wrangler owns the frontend build hook, so Cloudflare's direct `wrangler
deploy` path creates `site-dist` on a clean checkout.
- The public viewer uses in-memory fixtures, exposes a scenario selector, and
carries a persistent synthetic/not-live evidence banner.
- Production recovery defaults no longer substitute Graph/model simulators;
absent live ports fail closed as unavailable.
- Added a sponsor evidence classifier that requires `LIVE_CAPTURE` for live
requirements and reports `NOT_VERIFIED` for plans, simulators, or missing refs.
- Added C06 evidence index, demo/reset runbook, live capture checklist,
qualification report, and limitations.
- Merged `origin/milestone/c06-live-subgraph` commit `fe54774`: Arc Testnet USDC
Subgraph source plus a recorded Studio deployment. This does not upgrade The
Graph beyond `NOT VERIFIED` because the canonical immutable identity, Indexer
allocation, live MCP trace, and model/core trace remain missing.

## Validation

- Recovery UI: lint/type/build PASS; 51 tests PASS.
- Reconciliation: lint/type/build PASS; 74 tests PASS.
- Worker: lint/type PASS; 20 tests PASS.
- Root: lint/type/build PASS; 569 tests PASS; generated contracts and fixtures PASS.
- Replay nondeterminism found during full validation was fixed by binding the
chaos harness decision timestamp to its recorded scenario clock.
- Wrangler production bundle dry-run PASS; no deployment performed.
- Desktop and 390x844 mobile visual QA PASS.
- Changed-file Prettier PASS. Repository-wide format remains affected by the
pre-existing Windows line-ending baseline.

## Live gate

Privy, Arc, and The Graph remain `NOT VERIFIED`. C06 live acceptance cannot pass
until a human provisions and returns the sanitized artifacts in
`packages/reconciliation/docs/c06/LIVE_CAPTURE_CHECKLIST.md`.

## Review state

- Recorded base: `1250dec79bc702939fe2a3b0fd00e66bb34128af`.
- Gate A passed tree `28b9445183b7d453ab813662ab3be0d15afbd2e3` and
produced commit `41399ad18433116b71eb9ad910bec34e024f3f60`.
- That Gate A is now invalidated by the user-requested merge of
`milestone/c06-live-subgraph` and the subsequent integration fixes. A new
candidate review is required before another push.

## Post-review integration

- Merged commit `fe547744db3ef4d70e8d87a7bdcf8b736cafb6c9` through merge
commit `4ce750f`.
- Cloudflare check `15da7c47-1b3d-4f57-8408-d772eb4396fc` failed at the
pre-deploy boundary. Its private log requires Cloudflare login; the local
configuration showed that a clean direct `wrangler deploy` had no guaranteed
`site-dist` build.
- Added Wrangler `build.command`; dry-run now logs the custom Vite build before
loading four static assets.
- Added `subgraph` to the root pnpm workspace, moved dependency authority to the
root lockfile, and removed the redundant nested lockfile.
- Subgraph codegen PASS and Graph build PASS on Windows PowerShell.
- Root lint/type/build PASS; 569 tests PASS after the merge. Root build now
includes the Subgraph compiler.
- Wrangler dry-run PASS with the custom build hook visibly executing before
asset discovery. No Cloudflare deployment or rerun was performed.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ temp/

# Build artifacts and caches (expand per stack)
dist/
site-dist/
build/
coverage/
node_modules/
Expand Down
77 changes: 46 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,11 @@ flowchart TB
PrivyAdapter --> Privy[Privy wallet and policy]
ArcAdapter --> Arc[Arc USDC and RPC]
MCPAdapter -.-> MCP[Subgraph MCP]
MCP -.-> GraphIndex[Live OneShot Arc Subgraph]
MCP -.-> GraphIndex[OneShot Arc Subgraph]
```

Solid edges are implemented. Dashed edges are planned and not yet built.
Solid edges are implemented. Dashed runtime edges are unavailable in production;
the Subgraph source exists, but live Subgraph MCP/model composition is not verified.

### The state machine

Expand Down Expand Up @@ -101,7 +102,7 @@ These are enforced in code and tests, not by convention:
- **One atomic transition grants submission ownership.** Exactly one worker
crosses the external boundary.
- **Doubt fails closed.** A timeout, reset, truncated response, or any
unrecognized error is treated as *possibly submitted*, never as a safe retry.
unrecognized error is treated as _possibly submitted_, never as a safe retry.
- **A successful receipt is not confirmation.** Settlement is committed only
when the receipt carries exactly one matching ERC-20 Transfer, to the expected
recipient, for the exact amount, from the configured token.
Expand All @@ -112,11 +113,11 @@ These are enforced in code and tests, not by convention:

## Integrations

| System | Role |
| --- | --- |
| **Privy** | Corporate wallet, scoped authorization, and spending policy |
| **Arc** | USDC settlement rail (Arc Testnet, chain `5042002`) |
| **The Graph** | Planned candidate discovery when a transaction hash is lost |
| System | Role |
| ------------- | ----------------------------------------------------------------- |
| **Privy** | Corporate wallet, scoped authorization, and spending policy |
| **Arc** | USDC settlement rail (Arc Testnet, chain `5042002`) |
| **The Graph** | Arc USDC Subgraph source; live Subgraph MCP qualification pending |

Privy authorizes and constrains the wallet action. It is not the duplicate
lock: OneShot's durable state is.
Expand All @@ -133,7 +134,9 @@ packages/storage-postgres durable ledger and migrations
packages/arc-adapter Arc profiles, money, receipts, readiness
packages/privy-adapter authorization, requests, policy, adapters
packages/reconciliation recovery evidence and safety core
packages/recovery-ui synthetic recovery evidence viewer
packages/testkit-* simulators and sanitized fixtures
subgraph Arc Testnet USDC transfer indexer
```

## Quick start
Expand Down Expand Up @@ -166,31 +169,42 @@ pnpm --filter @oneshot/arc-adapter probe

That command is read-only. It cannot sign, send, or mutate anything.

To view the recovery UI locally:

```bash
pnpm --filter @oneshot/recovery-ui dev
```

Open `http://localhost:5173/?scenario=aged-unknown`. The public Wrangler target
uses the same clearly labelled synthetic viewer. Wrangler's build hook creates
the static bundle before local preview or `pnpm deploy`, including on a fresh
Cloudflare Workers Build checkout.

## API

| Method | Path | Purpose |
| --- | --- | --- |
| `POST` | `/v1/intents` | Create an intent; an identical replay returns the same result |
| `GET` | `/v1/intents/{id}` | Authoritative intent, attempts, settlement, evidence |
| `POST` | `/v1/intents/{id}/reconcile` | Trigger read-only reconciliation; never submits |
| `GET` | `/v1/intents/{id}/recovery-view` | Local authority plus labelled provider observations |
| `GET` | `/v1/metrics` | Operational metrics |
| `GET` | `/health/live` | Process liveness |
| `GET` | `/health/ready` | Configuration and Arc identity readiness |
| Method | Path | Purpose |
| ------ | -------------------------------- | ------------------------------------------------------------- |
| `POST` | `/v1/intents` | Create an intent; an identical replay returns the same result |
| `GET` | `/v1/intents/{id}` | Authoritative intent, attempts, settlement, evidence |
| `POST` | `/v1/intents/{id}/reconcile` | Trigger read-only reconciliation; never submits |
| `GET` | `/v1/intents/{id}/recovery-view` | Local authority plus labelled provider observations |
| `GET` | `/v1/metrics` | Operational metrics |
| `GET` | `/health/live` | Process liveness |
| `GET` | `/health/ready` | Configuration and Arc identity readiness |

The contract is defined in `packages/contracts/openapi/openapi.v1.json`.

## Project status

Under active development. **Testnet only.**

| Area | Status |
| --- | --- |
| Durable intent ledger, API, worker | Implemented |
| Settlement adapters and error taxonomy | Implemented, exercised against simulators |
| Recovery evidence and safety core | In progress |
| Subgraph MCP discovery and LLM recovery agent | Planned |
| Operator frontend | Intent creation, replay/conflict, and authoritative status implemented |
| Area | Status |
| --------------------------------------------- | ----------------------------------------------------------------------------------- |
| Durable intent ledger, API, worker | Implemented |
| Settlement adapters and error taxonomy | Implemented, exercised against simulators |
| Recovery evidence and safety core | Implemented against simulators |
| Subgraph MCP discovery and LLM recovery agent | Implemented boundary; live path not verified |
| Operator frontend | Intent/status UI and synthetic recovery viewer implemented; live API wiring pending |

**No live settlement has been executed.** No Privy application, wallet, policy,
or funded testnet account has been provisioned for this build. The adapters are
Expand All @@ -204,13 +218,14 @@ plus explicit human authorization.

## Documentation

| Document | Contents |
| --- | --- |
| [`plan.md`](plan.md) | Product plan, scope, and delivery gates |
| [`docs/DOMAIN_ARCHITECTURE.md`](docs/DOMAIN_ARCHITECTURE.md) | Domain model and boundaries |
| [`milestones/CONTRACTS.md`](milestones/CONTRACTS.md) | Frozen v1 contract pack |
| [`docs/settlement/`](docs/settlement/) | Settlement config, provider setup, live evidence |
| [`AGENTS.md`](AGENTS.md) | Contribution policy and review gates |
| Document | Contents |
| ------------------------------------------------------------------------ | ------------------------------------------------ |
| [`plan.md`](plan.md) | Product plan, scope, and delivery gates |
| [`docs/DOMAIN_ARCHITECTURE.md`](docs/DOMAIN_ARCHITECTURE.md) | Domain model and boundaries |
| [`milestones/CONTRACTS.md`](milestones/CONTRACTS.md) | Frozen v1 contract pack |
| [`docs/settlement/`](docs/settlement/) | Settlement config, provider setup, live evidence |
| [`packages/reconciliation/docs/c06/`](packages/reconciliation/docs/c06/) | C06 demo and qualification evidence index |
| [`AGENTS.md`](AGENTS.md) | Contribution policy and review gates |

## License

Expand Down
4 changes: 4 additions & 0 deletions apps/web/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

Minimal operator UI for creating or replaying a Business Intent and reading its authoritative status.

This package is not the production Worker asset target yet. Deploy it only after
`VITE_ONESHOT_API_BASE_URL` points to a reachable OneShot API. An assets-only
Worker cannot serve `/health` or `/v1`.

```powershell
pnpm --filter @oneshot/web dev
```
Expand Down
10 changes: 4 additions & 6 deletions apps/worker/src/composition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ import type {
WorkerOptions,
} from './types.js';
import {
createScenario,
RecoveryAgentSimulator,
RecoveryService,
SimulatorSubgraphMcpRecoveryPort,
UnavailableRecoveryAdvisorPort,
UnavailableSubgraphMcpRecoveryPort,
type RecoveryAdvisorPort,
type SubgraphMcpRecoveryPort,
} from '@oneshot/reconciliation';
Expand All @@ -44,9 +43,8 @@ export function createProductionRecoveryService(
localStatePort: localState,
...bridgeOptions,
});
const subgraphMcp =
subgraphMcpPort ?? new SimulatorSubgraphMcpRecoveryPort(createScenario('empty'));
const recoveryAdvisor = advisor ?? new RecoveryAgentSimulator({ scenario: 'auto' });
const subgraphMcp = subgraphMcpPort ?? new UnavailableSubgraphMcpRecoveryPort();
const recoveryAdvisor = advisor ?? new UnavailableRecoveryAdvisorPort();
return new RecoveryService({
localState,
knownIdentityEvidence,
Expand Down
9 changes: 8 additions & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import tseslint from 'typescript-eslint';

export default tseslint.config(
{
ignores: ['**/coverage/**', '**/dist/**', '**/generated/**'],
ignores: ['**/coverage/**', '**/dist/**', '**/site-dist/**', '**/generated/**'],
},
eslint.configs.recommended,
...tseslint.configs.recommended,
Expand All @@ -20,4 +20,11 @@ export default tseslint.config(
'@typescript-eslint/no-import-type-side-effects': 'error',
},
},
{
files: ['subgraph/src/**/*.ts'],
rules: {
// AssemblyScript does not support TypeScript's `import type` syntax.
'@typescript-eslint/consistent-type-imports': 'off',
},
},
);
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
"pnpm": "11.19.0"
},
"scripts": {
"build": "tsc -b",
"build": "tsc -b && pnpm --filter @oneshot/arc-subgraph build",
"check:generated": "pnpm --filter @oneshot/contracts check:generated",
"clean": "tsc -b --clean",
"deploy": "pnpm --filter @oneshot/web build && wrangler deploy",
"dev:frontend": "pnpm --filter @oneshot/web dev",
"deploy": "wrangler deploy",
"dev:frontend": "wrangler dev",
"dev:web": "pnpm --filter @oneshot/web dev",
"format": "prettier --write \"**/*.{ts,mts,mjs,json,jsonc,yml,yaml}\"",
"format:check": "prettier --check \"**/*.{ts,mts,mjs,json,jsonc,yml,yaml}\"",
"generate": "pnpm --filter @oneshot/contracts generate",
Expand Down
Loading
Loading