From 9f27b4017922b046e42fb0ff715951d390b93fe0 Mon Sep 17 00:00:00 2001 From: Tony Ketcham Date: Wed, 12 Aug 2026 10:53:23 -0700 Subject: [PATCH] feat: brand agent memory as Proof and the runner as Oven Switch the memory package, CLI, types, and docs to Proof. Point remaining DAG-runner mentions at Oven. Co-authored-by: Cursor Change-Id: Ic03af69fa313f104155886c7e6ffa0253dc2a0cd --- .../skills/effort-modeling/CONTEXT-FORMAT.md | 2 +- .agents/skills/effort-modeling/SKILL.md | 12 +- .agents/skills/grill-with-efforts/SKILL.md | 2 +- .../skills/{effort-graph => proof}/SKILL.md | 54 ++++----- .../{effort-graph => proof}/glossary.md | 10 +- .../{effort-graph => proof}/reference.md | 44 +++---- .../skills/proof}/release.json | 2 +- .../skills/{effort-graph => proof}/setup.md | 32 ++--- .../agents/flatbread-architecture-planner.md | 2 +- .../flatbread-code-review-orchestrator.md | 14 +-- .cursor/dags/README.md | 18 +-- .../skills/flatbread-major-migration/SKILL.md | 4 +- ...lob-cite-design-notes--j3jbgc0cymdb2t9g.md | 0 ...read-refs-docs-intent--ew3x4qpx1x3c1cy2.md | 0 ...ocal-blob-design-dump--pg7g6qy1td7yjqpy.md | 0 ...rface-not-the-product--4966nqjsnsmwq1fs.md | 0 ...ys-deliberately-small--02k06bxbjwrjfp9x.md | 0 ...ys-deliberately-small--45v1ae3neq26g1rz.md | 0 ...-markdown-yaml-writer--wrawg3b0hp779hd8.md | 0 ...e-the-source-of-truth--pnd7w2bs2zvk7ye9.md | 0 ...cli-and-unified-watch--k9dpxj57yrcv0pbz.md | 0 ...fing-fast-path-for-ef--kcw0rw39g3b2ym2h.md | 0 ...urface-as-crumb-graph--fvskcvagx3a7sybe.md | 0 ...urface-as-crumb-trail--tngncepdbwjkh9jc.md | 0 ...tions-into-live-reads--mc3728t4w1kyqcqq.md | 0 ...-journaled-save-or-un--sv9x93svkfz4a98r.md | 0 ...read-write-extraction--xxa1ge2chw6x3xx0.md | 0 ...-as-a-versioned-agent--8as4sybr34zcqyqh.md | 0 ...nclude-the-full-recor--xs7rnbha3zx8qdj9.md | 0 ...ction-and-nullability--0khw2zkc51hy230t.md | 0 ...xtract-validation-api--e96yngmrjqcjdxcn.md | 0 ...inement-as-bounded-lo--9ptqq1ck3sax00fq.md | 0 ...h-as-the-product-name--r5wr2vdjwjs9bs13.md | 2 + ...-with-a-primary-wedge--estattvqnhffm2dc.md | 0 ...n-first-content-layer--rc3pc0vczp6qhp3t.md | 0 ...ort-graph-agent-memor--nhxsqm8sd43s2avx.md | 0 ...he-planning-authority--gq4xegmc0hhbqjf7.md | 0 ...before-replacing-tool--q7xpn1g7rk65xvzj.md | 0 ...ongform-payloads-blob--9b11q14fgsx2ytve.md | 0 ...of-and-the-dag-runner--8e1qgp2032607pr2.md | 47 ++++++++ ...he-flatbread-query-en--476qb9qk878yfg62.md | 0 ...on-and-display-planes--spm2ckxvdsch6h9m.md | 0 ...on-with-optional-blob--fyga3x876n7rcnmn.md | 0 ...ver-effort-scoped-edg--pxwaenyra0aa365j.md | 0 ...ts-in-repo-by-default--xxpgwm9sv25j07z7.md | 0 ...ories-without-a-cache--8bn823dg29yfvbzv.md | 0 ...with-reviewable-slugs--xdg764ejat1kacd2.md | 0 ...-not-separate-schemas--27p0wakkyxj0kfc1.md | 0 ...d-a-standalone-writer--2d0m3tkqhad4yyhr.md | 0 ...emory-and-agent-wedge--szeqvmgqjqnhd002.md | 0 ...read-product-branding--zt7b35sa05kyvhdz.md | 0 ...me-and-ownership-loop--g28gfbb0kdrnpe2t.md | 0 ...utor-operating-system--ahhgtafvdhg4dfve.md | 0 ...al-content-foundation--8a8332x4cazgf2k0.md | 0 ...-on-how-blobs-are-cit--z9s360sgahmtjz7h.md | 0 ...nd-planning-authority--j1waeg8qh900sqee.md | 0 ...tocol-halves-effort-g--ht1jd1hsssf7mv2y.md | 0 ...-stay-within-one-effo--gkyd4dczafebk4fz.md | 0 ...now-match-the-current--p6c37v29mx4jjfr2.md | 0 ...flatbread-refs-intact--z33ar5vyjxzr7ys0.md | 0 ...ip-same-effort-checks--pts8c8ar72vaevvh.md | 0 ...eview-effort-graph-is--n8kb269z7vz8jhyk.md | 0 ...faced-three-real-defe--g21hg77x72hdty56.md | 0 ...p-but-lack-external-v--fx2qtjpcm8mtpw4f.md | 0 ...is-94-percent-smaller--qpvz4vch5hygye20.md | 0 ...ul-but-not-fully-type--vmr23k0t6qx3hk1k.md | 0 ...same-excerpt-as-brows--q5rbnhpxc697x2dv.md | 0 ...aph-has-been-released--w3ewcvmg3402bm5w.md | 11 ++ ...eeds-mapping-profiles--k2yvq5e9rcpsm1s1.md | 0 ...but-retains-test-gaps--91h2ncmytj8mq40r.md | 0 ...ped-validation-and-wa--p04gd8xfknwvz2pe.md | 0 ...avor-trail-over-graph--zzpgaw0kvqtaqmxt.md | 0 ...passes-the-unified-wa--qqvckprax45hyd2y.md | 0 ...ts-users-to-watch-mod--cwgqyjjvr6j9gx8n.md | 0 ...seded-live-reload-gui--naafmpvt3pcdes4p.md | 0 ...y-is-roadmap-critical--2ss712xpmsfh77xf.md | 0 ...-reaches-a-typed-read--8anm4wxbjm9f348z.md | 0 ...ce-is-already-removed--w56t43aa10v311hj.md | 0 ...o-the-deleted-roadmap--k38zmv7pqv7z95ts.md | 0 ...d-per-build-isolation--vdjfmtqb0dbjfcqk.md | 0 ...till-teach-13-mutatio--gvg2btns0q7rp0eq.md | 0 ...cision-state-on-the-r--2m807tcfjz2jz9gt.md | 0 ...ntended-runtime-contr--t9ghag8yqxgf3p5t.md | 0 ...n-passes-full-reposit--hm5cy9j2zts96dg4.md | 0 ...rumb-graph-over-yeast--tv3ydt3wfb3n4y0g.md | 0 ...record-bodies-through--ekfpcg6hrkwgy287.md | 0 ...ng-decision-semantics--3bj9ph7ppab2c7g2.md | 0 ...and-crumb-graph-cites--g2c7m6j39we5xy3z.md | 0 ...e-across-packages-cli--dp6jvt2kafab7m4t.md | 0 ...e-across-packages-cli--316rdzpt80sdxkw1.md | 0 ...name-across-both-repo--xr02e1wp62ry1ccq.md | 18 +++ ...xport-cli-remain-gaps--xe19gzqf654xeyg4.md | 0 ...ollow-ups-remain-open--4fkjb93v3pey43y0.md | 0 ...-example-over-constra--vd0gcnpc9cm6jzjh.md | 0 ...remains-a-product-gap--4zawc913n4gnyfcw.md | 0 ...es-leaves-the-superse--by624gyf21ex42sv.md | 0 ...ow-prompts-and-leak-s--3p7ybk07jqe5w593.md | 0 .gitignore | 8 +- AGENTS.md | 3 +- CHANGELOG.md | 4 + CONTRIBUTING.md | 22 ++-- .../performant-context-search/README.md | 2 +- flatbread-agent-artifact-opportunity.md | 28 ++--- flatbread-flow-agentic-workflows.md | 12 +- flatbread-flow-pmf-audit.md | 2 +- flatbread.config.js | 6 +- package.json | 8 +- packages/explorer/README.md | 8 +- packages/explorer/package.json | 6 +- .../explorer/src/node/matchPreset.test.ts | 14 +-- packages/explorer/src/node/matchPreset.ts | 12 +- .../src/web/app/components/DetailDrawer.tsx | 6 +- .../src/web/app/components/GraphCanvas.tsx | 10 +- .../src/web/app/components/Legend.tsx | 4 +- .../{EffortGraphApp.tsx => ProofApp.tsx} | 16 +-- .../src/web/app/components/RelationLegend.tsx | 12 +- .../src/web/app/components/TopBar.tsx | 9 +- packages/explorer/src/web/app/main.tsx | 4 +- .../explorer/src/web/core/endpoints.test.ts | 6 +- .../explorer/src/web/core/physics/index.ts | 2 +- .../src/web/core/physics/simulation.ts | 2 +- .../explorer/src/web/core/physics/types.ts | 2 +- .../{effort-graph => proof}/glyphs.test.ts | 0 .../presets/{effort-graph => proof}/glyphs.ts | 0 .../{effort-graph => proof}/lifecycle.test.ts | 0 .../{effort-graph => proof}/lifecycle.ts | 0 .../{effort-graph => proof}/normalize.test.ts | 28 ++--- .../{effort-graph => proof}/normalize.ts | 8 +- .../{effort-graph => proof}/primitives.ts | 4 +- .../{effort-graph => proof}/query.test.ts | 10 +- .../presets/{effort-graph => proof}/query.ts | 14 +-- .../presets/{effort-graph => proof}/types.ts | 2 +- .../useProofLive.test.ts} | 2 +- .../useProofLive.ts} | 26 ++-- packages/explorer/tsconfig.json | 2 +- packages/explorer/tsup.config.ts | 2 +- packages/flatbread/README.md | 20 +-- packages/flatbread/package.json | 2 +- packages/flatbread/src/cli/index.ts | 4 +- packages/flatbread/src/cli/openPath.test.ts | 26 ++-- .../src/cli/{effort.test.ts => proof.test.ts} | 66 +++++----- .../flatbread/src/cli/{effort.ts => proof.ts} | 87 +++++++------ .../graphql/effortGraphComposition.test.ts | 68 ----------- .../src/graphql/explorerMount.test.ts | 32 ++--- .../flatbread/src/graphql/explorerMount.ts | 2 +- packages/flatbread/src/graphql/liveServer.ts | 20 +-- .../graphql/liveServerExplorerWatch.test.ts | 8 +- ...tGraph.test.ts => liveServerProof.test.ts} | 50 ++++---- .../src/graphql/proofComposition.test.ts | 62 ++++++++++ ...raphComposition.ts => proofComposition.ts} | 20 +-- packages/flatbread/src/index.ts | 2 +- .../flatbread/src/{effort => proof}/read.ts | 30 ++--- packages/{effort-graph => proof}/README.md | 34 +++--- packages/{effort-graph => proof}/package.json | 6 +- .../scripts/pack-skills.mjs | 12 +- .../scripts/sync-skills.mjs | 10 +- .../scripts/watch-skills.mjs | 0 .../skills/effort-modeling/CONTEXT-FORMAT.md | 2 +- .../skills/effort-modeling/DECISION-BODY.md | 0 .../skills/effort-modeling/SKILL.md | 12 +- .../skills/grill-with-efforts/SKILL.md | 2 +- .../skills/proof}/SKILL.md | 54 ++++----- .../skills/proof}/glossary.md | 10 +- .../skills/proof}/reference.md | 44 +++---- .../proof/skills/proof}/release.json | 2 +- .../skills/proof}/setup.md | 32 ++--- .../src/__tests__/decision-lifecycle.test.ts | 10 +- .../src/__tests__/digest.test.ts | 2 +- .../src/__tests__/ids.test.ts | 8 +- .../src/__tests__/journal-barrier.test.ts | 8 +- .../src/__tests__/journal-recovery.test.ts | 4 +- .../src/__tests__/live-bridge.test.ts | 14 +-- .../src/__tests__/lock.test.ts | 23 ++-- .../src/__tests__/pack-skills.test.js | 12 +- .../src/__tests__/planner.test.ts | 10 +- .../src/__tests__/preset.test.ts | 26 ++-- .../src/__tests__/read.test.ts | 0 .../src/__tests__/schemas.test.ts | 33 +++-- .../src/__tests__/skills.test.ts | 2 +- .../src/__tests__/snapshot.test.ts | 25 ++-- .../src/__tests__/writer.test.ts | 52 ++++---- .../src/decision-lifecycle.ts | 24 ++-- .../{effort-graph => proof}/src/digest.ts | 6 +- .../{effort-graph => proof}/src/errors.ts | 32 ++--- .../src/frontmatter.ts | 0 packages/{effort-graph => proof}/src/ids.ts | 0 .../src/index-store.ts | 24 ++-- packages/{effort-graph => proof}/src/index.ts | 6 +- .../{effort-graph => proof}/src/journal.ts | 14 +-- .../src/journalBarrier.ts | 18 ++- packages/{effort-graph => proof}/src/live.ts | 36 +++--- packages/{effort-graph => proof}/src/lock.ts | 4 +- .../{effort-graph => proof}/src/planner.ts | 77 ++++++------ .../{effort-graph => proof}/src/preset.ts | 8 +- packages/{effort-graph => proof}/src/read.ts | 34 +++--- .../{effort-graph => proof}/src/schemas.ts | 4 +- .../{effort-graph => proof}/src/snapshot.ts | 52 ++++---- packages/{effort-graph => proof}/src/types.ts | 12 +- .../{effort-graph => proof}/src/writer.ts | 12 +- .../{effort-graph => proof}/tsconfig.json | 0 .../{effort-graph => proof}/tsup.config.ts | 0 pnpm-lock.yaml | 114 +++++++++--------- scripts/bumpVersions.test.ts | 18 ++- scripts/bumpVersions.ts | 8 +- scripts/publish.test.ts | 6 +- tsconfig.json | 2 +- 206 files changed, 1031 insertions(+), 1008 deletions(-) rename .agents/skills/{effort-graph => proof}/SKILL.md (74%) rename .agents/skills/{effort-graph => proof}/glossary.md (92%) rename .agents/skills/{effort-graph => proof}/reference.md (77%) rename {packages/effort-graph/skills/effort-graph => .agents/skills/proof}/release.json (68%) rename .agents/skills/{effort-graph => proof}/setup.md (75%) rename {.flatbread-efforts => .flatbread-proof}/blobs/blb-blob-cite-design-notes--j3jbgc0cymdb2t9g.md (100%) rename {.flatbread-efforts => .flatbread-proof}/citations/cit-flatbread-refs-docs-intent--ew3x4qpx1x3c1cy2.md (100%) rename {.flatbread-efforts => .flatbread-proof}/citations/cit-local-blob-design-dump--pg7g6qy1td7yjqpy.md (100%) rename {.flatbread-efforts => .flatbread-proof}/constraints/con-graphql-is-a-read-interface-not-the-product--4966nqjsnsmwq1fs.md (100%) rename {.flatbread-efforts => .flatbread-proof}/constraints/con-mutation-enum-stays-deliberately-small--02k06bxbjwrjfp9x.md (100%) rename {.flatbread-efforts => .flatbread-proof}/constraints/con-mutation-enum-stays-deliberately-small--45v1ae3neq26g1rz.md (100%) rename {.flatbread-efforts => .flatbread-proof}/constraints/con-prettier-remains-the-markdown-yaml-writer--wrawg3b0hp779hd8.md (100%) rename {.flatbread-efforts => .flatbread-proof}/constraints/con-repo-files-are-the-source-of-truth--pnd7w2bs2zvk7ye9.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-add-export-cli-and-unified-watch--k9dpxj57yrcv0pbz.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-adopt-a-bounded-status-briefing-fast-path-for-ef--kcw0rw39g3b2ym2h.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-brand-the-agent-memory-surface-as-crumb-graph--fvskcvagx3a7sybe.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-brand-the-agent-memory-surface-as-crumb-trail--tngncepdbwjkh9jc.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-bridge-committed-generations-into-live-reads--mc3728t4w1kyqcqq.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-canonical-forward-edges-and-journaled-save-or-un--sv9x93svkfz4a98r.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-defer-shared-flatbread-write-extraction--xxa1ge2chw6x3xx0.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-distribute-the-effort-graph-as-a-versioned-agent--8as4sybr34zcqyqh.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-effort-get-digests-always-include-the-full-recor--xs7rnbha3zx8qdj9.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-iterate-typed-selection-and-nullability--0khw2zkc51hy230t.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-keep-and-extract-validation-api--e96yngmrjqcjdxcn.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-keep-dags-acyclic-model-refinement-as-bounded-lo--9ptqq1ck3sax00fq.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-keep-effort-graph-as-the-product-name--r5wr2vdjwjs9bs13.md (97%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-keep-effort-graph-secondary-with-a-primary-wedge--estattvqnhffm2dc.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-keep-relation-first-content-layer--rc3pc0vczp6qhp3t.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-lead-flatbread-1-0-with-effort-graph-agent-memor--nhxsqm8sd43s2avx.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-make-the-effort-graph-the-planning-authority--gq4xegmc0hhbqjf7.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-modernize-reachable-checks-before-replacing-tool--q7xpn1g7rk65xvzj.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-name-citeable-longform-payloads-blob--9b11q14fgsx2ytve.md (100%) create mode 100644 .flatbread-proof/decisions/dec-name-the-memory-product-proof-and-the-dag-runner--8e1qgp2032607pr2.md rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-route-agent-reads-through-the-flatbread-query-en--476qb9qk878yfg62.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-separate-execution-and-display-planes--spm2ckxvdsch6h9m.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-ship-citation-collection-with-optional-blob--fyga3x876n7rcnmn.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-specify-blockingdecisions-over-effort-scoped-edg--pxwaenyra0aa365j.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-store-graph-artifacts-in-repo-by-default--xxpgwm9sv25j07z7.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-use-isolated-schema-factories-without-a-cache--8bn823dg29yfvbzv.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-use-prefixed-random-ids-with-reviewable-slugs--xdg764ejat1kacd2.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-use-profiles-not-separate-schemas--27p0wakkyxj0kfc1.md (100%) rename {.flatbread-efforts => .flatbread-proof}/decisions/dec-use-semantic-mutations-and-a-standalone-writer--2d0m3tkqhad4yyhr.md (100%) rename {.flatbread-efforts => .flatbread-proof}/efforts/eff-effort-graph-memory-and-agent-wedge--szeqvmgqjqnhd002.md (100%) rename {.flatbread-efforts => .flatbread-proof}/efforts/eff-flatbread-product-branding--zt7b35sa05kyvhdz.md (100%) rename {.flatbread-efforts => .flatbread-proof}/efforts/eff-local-runtime-and-ownership-loop--g28gfbb0kdrnpe2t.md (100%) rename {.flatbread-efforts => .flatbread-proof}/efforts/eff-proof-and-contributor-operating-system--ahhgtafvdhg4dfve.md (100%) rename {.flatbread-efforts => .flatbread-proof}/efforts/eff-relational-content-foundation--8a8332x4cazgf2k0.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-accepted-decisions-disagree-on-how-blobs-are-cit--z9s360sgahmtjz7h.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-adrs-created-a-second-planning-authority--j1waeg8qh900sqee.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-bounded-status-briefing-protocol-halves-effort-g--ht1jd1hsssf7mv2y.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-citation-and-blob-links-now-stay-within-one-effo--gkyd4dczafebk4fz.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-citation-and-blob-records-now-match-the-current--p6c37v29mx4jjfr2.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-citation-collection-keeps-flatbread-refs-intact--z33ar5vyjxzr7ys0.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-cites-and-citation-blob-skip-same-effort-checks--pts8c8ar72vaevvh.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-crumb-rebrand-refuted-in-review-effort-graph-is--n8kb269z7vz8jhyk.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-dogfooding-the-read-cli-surfaced-three-real-defe--g21hg77x72hdty56.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-exports-strengthen-ownership-but-lack-external-v--fx2qtjpcm8mtpw4f.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-filtered-retrieval-is-94-percent-smaller--qpvz4vch5hygye20.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-generated-read-api-is-useful-but-not-fully-type--vmr23k0t6qx3hk1k.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-getrecord-digests-call-the-same-excerpt-as-brows--q5rbnhpxc697x2dv.md (100%) create mode 100644 .flatbread-proof/findings/fnd-neither-proof-nor-effort-graph-has-been-released--w3ewcvmg3402bm5w.md rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-one-canonical-schema-needs-mapping-profiles--k2yvq5e9rcpsm1s1.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-phase-1-has-no-blockers-but-retains-test-gaps--91h2ncmytj8mq40r.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-pmf-rubric-understates-shipped-validation-and-wa--p04gd8xfknwvz2pe.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-postable-brand-names-favor-trail-over-graph--zzpgaw0kvqtaqmxt.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-primary-onboarding-still-bypasses-the-unified-wa--qqvckprax45hyd2y.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-public-onboarding-now-directs-users-to-watch-mod--cwgqyjjvr6j9gx8n.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-public-readmes-retain-superseded-live-reload-gui--naafmpvt3pcdes4p.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-reference-integrity-is-roadmap-critical--2ss712xpmsfh77xf.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-relation-first-starter-reaches-a-typed-read--8anm4wxbjm9f348z.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-root-readme-roadmap-reference-is-already-removed--w56t43aa10v311hj.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-root-readme-still-links-to-the-deleted-roadmap--k38zmv7pqv7z95ts.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-schemas-need-per-build-isolation--vdjfmtqb0dbjfcqk.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-skill-and-hard-constraint-still-teach-13-mutatio--gvg2btns0q7rp0eq.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-supersession-transitions-decision-state-on-the-r--2m807tcfjz2jz9gt.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-unified-watch-loop-is-the-intended-runtime-contr--t9ghag8yqxgf3p5t.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-versioned-skill-distribution-passes-full-reposit--hm5cy9j2zts96dg4.md (100%) rename {.flatbread-efforts => .flatbread-proof}/findings/fnd-workshop-shortlist-favors-crumb-graph-over-yeast--tv3ydt3wfb3n4y0g.md (100%) rename {.flatbread-efforts => .flatbread-proof}/issues/iss-agents-cannot-obtain-full-record-bodies-through--ekfpcg6hrkwgy287.md (100%) rename {.flatbread-efforts => .flatbread-proof}/issues/iss-define-blocking-decision-semantics--3bj9ph7ppab2c7g2.md (100%) rename {.flatbread-efforts => .flatbread-proof}/issues/iss-implement-blob-collection-and-crumb-graph-cites--g2c7m6j39we5xy3z.md (100%) rename {.flatbread-efforts => .flatbread-proof}/issues/iss-implement-crumb-graph-rename-across-packages-cli--dp6jvt2kafab7m4t.md (100%) rename {.flatbread-efforts => .flatbread-proof}/issues/iss-implement-crumb-trail-rename-across-packages-cli--316rdzpt80sdxkw1.md (100%) create mode 100644 .flatbread-proof/issues/iss-implement-proof-and-oven-rename-across-both-repo--xr02e1wp62ry1ccq.md rename {.flatbread-efforts => .flatbread-proof}/issues/iss-live-reload-and-export-cli-remain-gaps--xe19gzqf654xeyg4.md (100%) rename {.flatbread-efforts => .flatbread-proof}/issues/iss-proof-output-retention-follow-ups-remain-open--4fkjb93v3pey43y0.md (100%) rename {.flatbread-efforts => .flatbread-proof}/issues/iss-skill-scoped-records-filter-example-over-constra--vd0gcnpc9cm6jzjh.md (100%) rename {.flatbread-efforts => .flatbread-proof}/issues/iss-typed-selection-builder-remains-a-product-gap--4zawc913n4gnyfcw.md (100%) rename {.flatbread-efforts => .flatbread-proof}/issues/iss-writedecision-with-supersedes-leaves-the-superse--by624gyf21ex42sv.md (100%) rename {.flatbread-efforts => .flatbread-proof}/risks/rsk-full-transcripts-can-overflow-prompts-and-leak-s--3p7ybk07jqe5w593.md (100%) rename packages/explorer/src/web/app/components/{EffortGraphApp.tsx => ProofApp.tsx} (90%) rename packages/explorer/src/web/presets/{effort-graph => proof}/glyphs.test.ts (100%) rename packages/explorer/src/web/presets/{effort-graph => proof}/glyphs.ts (100%) rename packages/explorer/src/web/presets/{effort-graph => proof}/lifecycle.test.ts (100%) rename packages/explorer/src/web/presets/{effort-graph => proof}/lifecycle.ts (100%) rename packages/explorer/src/web/presets/{effort-graph => proof}/normalize.test.ts (81%) rename packages/explorer/src/web/presets/{effort-graph => proof}/normalize.ts (97%) rename packages/explorer/src/web/presets/{effort-graph => proof}/primitives.ts (98%) rename packages/explorer/src/web/presets/{effort-graph => proof}/query.test.ts (87%) rename packages/explorer/src/web/presets/{effort-graph => proof}/query.ts (94%) rename packages/explorer/src/web/presets/{effort-graph => proof}/types.ts (96%) rename packages/explorer/src/web/presets/{effort-graph/useEffortGraphLive.test.ts => proof/useProofLive.test.ts} (98%) rename packages/explorer/src/web/presets/{effort-graph/useEffortGraphLive.ts => proof/useProofLive.ts} (94%) rename packages/flatbread/src/cli/{effort.test.ts => proof.test.ts} (91%) rename packages/flatbread/src/cli/{effort.ts => proof.ts} (84%) delete mode 100644 packages/flatbread/src/graphql/effortGraphComposition.test.ts rename packages/flatbread/src/graphql/{liveServerEffortGraph.test.ts => liveServerProof.test.ts} (90%) create mode 100644 packages/flatbread/src/graphql/proofComposition.test.ts rename packages/flatbread/src/graphql/{effortGraphComposition.ts => proofComposition.ts} (50%) rename packages/flatbread/src/{effort => proof}/read.ts (96%) rename packages/{effort-graph => proof}/README.md (68%) rename packages/{effort-graph => proof}/package.json (88%) rename packages/{effort-graph => proof}/scripts/pack-skills.mjs (92%) rename packages/{effort-graph => proof}/scripts/sync-skills.mjs (95%) rename packages/{effort-graph => proof}/scripts/watch-skills.mjs (100%) rename packages/{effort-graph => proof}/skills/effort-modeling/CONTEXT-FORMAT.md (91%) rename packages/{effort-graph => proof}/skills/effort-modeling/DECISION-BODY.md (100%) rename packages/{effort-graph => proof}/skills/effort-modeling/SKILL.md (88%) rename packages/{effort-graph => proof}/skills/grill-with-efforts/SKILL.md (90%) rename packages/{effort-graph/skills/effort-graph => proof/skills/proof}/SKILL.md (74%) rename packages/{effort-graph/skills/effort-graph => proof/skills/proof}/glossary.md (92%) rename packages/{effort-graph/skills/effort-graph => proof/skills/proof}/reference.md (77%) rename {.agents/skills/effort-graph => packages/proof/skills/proof}/release.json (68%) rename packages/{effort-graph/skills/effort-graph => proof/skills/proof}/setup.md (75%) rename packages/{effort-graph => proof}/src/__tests__/decision-lifecycle.test.ts (92%) rename packages/{effort-graph => proof}/src/__tests__/digest.test.ts (99%) rename packages/{effort-graph => proof}/src/__tests__/ids.test.ts (93%) rename packages/{effort-graph => proof}/src/__tests__/journal-barrier.test.ts (94%) rename packages/{effort-graph => proof}/src/__tests__/journal-recovery.test.ts (97%) rename packages/{effort-graph => proof}/src/__tests__/live-bridge.test.ts (95%) rename packages/{effort-graph => proof}/src/__tests__/lock.test.ts (86%) rename packages/{effort-graph => proof}/src/__tests__/pack-skills.test.js (89%) rename packages/{effort-graph => proof}/src/__tests__/planner.test.ts (98%) rename packages/{effort-graph => proof}/src/__tests__/preset.test.ts (80%) rename packages/{effort-graph => proof}/src/__tests__/read.test.ts (100%) rename packages/{effort-graph => proof}/src/__tests__/schemas.test.ts (90%) rename packages/{effort-graph => proof}/src/__tests__/skills.test.ts (96%) rename packages/{effort-graph => proof}/src/__tests__/snapshot.test.ts (88%) rename packages/{effort-graph => proof}/src/__tests__/writer.test.ts (92%) rename packages/{effort-graph => proof}/src/decision-lifecycle.ts (70%) rename packages/{effort-graph => proof}/src/digest.ts (99%) rename packages/{effort-graph => proof}/src/errors.ts (52%) rename packages/{effort-graph => proof}/src/frontmatter.ts (100%) rename packages/{effort-graph => proof}/src/ids.ts (100%) rename packages/{effort-graph => proof}/src/index-store.ts (54%) rename packages/{effort-graph => proof}/src/index.ts (88%) rename packages/{effort-graph => proof}/src/journal.ts (94%) rename packages/{effort-graph => proof}/src/journalBarrier.ts (85%) rename packages/{effort-graph => proof}/src/live.ts (84%) rename packages/{effort-graph => proof}/src/lock.ts (94%) rename packages/{effort-graph => proof}/src/planner.ts (81%) rename packages/{effort-graph => proof}/src/preset.ts (94%) rename packages/{effort-graph => proof}/src/read.ts (84%) rename packages/{effort-graph => proof}/src/schemas.ts (97%) rename packages/{effort-graph => proof}/src/snapshot.ts (68%) rename packages/{effort-graph => proof}/src/types.ts (88%) rename packages/{effort-graph => proof}/src/writer.ts (88%) rename packages/{effort-graph => proof}/tsconfig.json (100%) rename packages/{effort-graph => proof}/tsup.config.ts (100%) diff --git a/.agents/skills/effort-modeling/CONTEXT-FORMAT.md b/.agents/skills/effort-modeling/CONTEXT-FORMAT.md index 6f0a6461..088a7fc1 100644 --- a/.agents/skills/effort-modeling/CONTEXT-FORMAT.md +++ b/.agents/skills/effort-modeling/CONTEXT-FORMAT.md @@ -11,4 +11,4 @@ that prevents a common ambiguity. ``` Do not put implementation plans, alternatives, or commitments here. Journal -those in Effort Graph records. +those in Proof records. diff --git a/.agents/skills/effort-modeling/SKILL.md b/.agents/skills/effort-modeling/SKILL.md index fad4dba7..fa9f6504 100644 --- a/.agents/skills/effort-modeling/SKILL.md +++ b/.agents/skills/effort-modeling/SKILL.md @@ -1,20 +1,20 @@ --- name: effort-modeling -description: Sharpen a project's vocabulary and planning through one-question-at-a-time grilling, then journal Decisions, Constraints, Findings, Issues, and Risks into the Flatbread Effort Graph. Use when a plan needs durable reasoning instead of ADRs. +description: Sharpen a project's vocabulary and planning through one-question-at-a-time grilling, then journal Decisions, Constraints, Findings, Issues, and Risks into the Flatbread Proof. Use when a plan needs durable reasoning instead of ADRs. disable-model-invocation: true --- # Effort modeling Use this discipline while a plan or design is being shaped. Store planning -records in the Effort Graph. Keep project terms in a glossary such as +records in the Proof. Keep project terms in a glossary such as `CONTEXT.md` or `docs/glossary.md`. ## Resume before asking -From the project root, use the `effort-graph` skill's bounded reads: +From the project root, use the `proof` skill's bounded reads: -1. `flatbread effort list --status active` +1. `flatbread proof list --status active` 2. For the relevant Effort, inspect open Issues and blocking Decisions. 3. Read a record or digest when a prior conclusion affects the question. @@ -35,8 +35,8 @@ answer, and resolve prerequisite choices before dependent ones. ## Journal the right speech act -Use `flatbread effort write` for the current Effort, following -[the Effort Graph reference](../effort-graph/reference.md): +Use `flatbread proof write` for the current Effort, following +[the Proof reference](../proof/reference.md): - **Finding** — evidence about code, users, or runtime behavior. - **Issue** — a question, defect, gap, or blocker needing attention. diff --git a/.agents/skills/grill-with-efforts/SKILL.md b/.agents/skills/grill-with-efforts/SKILL.md index 16eea0db..0b1f9599 100644 --- a/.agents/skills/grill-with-efforts/SKILL.md +++ b/.agents/skills/grill-with-efforts/SKILL.md @@ -1,6 +1,6 @@ --- name: grill-with-efforts -description: Run a relentless one-question-at-a-time planning interview that sharpens vocabulary and journals durable reasoning into the Flatbread Effort Graph. Use when a plan is fuzzy and needs an Effort Graph trail instead of ADRs. +description: Run a relentless one-question-at-a-time planning interview that sharpens vocabulary and journals durable reasoning into the Flatbread Proof. Use when a plan is fuzzy and needs an Proof trail instead of ADRs. disable-model-invocation: true --- diff --git a/.agents/skills/effort-graph/SKILL.md b/.agents/skills/proof/SKILL.md similarity index 74% rename from .agents/skills/effort-graph/SKILL.md rename to .agents/skills/proof/SKILL.md index 477dc6bc..c711a77d 100644 --- a/.agents/skills/effort-graph/SKILL.md +++ b/.agents/skills/proof/SKILL.md @@ -1,11 +1,11 @@ --- -name: effort-graph -description: Journal reasoning (decisions, findings, issues, constraints, risks, citations, blobs) into a Flatbread Effort Graph and recall it with bounded reads. Use when starting or resuming a thread of work, recording a decision or finding, resolving an issue, checking what is blocking or still open on an effort, or when the user mentions effort graph, journaling, blocking decisions, agent memory, citation, blob, cites, longform, WriteCitation, or WriteBlob. +name: proof +description: Journal reasoning (decisions, findings, issues, constraints, risks, citations, blobs) into a Flatbread Proof and recall it with bounded reads. Use when starting or resuming a thread of work, recording a decision or finding, resolving an issue, checking what is blocking or still open on an effort, or when the user mentions effort graph, journaling, blocking decisions, agent memory, citation, blob, cites, longform, WriteCitation, or WriteBlob. --- -# Effort Graph — agent journaling and recall +# Proof — agent journaling and recall -The Effort Graph stores durable project memory as markdown records in the +The Proof stores durable project memory as markdown records in the repository. It has eight record types: **Effort**, **Issue**, **Finding**, **Decision**, **Constraint**, and **Risk** capture the work and reasoning; **Citation** stores a source or reference; and **Blob** stores attached @@ -24,7 +24,7 @@ errors print JSON to stderr and exit 1. ## First activation Read [setup.md](./setup.md), make the reviewed config and gitignore edits, then -run `flatbread effort bootstrap` followed by `flatbread effort bootstrap --verify`. Bootstrap is report-only and never edits project files. +run `flatbread proof bootstrap` followed by `flatbread proof bootstrap --verify`. Bootstrap is report-only and never edits project files. ## Prerequisites @@ -35,26 +35,26 @@ import { defineConfig, sourceFilesystem, transformerMarkdown, - effortGraphContent, + proofContent, } from 'flatbread'; export default defineConfig({ source: sourceFilesystem(), transformer: transformerMarkdown(), - content: [...effortGraphContent()], + content: [...proofContent()], }); ``` Records live under `/{efforts,issues,findings,decisions,constraints,risks,citations,blobs}/`. The write journal is `/.journal/`; read digests cache under -`.flatbread/effort-graph/read-cache/` (both gitignored). +`.flatbread/proof/read-cache/` (both gitignored). ## Writing (journaling) One command for all 15 mutations — pass the payload as a single JSON argument: ```bash -flatbread effort write '{"type":"WriteDecision","effort":"","title":"...","body":"...","derives_from":[""]}' +flatbread proof write '{"type":"WriteDecision","effort":"","title":"...","body":"...","derives_from":[""]}' ``` Response: `{"generation":"","artifacts":[{"id","path","operation"}],"touched":[...]}`. @@ -79,7 +79,7 @@ Critical semantics: `cites: [""]` when creating an Issue, Finding, Decision, Constraint, or Risk. Both the Citation in `cites` and the Blob in `Citation.blob` must belong to the same Effort as the record that links to - them. Bounded digests omit Blob bodies; use `effort get ` to read + them. Bounded digests omit Blob bodies; use `proof get ` to read one. - When superseding, open the new record's body with a short rollup of what changed and why — reads render ancestors only as one-line checkpoints. @@ -97,29 +97,29 @@ Read on it, or grep it), `served_generation`, page info, and ≤10 executable `hints`. Digests cap at 25 records / one-hop expansion / 50 edges / 64 KiB. Browse digests (`list`, `records`, `relations`, `blocking-decisions`) excerpt -each body at 600 chars / 12 lines (`[…truncated]`). **`effort get` digests +each body at 600 chars / 12 lines (`[…truncated]`). **`proof get` digests always include the full record body** (still subject to the 64 KiB digest byte cap). Zoom in with `get`, then Read/grep that digest — do not open -`.flatbread-efforts/**/*.md` for normal full-body recall. +`.flatbread-proof/**/*.md` for normal full-body recall. ```bash # What's gating this effort? (proposed Decisions deriving from open blocker Issues) -flatbread effort blocking-decisions +flatbread proof blocking-decisions # Resume: discover active Efforts first -flatbread effort list --status active +flatbread proof list --status active # Scoped listing with filters (AND across flags, OR within comma lists). # --status filters Issues and --state filters Decisions, so combining them in # one call ANDs across kinds and matches nothing — query each kind separately. -flatbread effort records --kinds issue --status open --since 2026-07-01T00:00:00Z --limit 10 -flatbread effort records --kinds decision --state proposed --limit 10 +flatbread proof records --kinds issue --status open --since 2026-07-01T00:00:00Z --limit 10 +flatbread proof records --kinds decision --state proposed --limit 10 # One-hop neighbors of a record -flatbread effort relations --relations derives_from,superseded_by +flatbread proof relations --relations derives_from,superseded_by # Single record with full body; --resolve head follows supersession to the tip -flatbread effort get [--resolve head] +flatbread proof get [--resolve head] ``` Flags shared by reads: `--strict-min-generation ` (with optional @@ -127,33 +127,33 @@ Flags shared by reads: `--strict-min-generation ` (with optional (≤25) and `--cursor` (opaque `next_cursor` from a prior page; only valid for the same query at the same generation). -`effort list` is bounded Effort discovery. It defaults to `active`; valid +`proof list` is bounded Effort discovery. It defaults to `active`; valid statuses are exactly `active`, `paused`, `completed`, and `abandoned`. Comma-separated statuses are ORed. Results use the shared `created_at`, then `id` ordering. After discovery, use bounded effort-scoped reads. **Consistency:** reads are eventual by default. Immediately after a write, pass the returned generation as `--strict-min-generation` — you get either -fresh data or an `EFFORT_GRAPH_GENERATION_WAIT_TIMEOUT` error (exit 1), +fresh data or a `PROOF_GENERATION_WAIT_TIMEOUT` error (exit 1), never silently stale results. Do not build polling loops; the wait is server-side. ## Recommended session workflow -1. **Resume / status briefing (bounded fast-path):** `effort list --status active` +1. **Resume / status briefing (bounded fast-path):** `proof list --status active` and trust the returned digest. For each active Effort, run - `effort records --kinds issue,decision` and read each record's - status/state from that one digest. Run `effort blocking-decisions ` + `proof records --kinds issue,decision` and read each record's + status/state from that one digest. Run `proof blocking-decisions ` only for an Effort whose digest shows an open `blocker` Issue — skip it - otherwise. Do not open raw `.flatbread-efforts/**/*.md` for briefing; + otherwise. Do not open raw `.flatbread-proof/**/*.md` for briefing; browse digests are authoritative for status/state. Budget ≈ (1 + number of active Efforts) digest reads. A 12-run experiment across three model families showed this roughly halves recall tool calls with no loss of answer quality (Decision `dec-adopt-a-bounded-status-briefing-fast-path-for-ef--kcw0rw39g3b2ym2h`). 2. **When a browse digest shows `[…truncated]` and you need the body:** run - `flatbread effort get `, then Read/grep that digest (`artifact_path`) - for the full body. Reserve opening `.flatbread-efforts/**/*.md` for rare + `flatbread proof get `, then Read/grep that digest (`artifact_path`) + for the full body. Reserve opening `.flatbread-proof/**/*.md` for rare cases (e.g. digest byte-cap miss on an oversized record), not normal zoom-in. 3. **During work:** when outside material supports a record, save large @@ -165,5 +165,5 @@ server-side. they respond to. 4. **On commitment:** `AcceptDecision` (mind `rejectSiblings`), `ResolveIssue` with `resolvedBy` citing the closing Decision/Findings. -5. Maintenance: `flatbread effort cache prune` deletes digests older than +5. Maintenance: `flatbread proof cache prune` deletes digests older than 24h / over the 100 MiB ceiling. diff --git a/.agents/skills/effort-graph/glossary.md b/.agents/skills/proof/glossary.md similarity index 92% rename from .agents/skills/effort-graph/glossary.md rename to .agents/skills/proof/glossary.md index 7ca533e5..fd002a10 100644 --- a/.agents/skills/effort-graph/glossary.md +++ b/.agents/skills/proof/glossary.md @@ -1,6 +1,6 @@ -# Effort Graph glossary +# Proof glossary -The Effort Graph is persistent, queryable memory for long-horizon software +The Proof is persistent, queryable memory for long-horizon software work. It builds on Flatbread's content vocabulary: each primitive is a Collection, its instances are Records, and cross-primitive references are Relations in frontmatter. @@ -63,7 +63,7 @@ have a proposed/accepted lifecycle. They are ordinary Flatbread content: filesystem-backed today, with other sources such as S3 or a CDN possible later. Records do not cite Blobs directly. Instead, they cite a Citation, which may optionally point to a Blob. Bounded digests omit Blob bodies by -default; use `effort get ` to read the content. +default; use `proof get ` to read the content. ## Edges @@ -74,8 +74,8 @@ writer-materialized reverse projections. `cites` links an Issue, Finding, Decision, Constraint, or Risk to a Citation. It accepts Citation ids only, never Blob ids. A Citation may optionally point -to a Blob. Both links must stay within the same Effort. `flatbread effort relations` follows `cites` links, but does not follow Blob attachments; use -`flatbread effort get ` to read an attachment. +to a Blob. Both links must stay within the same Effort. `flatbread proof relations` follows `cites` links, but does not follow Blob attachments; use +`flatbread proof get ` to read an attachment. New edge vocabulary needs a dogfooded query the existing vocabulary cannot express. diff --git a/.agents/skills/effort-graph/reference.md b/.agents/skills/proof/reference.md similarity index 77% rename from .agents/skills/effort-graph/reference.md rename to .agents/skills/proof/reference.md index 8f544677..7ebeb271 100644 --- a/.agents/skills/effort-graph/reference.md +++ b/.agents/skills/proof/reference.md @@ -1,4 +1,4 @@ -# Effort Graph — full API reference +# Proof — full API reference Ground truth: the installed `flatbread` CLI and this reference (mutations), reads, and configuration examples. Repository implementation files are not @@ -11,7 +11,7 @@ Generated as `---<16-char-crockford>` with prefixes `eff`, identity. Let the writer generate ids; capture them from mutation results (`artifacts[0].id` for creates). -## The 15 mutations (`flatbread effort write ''`) +## The 15 mutations (`flatbread proof write ''`) Common optional fields on all creates: `id`, `created_at` (ISO with offset), `produced_in`, `created_by` (opaque provenance strings). Forward edge fields @@ -95,7 +95,7 @@ the generated schema) and return a `ReadEnvelope`: ```json { "summary": "2 records; proposed 2; complete", - "artifact_path": ".flatbread/effort-graph/read-cache//.md", + "artifact_path": ".flatbread/proof/read-cache//.md", "artifact_sha256": "...", "served_generation": "55", "consistency": { "mode": "eventual|strict", "min_generation": null }, @@ -108,11 +108,11 @@ The digest at `artifact_path` is deterministic markdown: YAML query header, anchor index, per-record sections (selected frontmatter, body, relation lists), one-hop related records, and an edge table. Body policy: -- **`effort get`:** full record body (the normal zoom-in path), including +- **`proof get`:** full record body (the normal zoom-in path), including Blob payloads and Citation bodies (URLs / short notes). - **`list` / `records` / `relations` / `blocking-decisions`:** body excerpt capped at 600 chars / 12 lines (`[…truncated]`). **Blob bodies are omitted** - from these digests — use `effort get` for the payload. Citation bodies + from these digests — use `proof get` for the payload. Citation bodies (usually short) still excerpt normally. Caps: 25 primary records, one hop, 50 edges, 64 KiB; hitting a cap sets @@ -124,12 +124,12 @@ full body via the 600/12 excerpt). ### Commands ```bash -flatbread effort get [--resolve exact|head] [consistency flags] -flatbread effort list [--status active,paused,...] [--limit n] [--cursor c] [consistency flags] -flatbread effort records [--kinds k1,k2] [--state s1,s2] [--status s1,s2] [--kind k1,k2] [--since iso] [--until iso] [--limit n] [--cursor c] [consistency flags] -flatbread effort relations --relations r1,r2 [--limit n] [--cursor c] [consistency flags] -flatbread effort blocking-decisions [consistency flags] -flatbread effort cache prune +flatbread proof get [--resolve exact|head] [consistency flags] +flatbread proof list [--status active,paused,...] [--limit n] [--cursor c] [consistency flags] +flatbread proof records [--kinds k1,k2] [--state s1,s2] [--status s1,s2] [--kind k1,k2] [--since iso] [--until iso] [--limit n] [--cursor c] [consistency flags] +flatbread proof relations --relations r1,r2 [--limit n] [--cursor c] [consistency flags] +flatbread proof blocking-decisions [consistency flags] +flatbread proof cache prune ``` - `--kinds`: `effort|issue|finding|decision|constraint|risk|citation|blob`. @@ -155,20 +155,20 @@ flatbread effort cache prune - `--strict-min-generation `: serve at or after that journal generation, or fail. `--timeout-ms ` bounds the wait (default 3000). -- Errors (stderr JSON, exit 1): `EFFORT_GRAPH_GENERATION_WAIT_TIMEOUT`, - `EFFORT_GRAPH_INVALID_CURSOR` (cursor reused across a different query or +- Errors (stderr JSON, exit 1): `PROOF_GENERATION_WAIT_TIMEOUT`, + `PROOF_INVALID_CURSOR` (cursor reused across a different query or generation). ## Configuration surface -| Option | Where | Default | Notes | -| ---------------- | --------------------------------------------------- | ------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | -| Graph root | `effortGraphContent(root)` in `flatbread.config.js` | `.flatbread-efforts` | All eight collection paths + refs derive from it; the preset must appear complete and unmodified for detection. | -| Config discovery | cwd of the CLI invocation | — | Exactly one `flatbread.config.*` must exist in cwd. | -| Digest cache | fixed | `/.flatbread/effort-graph/read-cache/` | Generation-keyed; gitignore it. `cache prune`: >24h old deleted, then oldest-first to ≤100 MiB. | -| Journal | fixed | `/.journal/` | Writer-owned; gitignored. Never edit. | -| Strict timeout | `--timeout-ms` per read | 3000 ms | | -| Page limit | `--limit` per read | 25 | Hard max 25. | +| Option | Where | Default | Notes | +| ---------------- | --------------------------------------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------- | +| Graph root | `proofContent(root)` in `flatbread.config.js` | `.flatbread-proof` | All eight collection paths + refs derive from it; the preset must appear complete and unmodified for detection. | +| Config discovery | cwd of the CLI invocation | — | Exactly one `flatbread.config.*` must exist in cwd. | +| Digest cache | fixed | `/.flatbread/proof/read-cache/` | Generation-keyed; gitignore it. `cache prune`: >24h old deleted, then oldest-first to ≤100 MiB. | +| Journal | fixed | `/.journal/` | Writer-owned; gitignored. Never edit. | +| Strict timeout | `--timeout-ms` per read | 3000 ms | | +| Page limit | `--limit` per read | 25 | Hard max 25. | ## What not to do @@ -182,4 +182,4 @@ flatbread effort cache prune `produced_in` / `created_by` fields. - Do not put citation metadata objects into `cites` — use Citation records (body/role/optional blob) and bare Citation ids in `cites`. -- Do not expect Blob bodies in list/records digests; zoom with `effort get`. +- Do not expect Blob bodies in list/records digests; zoom with `proof get`. diff --git a/packages/effort-graph/skills/effort-graph/release.json b/.agents/skills/proof/release.json similarity index 68% rename from packages/effort-graph/skills/effort-graph/release.json rename to .agents/skills/proof/release.json index 26e56748..882486f6 100644 --- a/packages/effort-graph/skills/effort-graph/release.json +++ b/.agents/skills/proof/release.json @@ -1,6 +1,6 @@ { "format": 1, "flatbreadVersion": "1.0.0", - "effortGraphVersion": "1.0.0", + "proofVersion": "1.0.0", "gitTag": "v1.0.0" } diff --git a/.agents/skills/effort-graph/setup.md b/.agents/skills/proof/setup.md similarity index 75% rename from .agents/skills/effort-graph/setup.md rename to .agents/skills/proof/setup.md index d961a875..aad39548 100644 --- a/.agents/skills/effort-graph/setup.md +++ b/.agents/skills/proof/setup.md @@ -1,7 +1,7 @@ -# Effort Graph setup +# Proof setup The canonical skill files live in this package. The repository -`.agents/skills/effort-graph/` directory is an exclusively generated +`.agents/skills/proof/` directory is an exclusively generated projection: do not edit it directly, and stale projected files are deleted by `pnpm skills:sync`. @@ -18,20 +18,20 @@ values exactly. `skills-lock.json` is installation provenance/restore data only; do not use its optional ref or version fields as release identity: ```bash -npx skills add https://github.com/FlatbreadLabs/flatbread/tree//packages/effort-graph/skills/effort-graph --skill effort-graph +npx skills add https://github.com/FlatbreadLabs/flatbread/tree//packages/proof/skills/proof --skill proof npm install --save-dev flatbread@ ``` Equivalent commands are: ```bash -pnpm dlx skills add https://github.com/FlatbreadLabs/flatbread/tree//packages/effort-graph/skills/effort-graph --skill effort-graph +pnpm dlx skills add https://github.com/FlatbreadLabs/flatbread/tree//packages/proof/skills/proof --skill proof pnpm add -D flatbread@ -yarn dlx skills add https://github.com/FlatbreadLabs/flatbread/tree//packages/effort-graph/skills/effort-graph --skill effort-graph +yarn dlx skills add https://github.com/FlatbreadLabs/flatbread/tree//packages/proof/skills/proof --skill proof yarn add -D flatbread@ -bunx skills add https://github.com/FlatbreadLabs/flatbread/tree//packages/effort-graph/skills/effort-graph --skill effort-graph +bunx skills add https://github.com/FlatbreadLabs/flatbread/tree//packages/proof/skills/proof --skill proof bun add -d flatbread@ ``` @@ -49,7 +49,7 @@ import { defineConfig, sourceFilesystem, transformerMarkdown, - effortGraphContent, + proofContent, } from 'flatbread'; export default defineConfig({ @@ -57,7 +57,7 @@ export default defineConfig({ transformer: transformerMarkdown(), content: [ // existing entries - ...effortGraphContent(), // or effortGraphContent('path/to/graph') + ...proofContent(), // or proofContent('path/to/graph') ], }); ``` @@ -65,29 +65,29 @@ export default defineConfig({ Add these entries to `.gitignore` (using the selected graph root): ```gitignore -**/.flatbread-efforts/.journal/ -**/.flatbread/effort-graph/read-cache/ +**/.flatbread-proof/.journal/ +**/.flatbread/proof/read-cache/ ``` -For a custom root, replace `.flatbread-efforts` with that root. Review both +For a custom root, replace `.flatbread-proof` with that root. Review both edits before saving; the bootstrap command never creates or rewrites them. ## 3. Verify activation ```bash -flatbread effort bootstrap -flatbread effort bootstrap --verify +flatbread proof bootstrap +flatbread proof bootstrap --verify ``` The second command must print `{"status":"ready",...}` and exit successfully. -On resume, begin with `flatbread effort list --status active`, then use bounded +On resume, begin with `flatbread proof list --status active`, then use bounded effort-scoped reads. Capture mutation `generation` tokens and use `--strict-min-generation` for immediate read-after-write checks; never implement -client polling loops. Semantic changes go through `flatbread effort write`. +client polling loops. Semantic changes go through `flatbread proof write`. ## 4. Open the explorer (optional) -With a complete `effortGraphContent()` preset in config, Flatbread serves the +With a complete `proofContent()` preset in config, Flatbread serves the content-relation explorer automatically (`@flatbread/explorer` ships with `flatbread`): diff --git a/.cursor/agents/flatbread-architecture-planner.md b/.cursor/agents/flatbread-architecture-planner.md index 99fc8365..cb943216 100644 --- a/.cursor/agents/flatbread-architecture-planner.md +++ b/.cursor/agents/flatbread-architecture-planner.md @@ -31,7 +31,7 @@ Keep recommendations aligned with `flatbread-flow-pmf-audit.md` and `flatbread-f ## Output Schema For DAG Handoff -When invoked inside a Proof DAG task (external CLI from https://github.com/FlatbreadLabs/proof, package `@flatbread/proof`), keep the response under ~1800 chars and lead with these exact `##` headings so downstream tasks can find them after the 2000-char upstream stitch cap: +When invoked inside an Oven DAG task (external CLI from https://github.com/FlatbreadLabs/oven, package `@flatbread/oven`), keep the response under ~1800 chars and lead with these exact `##` headings so downstream tasks can find them after the 2000-char upstream stitch cap: ``` ## Current contract diff --git a/.cursor/agents/flatbread-code-review-orchestrator.md b/.cursor/agents/flatbread-code-review-orchestrator.md index c2cf4be5..784883db 100644 --- a/.cursor/agents/flatbread-code-review-orchestrator.md +++ b/.cursor/agents/flatbread-code-review-orchestrator.md @@ -1,13 +1,13 @@ --- name: flatbread-code-review-orchestrator -description: Orchestrates an adversarial code-review DAG over a Flatbread change diff using the external Proof CLI (`@flatbread/proof`) — picks ≤5 reviewer perspectives dynamically from the diff, runs them in a single rank, and merges their findings through a judge that emits chunk-bound structured feedback. +description: Orchestrates an adversarial code-review DAG over a Flatbread change diff using the external Oven CLI (`@flatbread/oven`) — picks ≤5 reviewer perspectives dynamically from the diff, runs them in a single rank, and merges their findings through a judge that emits chunk-bound structured feedback. readonly: true tools: ReadFile, Glob, rg, Shell --- # Flatbread Code-Review Orchestrator -You orchestrate an adversarial code review over a Flatbread change diff. Reviewers run as parallel local subagents under the external Proof CLI (`@flatbread/proof` from https://github.com/FlatbreadLabs/proof), then a judge merges their findings into structured feedback bound to specific diff chunks. You do not edit code. You produce a DAG, run it, and report. +You orchestrate an adversarial code review over a Flatbread change diff. Reviewers run as parallel local subagents under the external Oven CLI (`@flatbread/oven` from https://github.com/FlatbreadLabs/oven), then a judge merges their findings into structured feedback bound to specific diff chunks. You do not edit code. You produce a DAG, run it, and report. Your loyalty is to **correctness** and **wide, robust test coverage**. Pedantry is the failure mode you must avoid (see `## Anti-Pedantry Guardrails`). @@ -91,26 +91,26 @@ Pass the diff to each subtask by **file path reference**, not by inlining. The d ### 4. Run the DAG -Proof is an external package (`@flatbread/proof` from https://github.com/FlatbreadLabs/proof). It is not a workspace package in this monorepo. Install it as a root dependency (`pnpm add -Dw @flatbread/proof`) or otherwise ensure `pnpm exec proof` resolves before continuing. Also set `CURSOR_API_KEY` (or load it from `.env`). +Oven is an external package (`@flatbread/oven` from https://github.com/FlatbreadLabs/oven). It is not a workspace package in this monorepo. Install it as a root dependency (`pnpm add -Dw @flatbread/oven`) or otherwise ensure `pnpm exec oven` resolves before continuing. Also set `CURSOR_API_KEY` (or load it from `.env`). ```bash [ -n "$CURSOR_API_KEY" ] || { [ -f .env ] && set -a && source .env && set +a; } -pnpm exec proof --help >/dev/null || { - echo "Install @flatbread/proof so pnpm exec proof resolves (pnpm add -Dw @flatbread/proof)." +pnpm exec oven --help >/dev/null || { + echo "Install @flatbread/oven so pnpm exec oven resolves (pnpm add -Dw @flatbread/oven)." exit 1 } CANVAS_PATH="$HOME/.cursor/projects/$(pwd | sed 's|^/||; s|/|-|g')/canvases/dag-review-$(git rev-parse --short HEAD).canvas.tsx" -pnpm exec proof --init-only --dag /tmp/review-dag.json --canvas-path "$CANVAS_PATH" +pnpm exec oven --init-only --dag /tmp/review-dag.json --canvas-path "$CANVAS_PATH" open "$CANVAS_PATH" >/dev/null 2>&1 || true ``` Then surface the canvas link in chat using the exact text `Open Canvas`, then run for real: ```bash -pnpm exec proof --dag /tmp/review-dag.json --canvas-path "$CANVAS_PATH" +pnpm exec oven --dag /tmp/review-dag.json --canvas-path "$CANVAS_PATH" ``` ### 5. Report diff --git a/.cursor/dags/README.md b/.cursor/dags/README.md index 41031302..8c30b8e3 100644 --- a/.cursor/dags/README.md +++ b/.cursor/dags/README.md @@ -1,8 +1,8 @@ -# Flatbread Proof DAGs +# Flatbread Oven DAGs -Flatbread-specific DAG JSON for the external Proof CLI -([`@flatbread/proof`](https://github.com/FlatbreadLabs/proof)). These files -belong here, not in the Proof repo: their prompts call monorepo commands such +Flatbread-specific DAG JSON for the external Oven CLI +([`@flatbread/oven`](https://github.com/FlatbreadLabs/oven)). These files +belong here, not in the Oven repo: their prompts call monorepo commands such as `pnpm --filter @flatbread/…` and name Flatbread packages, ports, and agents. ## Layout @@ -15,13 +15,13 @@ as `pnpm --filter @flatbread/…` and name Flatbread packages, ports, and agents ## Prerequisites -1. Install Proof so `pnpm exec proof` resolves from this repo root, for example: +1. Install Oven so `pnpm exec oven` resolves from this repo root, for example: ```bash - pnpm add -Dw @flatbread/proof + pnpm add -Dw @flatbread/oven ``` - Or install from the Proof repository if the package is not on the registry + Or install from the Oven repository if the package is not on the registry you use yet. 2. Set `CURSOR_API_KEY` (or load it from `.env`). @@ -31,8 +31,8 @@ as `pnpm --filter @flatbread/…` and name Flatbread packages, ports, and agents From the Flatbread repo root: ```bash -pnpm exec proof --init-only --dag .cursor/dags/flatbread/dag-schema-migration.json -pnpm exec proof --dag .cursor/dags/flatbread/dag-schema-migration.json +pnpm exec oven --init-only --dag .cursor/dags/flatbread/dag-schema-migration.json +pnpm exec oven --dag .cursor/dags/flatbread/dag-schema-migration.json ``` Replace the DAG path with any file under `flatbread/`. Edit task prompts and diff --git a/.cursor/skills/flatbread-major-migration/SKILL.md b/.cursor/skills/flatbread-major-migration/SKILL.md index f38492a4..a4f787c6 100644 --- a/.cursor/skills/flatbread-major-migration/SKILL.md +++ b/.cursor/skills/flatbread-major-migration/SKILL.md @@ -64,7 +64,7 @@ Treat breaking work as a coordinated monorepo release across `flatbread`, `@flat ## Default DAG Shape -When this skill is run under the external Proof CLI (`@flatbread/proof` from https://github.com/FlatbreadLabs/proof), use the topology in `flatbread-flow-agentic-workflows.md` ("DAG Topology" section). The canonical schema-migration shape — express the DAG via `depends_on` only; the runner computes ranks via Kahn topo-sort. The shape below is what `pnpm exec proof --init-only` produces for the starter template (21 tasks across 7 ranks): +When this skill is run under the external Oven CLI (`@flatbread/oven` from https://github.com/FlatbreadLabs/oven), use the topology in `flatbread-flow-agentic-workflows.md` ("DAG Topology" section). The canonical schema-migration shape — express the DAG via `depends_on` only; the runner computes ranks via Kahn topo-sort. The shape below is what `pnpm exec oven --init-only` produces for the starter template (21 tasks across 7 ranks): ``` rank 1 diag-schema, diag-resolvers, diag-types, diag-codegen, diag-cli, @@ -79,7 +79,7 @@ rank 6 verify-cli (reviewer; b rank 7 browser-verify (browser-verifier; binds port 5057, depends_on impl-examples + verify-cli) ``` -Two ranks bind port `5057` (`verify-cli`, `browser-verify`); they must remain on distinct ranks. A starter JSON lives at `.cursor/dags/flatbread/dag-schema-migration.json`. Edit task contents and `depends_on`, then re-run `--init-only` to confirm the rank shape didn't regress. See `.cursor/dags/README.md` for how to install and run Proof against these DAGs. +Two ranks bind port `5057` (`verify-cli`, `browser-verify`); they must remain on distinct ranks. A starter JSON lives at `.cursor/dags/flatbread/dag-schema-migration.json`. Edit task contents and `depends_on`, then re-run `--init-only` to confirm the rank shape didn't regress. See `.cursor/dags/README.md` for how to install and run Oven against these DAGs. ### Safe parallel cuts diff --git a/.flatbread-efforts/blobs/blb-blob-cite-design-notes--j3jbgc0cymdb2t9g.md b/.flatbread-proof/blobs/blb-blob-cite-design-notes--j3jbgc0cymdb2t9g.md similarity index 100% rename from .flatbread-efforts/blobs/blb-blob-cite-design-notes--j3jbgc0cymdb2t9g.md rename to .flatbread-proof/blobs/blb-blob-cite-design-notes--j3jbgc0cymdb2t9g.md diff --git a/.flatbread-efforts/citations/cit-flatbread-refs-docs-intent--ew3x4qpx1x3c1cy2.md b/.flatbread-proof/citations/cit-flatbread-refs-docs-intent--ew3x4qpx1x3c1cy2.md similarity index 100% rename from .flatbread-efforts/citations/cit-flatbread-refs-docs-intent--ew3x4qpx1x3c1cy2.md rename to .flatbread-proof/citations/cit-flatbread-refs-docs-intent--ew3x4qpx1x3c1cy2.md diff --git a/.flatbread-efforts/citations/cit-local-blob-design-dump--pg7g6qy1td7yjqpy.md b/.flatbread-proof/citations/cit-local-blob-design-dump--pg7g6qy1td7yjqpy.md similarity index 100% rename from .flatbread-efforts/citations/cit-local-blob-design-dump--pg7g6qy1td7yjqpy.md rename to .flatbread-proof/citations/cit-local-blob-design-dump--pg7g6qy1td7yjqpy.md diff --git a/.flatbread-efforts/constraints/con-graphql-is-a-read-interface-not-the-product--4966nqjsnsmwq1fs.md b/.flatbread-proof/constraints/con-graphql-is-a-read-interface-not-the-product--4966nqjsnsmwq1fs.md similarity index 100% rename from .flatbread-efforts/constraints/con-graphql-is-a-read-interface-not-the-product--4966nqjsnsmwq1fs.md rename to .flatbread-proof/constraints/con-graphql-is-a-read-interface-not-the-product--4966nqjsnsmwq1fs.md diff --git a/.flatbread-efforts/constraints/con-mutation-enum-stays-deliberately-small--02k06bxbjwrjfp9x.md b/.flatbread-proof/constraints/con-mutation-enum-stays-deliberately-small--02k06bxbjwrjfp9x.md similarity index 100% rename from .flatbread-efforts/constraints/con-mutation-enum-stays-deliberately-small--02k06bxbjwrjfp9x.md rename to .flatbread-proof/constraints/con-mutation-enum-stays-deliberately-small--02k06bxbjwrjfp9x.md diff --git a/.flatbread-efforts/constraints/con-mutation-enum-stays-deliberately-small--45v1ae3neq26g1rz.md b/.flatbread-proof/constraints/con-mutation-enum-stays-deliberately-small--45v1ae3neq26g1rz.md similarity index 100% rename from .flatbread-efforts/constraints/con-mutation-enum-stays-deliberately-small--45v1ae3neq26g1rz.md rename to .flatbread-proof/constraints/con-mutation-enum-stays-deliberately-small--45v1ae3neq26g1rz.md diff --git a/.flatbread-efforts/constraints/con-prettier-remains-the-markdown-yaml-writer--wrawg3b0hp779hd8.md b/.flatbread-proof/constraints/con-prettier-remains-the-markdown-yaml-writer--wrawg3b0hp779hd8.md similarity index 100% rename from .flatbread-efforts/constraints/con-prettier-remains-the-markdown-yaml-writer--wrawg3b0hp779hd8.md rename to .flatbread-proof/constraints/con-prettier-remains-the-markdown-yaml-writer--wrawg3b0hp779hd8.md diff --git a/.flatbread-efforts/constraints/con-repo-files-are-the-source-of-truth--pnd7w2bs2zvk7ye9.md b/.flatbread-proof/constraints/con-repo-files-are-the-source-of-truth--pnd7w2bs2zvk7ye9.md similarity index 100% rename from .flatbread-efforts/constraints/con-repo-files-are-the-source-of-truth--pnd7w2bs2zvk7ye9.md rename to .flatbread-proof/constraints/con-repo-files-are-the-source-of-truth--pnd7w2bs2zvk7ye9.md diff --git a/.flatbread-efforts/decisions/dec-add-export-cli-and-unified-watch--k9dpxj57yrcv0pbz.md b/.flatbread-proof/decisions/dec-add-export-cli-and-unified-watch--k9dpxj57yrcv0pbz.md similarity index 100% rename from .flatbread-efforts/decisions/dec-add-export-cli-and-unified-watch--k9dpxj57yrcv0pbz.md rename to .flatbread-proof/decisions/dec-add-export-cli-and-unified-watch--k9dpxj57yrcv0pbz.md diff --git a/.flatbread-efforts/decisions/dec-adopt-a-bounded-status-briefing-fast-path-for-ef--kcw0rw39g3b2ym2h.md b/.flatbread-proof/decisions/dec-adopt-a-bounded-status-briefing-fast-path-for-ef--kcw0rw39g3b2ym2h.md similarity index 100% rename from .flatbread-efforts/decisions/dec-adopt-a-bounded-status-briefing-fast-path-for-ef--kcw0rw39g3b2ym2h.md rename to .flatbread-proof/decisions/dec-adopt-a-bounded-status-briefing-fast-path-for-ef--kcw0rw39g3b2ym2h.md diff --git a/.flatbread-efforts/decisions/dec-brand-the-agent-memory-surface-as-crumb-graph--fvskcvagx3a7sybe.md b/.flatbread-proof/decisions/dec-brand-the-agent-memory-surface-as-crumb-graph--fvskcvagx3a7sybe.md similarity index 100% rename from .flatbread-efforts/decisions/dec-brand-the-agent-memory-surface-as-crumb-graph--fvskcvagx3a7sybe.md rename to .flatbread-proof/decisions/dec-brand-the-agent-memory-surface-as-crumb-graph--fvskcvagx3a7sybe.md diff --git a/.flatbread-efforts/decisions/dec-brand-the-agent-memory-surface-as-crumb-trail--tngncepdbwjkh9jc.md b/.flatbread-proof/decisions/dec-brand-the-agent-memory-surface-as-crumb-trail--tngncepdbwjkh9jc.md similarity index 100% rename from .flatbread-efforts/decisions/dec-brand-the-agent-memory-surface-as-crumb-trail--tngncepdbwjkh9jc.md rename to .flatbread-proof/decisions/dec-brand-the-agent-memory-surface-as-crumb-trail--tngncepdbwjkh9jc.md diff --git a/.flatbread-efforts/decisions/dec-bridge-committed-generations-into-live-reads--mc3728t4w1kyqcqq.md b/.flatbread-proof/decisions/dec-bridge-committed-generations-into-live-reads--mc3728t4w1kyqcqq.md similarity index 100% rename from .flatbread-efforts/decisions/dec-bridge-committed-generations-into-live-reads--mc3728t4w1kyqcqq.md rename to .flatbread-proof/decisions/dec-bridge-committed-generations-into-live-reads--mc3728t4w1kyqcqq.md diff --git a/.flatbread-efforts/decisions/dec-canonical-forward-edges-and-journaled-save-or-un--sv9x93svkfz4a98r.md b/.flatbread-proof/decisions/dec-canonical-forward-edges-and-journaled-save-or-un--sv9x93svkfz4a98r.md similarity index 100% rename from .flatbread-efforts/decisions/dec-canonical-forward-edges-and-journaled-save-or-un--sv9x93svkfz4a98r.md rename to .flatbread-proof/decisions/dec-canonical-forward-edges-and-journaled-save-or-un--sv9x93svkfz4a98r.md diff --git a/.flatbread-efforts/decisions/dec-defer-shared-flatbread-write-extraction--xxa1ge2chw6x3xx0.md b/.flatbread-proof/decisions/dec-defer-shared-flatbread-write-extraction--xxa1ge2chw6x3xx0.md similarity index 100% rename from .flatbread-efforts/decisions/dec-defer-shared-flatbread-write-extraction--xxa1ge2chw6x3xx0.md rename to .flatbread-proof/decisions/dec-defer-shared-flatbread-write-extraction--xxa1ge2chw6x3xx0.md diff --git a/.flatbread-efforts/decisions/dec-distribute-the-effort-graph-as-a-versioned-agent--8as4sybr34zcqyqh.md b/.flatbread-proof/decisions/dec-distribute-the-effort-graph-as-a-versioned-agent--8as4sybr34zcqyqh.md similarity index 100% rename from .flatbread-efforts/decisions/dec-distribute-the-effort-graph-as-a-versioned-agent--8as4sybr34zcqyqh.md rename to .flatbread-proof/decisions/dec-distribute-the-effort-graph-as-a-versioned-agent--8as4sybr34zcqyqh.md diff --git a/.flatbread-efforts/decisions/dec-effort-get-digests-always-include-the-full-recor--xs7rnbha3zx8qdj9.md b/.flatbread-proof/decisions/dec-effort-get-digests-always-include-the-full-recor--xs7rnbha3zx8qdj9.md similarity index 100% rename from .flatbread-efforts/decisions/dec-effort-get-digests-always-include-the-full-recor--xs7rnbha3zx8qdj9.md rename to .flatbread-proof/decisions/dec-effort-get-digests-always-include-the-full-recor--xs7rnbha3zx8qdj9.md diff --git a/.flatbread-efforts/decisions/dec-iterate-typed-selection-and-nullability--0khw2zkc51hy230t.md b/.flatbread-proof/decisions/dec-iterate-typed-selection-and-nullability--0khw2zkc51hy230t.md similarity index 100% rename from .flatbread-efforts/decisions/dec-iterate-typed-selection-and-nullability--0khw2zkc51hy230t.md rename to .flatbread-proof/decisions/dec-iterate-typed-selection-and-nullability--0khw2zkc51hy230t.md diff --git a/.flatbread-efforts/decisions/dec-keep-and-extract-validation-api--e96yngmrjqcjdxcn.md b/.flatbread-proof/decisions/dec-keep-and-extract-validation-api--e96yngmrjqcjdxcn.md similarity index 100% rename from .flatbread-efforts/decisions/dec-keep-and-extract-validation-api--e96yngmrjqcjdxcn.md rename to .flatbread-proof/decisions/dec-keep-and-extract-validation-api--e96yngmrjqcjdxcn.md diff --git a/.flatbread-efforts/decisions/dec-keep-dags-acyclic-model-refinement-as-bounded-lo--9ptqq1ck3sax00fq.md b/.flatbread-proof/decisions/dec-keep-dags-acyclic-model-refinement-as-bounded-lo--9ptqq1ck3sax00fq.md similarity index 100% rename from .flatbread-efforts/decisions/dec-keep-dags-acyclic-model-refinement-as-bounded-lo--9ptqq1ck3sax00fq.md rename to .flatbread-proof/decisions/dec-keep-dags-acyclic-model-refinement-as-bounded-lo--9ptqq1ck3sax00fq.md diff --git a/.flatbread-efforts/decisions/dec-keep-effort-graph-as-the-product-name--r5wr2vdjwjs9bs13.md b/.flatbread-proof/decisions/dec-keep-effort-graph-as-the-product-name--r5wr2vdjwjs9bs13.md similarity index 97% rename from .flatbread-efforts/decisions/dec-keep-effort-graph-as-the-product-name--r5wr2vdjwjs9bs13.md rename to .flatbread-proof/decisions/dec-keep-effort-graph-as-the-product-name--r5wr2vdjwjs9bs13.md index 7f0e8542..77defd6b 100644 --- a/.flatbread-efforts/decisions/dec-keep-effort-graph-as-the-product-name--r5wr2vdjwjs9bs13.md +++ b/.flatbread-proof/decisions/dec-keep-effort-graph-as-the-product-name--r5wr2vdjwjs9bs13.md @@ -8,6 +8,8 @@ derives_from: - fnd-crumb-rebrand-refuted-in-review-effort-graph-is--n8kb269z7vz8jhyk supersedes: - dec-brand-the-agent-memory-surface-as-crumb-trail--tngncepdbwjkh9jc +superseded_by: + - dec-name-the-memory-product-proof-and-the-dag-runner--8e1qgp2032607pr2 --- Supersedes Crumb Trail (and, transitively, Crumb Graph). The rebrand line is refuted: **Effort Graph** is the product name for Flatbread's longform agent memory, and crumb naming is dropped entirely rather than retained as a datamodel explainer. diff --git a/.flatbread-efforts/decisions/dec-keep-effort-graph-secondary-with-a-primary-wedge--estattvqnhffm2dc.md b/.flatbread-proof/decisions/dec-keep-effort-graph-secondary-with-a-primary-wedge--estattvqnhffm2dc.md similarity index 100% rename from .flatbread-efforts/decisions/dec-keep-effort-graph-secondary-with-a-primary-wedge--estattvqnhffm2dc.md rename to .flatbread-proof/decisions/dec-keep-effort-graph-secondary-with-a-primary-wedge--estattvqnhffm2dc.md diff --git a/.flatbread-efforts/decisions/dec-keep-relation-first-content-layer--rc3pc0vczp6qhp3t.md b/.flatbread-proof/decisions/dec-keep-relation-first-content-layer--rc3pc0vczp6qhp3t.md similarity index 100% rename from .flatbread-efforts/decisions/dec-keep-relation-first-content-layer--rc3pc0vczp6qhp3t.md rename to .flatbread-proof/decisions/dec-keep-relation-first-content-layer--rc3pc0vczp6qhp3t.md diff --git a/.flatbread-efforts/decisions/dec-lead-flatbread-1-0-with-effort-graph-agent-memor--nhxsqm8sd43s2avx.md b/.flatbread-proof/decisions/dec-lead-flatbread-1-0-with-effort-graph-agent-memor--nhxsqm8sd43s2avx.md similarity index 100% rename from .flatbread-efforts/decisions/dec-lead-flatbread-1-0-with-effort-graph-agent-memor--nhxsqm8sd43s2avx.md rename to .flatbread-proof/decisions/dec-lead-flatbread-1-0-with-effort-graph-agent-memor--nhxsqm8sd43s2avx.md diff --git a/.flatbread-efforts/decisions/dec-make-the-effort-graph-the-planning-authority--gq4xegmc0hhbqjf7.md b/.flatbread-proof/decisions/dec-make-the-effort-graph-the-planning-authority--gq4xegmc0hhbqjf7.md similarity index 100% rename from .flatbread-efforts/decisions/dec-make-the-effort-graph-the-planning-authority--gq4xegmc0hhbqjf7.md rename to .flatbread-proof/decisions/dec-make-the-effort-graph-the-planning-authority--gq4xegmc0hhbqjf7.md diff --git a/.flatbread-efforts/decisions/dec-modernize-reachable-checks-before-replacing-tool--q7xpn1g7rk65xvzj.md b/.flatbread-proof/decisions/dec-modernize-reachable-checks-before-replacing-tool--q7xpn1g7rk65xvzj.md similarity index 100% rename from .flatbread-efforts/decisions/dec-modernize-reachable-checks-before-replacing-tool--q7xpn1g7rk65xvzj.md rename to .flatbread-proof/decisions/dec-modernize-reachable-checks-before-replacing-tool--q7xpn1g7rk65xvzj.md diff --git a/.flatbread-efforts/decisions/dec-name-citeable-longform-payloads-blob--9b11q14fgsx2ytve.md b/.flatbread-proof/decisions/dec-name-citeable-longform-payloads-blob--9b11q14fgsx2ytve.md similarity index 100% rename from .flatbread-efforts/decisions/dec-name-citeable-longform-payloads-blob--9b11q14fgsx2ytve.md rename to .flatbread-proof/decisions/dec-name-citeable-longform-payloads-blob--9b11q14fgsx2ytve.md diff --git a/.flatbread-proof/decisions/dec-name-the-memory-product-proof-and-the-dag-runner--8e1qgp2032607pr2.md b/.flatbread-proof/decisions/dec-name-the-memory-product-proof-and-the-dag-runner--8e1qgp2032607pr2.md new file mode 100644 index 00000000..3bcdf13b --- /dev/null +++ b/.flatbread-proof/decisions/dec-name-the-memory-product-proof-and-the-dag-runner--8e1qgp2032607pr2.md @@ -0,0 +1,47 @@ +--- +id: dec-name-the-memory-product-proof-and-the-dag-runner--8e1qgp2032607pr2 +effort: eff-flatbread-product-branding--zt7b35sa05kyvhdz +title: Name the memory product Proof and the DAG runner Oven +state: accepted +created_at: '2026-08-12T17:27:32.577Z' +derives_from: + - fnd-neither-proof-nor-effort-graph-has-been-released--w3ewcvmg3402bm5w + - fnd-workshop-shortlist-favors-crumb-graph-over-yeast--tv3ydt3wfb3n4y0g +supersedes: + - dec-keep-effort-graph-as-the-product-name--r5wr2vdjwjs9bs13 +--- + +Supersedes “Keep Effort Graph as the product name.” Proof moves from the DAG runner to the auditable memory graph. The runner becomes Oven. Identifiers move in the same change. Effort stays the primitive. + +## Context + +Effort Graph is accurate for Effort-scoped records but reads as a subsystem label. Proof means evidence you can audit, which matches journaled Findings, Decisions, and bounded recall. The DAG runner took that name first (baking “proof” / a peer brand), so earlier workshops treated it as taken and tried Crumb Graph / Crumb Trail, then reversed those because the metaphor failed and the identifier rename was deferred. + +The reversal criteria on the superseded Decision now hold: a candidate name wins, and this Decision commits to renaming packages, CLI, paths, and skills in the same sweep rather than branding-only. Neither product has been released, so the sweep is a clean cut, not a major migration. + +## Decision + +1. Brand Flatbread’s longform agent memory as **Proof**. Keep **Effort** as the record type, the `effort` field, `eff-*` ids, and the `efforts/` collection folder. Do not keep Effort Graph as a product name or documented alias. +2. Brand the DAG task runner as **Oven**. Do not leave “proof” in the runner’s package, bin, skill, log prefix, or default state directory. +3. Move identifiers in one sweep. Mapping: runner `@flatbread/proof` / `proof` / `proof-supervisor` / `FlatbreadLabs/proof` / skill `proof` / `.proof/` / `.flatbread/artifacts/` → `@flatbread/oven` / `oven` / `oven-supervisor` / `FlatbreadLabs/oven` / skill `oven` / `.oven/` / `.oven/artifacts/`. Memory `@flatbread/effort-graph` / `flatbread effort` / skill `effort-graph` / `effortGraphContent` / `EFFORT_GRAPH_*` / `.flatbread-efforts/` / `.flatbread/effort-graph/` → `@flatbread/proof` / `flatbread proof` / skill `proof` / `proofContent` / `PROOF_*` / `.flatbread-proof/` / `.flatbread/proof/`. +4. Vacate the runner’s `proof` identifiers before the memory product takes them. In this monorepo, rename `.cursor/skills/proof` (runner) to `oven` before the memory skill becomes `proof`. +5. Keep skills `effort-modeling` and `grill-with-efforts`. Keep `.journal/`. `git mv` the dogfood graph root; do not rewrite historical record ids. +6. GitHub: rename `FlatbreadLabs/proof` to `FlatbreadLabs/oven`. Memory stays in `FlatbreadLabs/flatbread`. Do not try to reuse the redirected GitHub name for memory. npm: publish Oven, then publish memory as `@flatbread/proof` — no deprecation window, because nothing has been released. + +## Alternatives considered + +- **Keep Effort Graph; leave the runner as Proof.** Rejected: Proof fits the memory product; Effort Graph underplays brandability. +- **Crumb Graph / Crumb Trail.** Already refuted; crumbs read as leftovers and collide with UI breadcrumbs. +- **Rank / Bake / restore dag-task-runner for the runner.** Rank collides with search ranking; Bake collides with JS “build”; the old skill name is accurate but not a peer brand. Oven is short, unleavened, and names the place work cooks. +- **Brand-only rename, defer packages/CLI/paths.** Rejected: that is how Crumb Graph failed. This Decision is the identifier map. +- **Treat the rename as a 1.0 major migration with npm cooling-off.** Rejected: neither product has been released. + +## Consequences + +- Docs, skills, CLI, packages, error codes, and on-disk roots say Proof for memory and Oven for the runner. +- Implementation is in scope now, not deferred. Follow the sweep handoff for touchpoints. +- Yeast names stay off the table. Weave stays the merge driver. + +## Reversal criteria + +Revisit if users read Proof as the DAG runner after the sweep, if Oven fails to be found by agents looking for a task DAG, or if Effort-as-primitive plus Proof-as-product still forces a second vocabulary. Any later rename must move identifiers in the same Decision. diff --git a/.flatbread-efforts/decisions/dec-route-agent-reads-through-the-flatbread-query-en--476qb9qk878yfg62.md b/.flatbread-proof/decisions/dec-route-agent-reads-through-the-flatbread-query-en--476qb9qk878yfg62.md similarity index 100% rename from .flatbread-efforts/decisions/dec-route-agent-reads-through-the-flatbread-query-en--476qb9qk878yfg62.md rename to .flatbread-proof/decisions/dec-route-agent-reads-through-the-flatbread-query-en--476qb9qk878yfg62.md diff --git a/.flatbread-efforts/decisions/dec-separate-execution-and-display-planes--spm2ckxvdsch6h9m.md b/.flatbread-proof/decisions/dec-separate-execution-and-display-planes--spm2ckxvdsch6h9m.md similarity index 100% rename from .flatbread-efforts/decisions/dec-separate-execution-and-display-planes--spm2ckxvdsch6h9m.md rename to .flatbread-proof/decisions/dec-separate-execution-and-display-planes--spm2ckxvdsch6h9m.md diff --git a/.flatbread-efforts/decisions/dec-ship-citation-collection-with-optional-blob--fyga3x876n7rcnmn.md b/.flatbread-proof/decisions/dec-ship-citation-collection-with-optional-blob--fyga3x876n7rcnmn.md similarity index 100% rename from .flatbread-efforts/decisions/dec-ship-citation-collection-with-optional-blob--fyga3x876n7rcnmn.md rename to .flatbread-proof/decisions/dec-ship-citation-collection-with-optional-blob--fyga3x876n7rcnmn.md diff --git a/.flatbread-efforts/decisions/dec-specify-blockingdecisions-over-effort-scoped-edg--pxwaenyra0aa365j.md b/.flatbread-proof/decisions/dec-specify-blockingdecisions-over-effort-scoped-edg--pxwaenyra0aa365j.md similarity index 100% rename from .flatbread-efforts/decisions/dec-specify-blockingdecisions-over-effort-scoped-edg--pxwaenyra0aa365j.md rename to .flatbread-proof/decisions/dec-specify-blockingdecisions-over-effort-scoped-edg--pxwaenyra0aa365j.md diff --git a/.flatbread-efforts/decisions/dec-store-graph-artifacts-in-repo-by-default--xxpgwm9sv25j07z7.md b/.flatbread-proof/decisions/dec-store-graph-artifacts-in-repo-by-default--xxpgwm9sv25j07z7.md similarity index 100% rename from .flatbread-efforts/decisions/dec-store-graph-artifacts-in-repo-by-default--xxpgwm9sv25j07z7.md rename to .flatbread-proof/decisions/dec-store-graph-artifacts-in-repo-by-default--xxpgwm9sv25j07z7.md diff --git a/.flatbread-efforts/decisions/dec-use-isolated-schema-factories-without-a-cache--8bn823dg29yfvbzv.md b/.flatbread-proof/decisions/dec-use-isolated-schema-factories-without-a-cache--8bn823dg29yfvbzv.md similarity index 100% rename from .flatbread-efforts/decisions/dec-use-isolated-schema-factories-without-a-cache--8bn823dg29yfvbzv.md rename to .flatbread-proof/decisions/dec-use-isolated-schema-factories-without-a-cache--8bn823dg29yfvbzv.md diff --git a/.flatbread-efforts/decisions/dec-use-prefixed-random-ids-with-reviewable-slugs--xdg764ejat1kacd2.md b/.flatbread-proof/decisions/dec-use-prefixed-random-ids-with-reviewable-slugs--xdg764ejat1kacd2.md similarity index 100% rename from .flatbread-efforts/decisions/dec-use-prefixed-random-ids-with-reviewable-slugs--xdg764ejat1kacd2.md rename to .flatbread-proof/decisions/dec-use-prefixed-random-ids-with-reviewable-slugs--xdg764ejat1kacd2.md diff --git a/.flatbread-efforts/decisions/dec-use-profiles-not-separate-schemas--27p0wakkyxj0kfc1.md b/.flatbread-proof/decisions/dec-use-profiles-not-separate-schemas--27p0wakkyxj0kfc1.md similarity index 100% rename from .flatbread-efforts/decisions/dec-use-profiles-not-separate-schemas--27p0wakkyxj0kfc1.md rename to .flatbread-proof/decisions/dec-use-profiles-not-separate-schemas--27p0wakkyxj0kfc1.md diff --git a/.flatbread-efforts/decisions/dec-use-semantic-mutations-and-a-standalone-writer--2d0m3tkqhad4yyhr.md b/.flatbread-proof/decisions/dec-use-semantic-mutations-and-a-standalone-writer--2d0m3tkqhad4yyhr.md similarity index 100% rename from .flatbread-efforts/decisions/dec-use-semantic-mutations-and-a-standalone-writer--2d0m3tkqhad4yyhr.md rename to .flatbread-proof/decisions/dec-use-semantic-mutations-and-a-standalone-writer--2d0m3tkqhad4yyhr.md diff --git a/.flatbread-efforts/efforts/eff-effort-graph-memory-and-agent-wedge--szeqvmgqjqnhd002.md b/.flatbread-proof/efforts/eff-effort-graph-memory-and-agent-wedge--szeqvmgqjqnhd002.md similarity index 100% rename from .flatbread-efforts/efforts/eff-effort-graph-memory-and-agent-wedge--szeqvmgqjqnhd002.md rename to .flatbread-proof/efforts/eff-effort-graph-memory-and-agent-wedge--szeqvmgqjqnhd002.md diff --git a/.flatbread-efforts/efforts/eff-flatbread-product-branding--zt7b35sa05kyvhdz.md b/.flatbread-proof/efforts/eff-flatbread-product-branding--zt7b35sa05kyvhdz.md similarity index 100% rename from .flatbread-efforts/efforts/eff-flatbread-product-branding--zt7b35sa05kyvhdz.md rename to .flatbread-proof/efforts/eff-flatbread-product-branding--zt7b35sa05kyvhdz.md diff --git a/.flatbread-efforts/efforts/eff-local-runtime-and-ownership-loop--g28gfbb0kdrnpe2t.md b/.flatbread-proof/efforts/eff-local-runtime-and-ownership-loop--g28gfbb0kdrnpe2t.md similarity index 100% rename from .flatbread-efforts/efforts/eff-local-runtime-and-ownership-loop--g28gfbb0kdrnpe2t.md rename to .flatbread-proof/efforts/eff-local-runtime-and-ownership-loop--g28gfbb0kdrnpe2t.md diff --git a/.flatbread-efforts/efforts/eff-proof-and-contributor-operating-system--ahhgtafvdhg4dfve.md b/.flatbread-proof/efforts/eff-proof-and-contributor-operating-system--ahhgtafvdhg4dfve.md similarity index 100% rename from .flatbread-efforts/efforts/eff-proof-and-contributor-operating-system--ahhgtafvdhg4dfve.md rename to .flatbread-proof/efforts/eff-proof-and-contributor-operating-system--ahhgtafvdhg4dfve.md diff --git a/.flatbread-efforts/efforts/eff-relational-content-foundation--8a8332x4cazgf2k0.md b/.flatbread-proof/efforts/eff-relational-content-foundation--8a8332x4cazgf2k0.md similarity index 100% rename from .flatbread-efforts/efforts/eff-relational-content-foundation--8a8332x4cazgf2k0.md rename to .flatbread-proof/efforts/eff-relational-content-foundation--8a8332x4cazgf2k0.md diff --git a/.flatbread-efforts/findings/fnd-accepted-decisions-disagree-on-how-blobs-are-cit--z9s360sgahmtjz7h.md b/.flatbread-proof/findings/fnd-accepted-decisions-disagree-on-how-blobs-are-cit--z9s360sgahmtjz7h.md similarity index 100% rename from .flatbread-efforts/findings/fnd-accepted-decisions-disagree-on-how-blobs-are-cit--z9s360sgahmtjz7h.md rename to .flatbread-proof/findings/fnd-accepted-decisions-disagree-on-how-blobs-are-cit--z9s360sgahmtjz7h.md diff --git a/.flatbread-efforts/findings/fnd-adrs-created-a-second-planning-authority--j1waeg8qh900sqee.md b/.flatbread-proof/findings/fnd-adrs-created-a-second-planning-authority--j1waeg8qh900sqee.md similarity index 100% rename from .flatbread-efforts/findings/fnd-adrs-created-a-second-planning-authority--j1waeg8qh900sqee.md rename to .flatbread-proof/findings/fnd-adrs-created-a-second-planning-authority--j1waeg8qh900sqee.md diff --git a/.flatbread-efforts/findings/fnd-bounded-status-briefing-protocol-halves-effort-g--ht1jd1hsssf7mv2y.md b/.flatbread-proof/findings/fnd-bounded-status-briefing-protocol-halves-effort-g--ht1jd1hsssf7mv2y.md similarity index 100% rename from .flatbread-efforts/findings/fnd-bounded-status-briefing-protocol-halves-effort-g--ht1jd1hsssf7mv2y.md rename to .flatbread-proof/findings/fnd-bounded-status-briefing-protocol-halves-effort-g--ht1jd1hsssf7mv2y.md diff --git a/.flatbread-efforts/findings/fnd-citation-and-blob-links-now-stay-within-one-effo--gkyd4dczafebk4fz.md b/.flatbread-proof/findings/fnd-citation-and-blob-links-now-stay-within-one-effo--gkyd4dczafebk4fz.md similarity index 100% rename from .flatbread-efforts/findings/fnd-citation-and-blob-links-now-stay-within-one-effo--gkyd4dczafebk4fz.md rename to .flatbread-proof/findings/fnd-citation-and-blob-links-now-stay-within-one-effo--gkyd4dczafebk4fz.md diff --git a/.flatbread-efforts/findings/fnd-citation-and-blob-records-now-match-the-current--p6c37v29mx4jjfr2.md b/.flatbread-proof/findings/fnd-citation-and-blob-records-now-match-the-current--p6c37v29mx4jjfr2.md similarity index 100% rename from .flatbread-efforts/findings/fnd-citation-and-blob-records-now-match-the-current--p6c37v29mx4jjfr2.md rename to .flatbread-proof/findings/fnd-citation-and-blob-records-now-match-the-current--p6c37v29mx4jjfr2.md diff --git a/.flatbread-efforts/findings/fnd-citation-collection-keeps-flatbread-refs-intact--z33ar5vyjxzr7ys0.md b/.flatbread-proof/findings/fnd-citation-collection-keeps-flatbread-refs-intact--z33ar5vyjxzr7ys0.md similarity index 100% rename from .flatbread-efforts/findings/fnd-citation-collection-keeps-flatbread-refs-intact--z33ar5vyjxzr7ys0.md rename to .flatbread-proof/findings/fnd-citation-collection-keeps-flatbread-refs-intact--z33ar5vyjxzr7ys0.md diff --git a/.flatbread-efforts/findings/fnd-cites-and-citation-blob-skip-same-effort-checks--pts8c8ar72vaevvh.md b/.flatbread-proof/findings/fnd-cites-and-citation-blob-skip-same-effort-checks--pts8c8ar72vaevvh.md similarity index 100% rename from .flatbread-efforts/findings/fnd-cites-and-citation-blob-skip-same-effort-checks--pts8c8ar72vaevvh.md rename to .flatbread-proof/findings/fnd-cites-and-citation-blob-skip-same-effort-checks--pts8c8ar72vaevvh.md diff --git a/.flatbread-efforts/findings/fnd-crumb-rebrand-refuted-in-review-effort-graph-is--n8kb269z7vz8jhyk.md b/.flatbread-proof/findings/fnd-crumb-rebrand-refuted-in-review-effort-graph-is--n8kb269z7vz8jhyk.md similarity index 100% rename from .flatbread-efforts/findings/fnd-crumb-rebrand-refuted-in-review-effort-graph-is--n8kb269z7vz8jhyk.md rename to .flatbread-proof/findings/fnd-crumb-rebrand-refuted-in-review-effort-graph-is--n8kb269z7vz8jhyk.md diff --git a/.flatbread-efforts/findings/fnd-dogfooding-the-read-cli-surfaced-three-real-defe--g21hg77x72hdty56.md b/.flatbread-proof/findings/fnd-dogfooding-the-read-cli-surfaced-three-real-defe--g21hg77x72hdty56.md similarity index 100% rename from .flatbread-efforts/findings/fnd-dogfooding-the-read-cli-surfaced-three-real-defe--g21hg77x72hdty56.md rename to .flatbread-proof/findings/fnd-dogfooding-the-read-cli-surfaced-three-real-defe--g21hg77x72hdty56.md diff --git a/.flatbread-efforts/findings/fnd-exports-strengthen-ownership-but-lack-external-v--fx2qtjpcm8mtpw4f.md b/.flatbread-proof/findings/fnd-exports-strengthen-ownership-but-lack-external-v--fx2qtjpcm8mtpw4f.md similarity index 100% rename from .flatbread-efforts/findings/fnd-exports-strengthen-ownership-but-lack-external-v--fx2qtjpcm8mtpw4f.md rename to .flatbread-proof/findings/fnd-exports-strengthen-ownership-but-lack-external-v--fx2qtjpcm8mtpw4f.md diff --git a/.flatbread-efforts/findings/fnd-filtered-retrieval-is-94-percent-smaller--qpvz4vch5hygye20.md b/.flatbread-proof/findings/fnd-filtered-retrieval-is-94-percent-smaller--qpvz4vch5hygye20.md similarity index 100% rename from .flatbread-efforts/findings/fnd-filtered-retrieval-is-94-percent-smaller--qpvz4vch5hygye20.md rename to .flatbread-proof/findings/fnd-filtered-retrieval-is-94-percent-smaller--qpvz4vch5hygye20.md diff --git a/.flatbread-efforts/findings/fnd-generated-read-api-is-useful-but-not-fully-type--vmr23k0t6qx3hk1k.md b/.flatbread-proof/findings/fnd-generated-read-api-is-useful-but-not-fully-type--vmr23k0t6qx3hk1k.md similarity index 100% rename from .flatbread-efforts/findings/fnd-generated-read-api-is-useful-but-not-fully-type--vmr23k0t6qx3hk1k.md rename to .flatbread-proof/findings/fnd-generated-read-api-is-useful-but-not-fully-type--vmr23k0t6qx3hk1k.md diff --git a/.flatbread-efforts/findings/fnd-getrecord-digests-call-the-same-excerpt-as-brows--q5rbnhpxc697x2dv.md b/.flatbread-proof/findings/fnd-getrecord-digests-call-the-same-excerpt-as-brows--q5rbnhpxc697x2dv.md similarity index 100% rename from .flatbread-efforts/findings/fnd-getrecord-digests-call-the-same-excerpt-as-brows--q5rbnhpxc697x2dv.md rename to .flatbread-proof/findings/fnd-getrecord-digests-call-the-same-excerpt-as-brows--q5rbnhpxc697x2dv.md diff --git a/.flatbread-proof/findings/fnd-neither-proof-nor-effort-graph-has-been-released--w3ewcvmg3402bm5w.md b/.flatbread-proof/findings/fnd-neither-proof-nor-effort-graph-has-been-released--w3ewcvmg3402bm5w.md new file mode 100644 index 00000000..cc0bb6f1 --- /dev/null +++ b/.flatbread-proof/findings/fnd-neither-proof-nor-effort-graph-has-been-released--w3ewcvmg3402bm5w.md @@ -0,0 +1,11 @@ +--- +id: fnd-neither-proof-nor-effort-graph-has-been-released--w3ewcvmg3402bm5w +effort: eff-flatbread-product-branding--zt7b35sa05kyvhdz +title: Neither Proof nor Effort Graph has been released +kind: measurement +created_at: '2026-08-12T17:27:19.564Z' +--- + +Owner confirmation: the DAG runner (`@flatbread/proof`, GitHub FlatbreadLabs/proof) and the agent-memory package (`@flatbread/effort-graph`) have not shipped to external users. In-repo CHANGELOG 1.0 copy describes both packages, but that is not a public release. + +Consequence for naming: identifier reuse is a clean cut. There is no npm deprecation window, no major-version compatibility story, and no need to keep `@flatbread/proof` meaning the runner for existing lockfiles. GitHub may still redirect if the runner repo is renamed; memory stays in the Flatbread monorepo and does not need that GitHub name. diff --git a/.flatbread-efforts/findings/fnd-one-canonical-schema-needs-mapping-profiles--k2yvq5e9rcpsm1s1.md b/.flatbread-proof/findings/fnd-one-canonical-schema-needs-mapping-profiles--k2yvq5e9rcpsm1s1.md similarity index 100% rename from .flatbread-efforts/findings/fnd-one-canonical-schema-needs-mapping-profiles--k2yvq5e9rcpsm1s1.md rename to .flatbread-proof/findings/fnd-one-canonical-schema-needs-mapping-profiles--k2yvq5e9rcpsm1s1.md diff --git a/.flatbread-efforts/findings/fnd-phase-1-has-no-blockers-but-retains-test-gaps--91h2ncmytj8mq40r.md b/.flatbread-proof/findings/fnd-phase-1-has-no-blockers-but-retains-test-gaps--91h2ncmytj8mq40r.md similarity index 100% rename from .flatbread-efforts/findings/fnd-phase-1-has-no-blockers-but-retains-test-gaps--91h2ncmytj8mq40r.md rename to .flatbread-proof/findings/fnd-phase-1-has-no-blockers-but-retains-test-gaps--91h2ncmytj8mq40r.md diff --git a/.flatbread-efforts/findings/fnd-pmf-rubric-understates-shipped-validation-and-wa--p04gd8xfknwvz2pe.md b/.flatbread-proof/findings/fnd-pmf-rubric-understates-shipped-validation-and-wa--p04gd8xfknwvz2pe.md similarity index 100% rename from .flatbread-efforts/findings/fnd-pmf-rubric-understates-shipped-validation-and-wa--p04gd8xfknwvz2pe.md rename to .flatbread-proof/findings/fnd-pmf-rubric-understates-shipped-validation-and-wa--p04gd8xfknwvz2pe.md diff --git a/.flatbread-efforts/findings/fnd-postable-brand-names-favor-trail-over-graph--zzpgaw0kvqtaqmxt.md b/.flatbread-proof/findings/fnd-postable-brand-names-favor-trail-over-graph--zzpgaw0kvqtaqmxt.md similarity index 100% rename from .flatbread-efforts/findings/fnd-postable-brand-names-favor-trail-over-graph--zzpgaw0kvqtaqmxt.md rename to .flatbread-proof/findings/fnd-postable-brand-names-favor-trail-over-graph--zzpgaw0kvqtaqmxt.md diff --git a/.flatbread-efforts/findings/fnd-primary-onboarding-still-bypasses-the-unified-wa--qqvckprax45hyd2y.md b/.flatbread-proof/findings/fnd-primary-onboarding-still-bypasses-the-unified-wa--qqvckprax45hyd2y.md similarity index 100% rename from .flatbread-efforts/findings/fnd-primary-onboarding-still-bypasses-the-unified-wa--qqvckprax45hyd2y.md rename to .flatbread-proof/findings/fnd-primary-onboarding-still-bypasses-the-unified-wa--qqvckprax45hyd2y.md diff --git a/.flatbread-efforts/findings/fnd-public-onboarding-now-directs-users-to-watch-mod--cwgqyjjvr6j9gx8n.md b/.flatbread-proof/findings/fnd-public-onboarding-now-directs-users-to-watch-mod--cwgqyjjvr6j9gx8n.md similarity index 100% rename from .flatbread-efforts/findings/fnd-public-onboarding-now-directs-users-to-watch-mod--cwgqyjjvr6j9gx8n.md rename to .flatbread-proof/findings/fnd-public-onboarding-now-directs-users-to-watch-mod--cwgqyjjvr6j9gx8n.md diff --git a/.flatbread-efforts/findings/fnd-public-readmes-retain-superseded-live-reload-gui--naafmpvt3pcdes4p.md b/.flatbread-proof/findings/fnd-public-readmes-retain-superseded-live-reload-gui--naafmpvt3pcdes4p.md similarity index 100% rename from .flatbread-efforts/findings/fnd-public-readmes-retain-superseded-live-reload-gui--naafmpvt3pcdes4p.md rename to .flatbread-proof/findings/fnd-public-readmes-retain-superseded-live-reload-gui--naafmpvt3pcdes4p.md diff --git a/.flatbread-efforts/findings/fnd-reference-integrity-is-roadmap-critical--2ss712xpmsfh77xf.md b/.flatbread-proof/findings/fnd-reference-integrity-is-roadmap-critical--2ss712xpmsfh77xf.md similarity index 100% rename from .flatbread-efforts/findings/fnd-reference-integrity-is-roadmap-critical--2ss712xpmsfh77xf.md rename to .flatbread-proof/findings/fnd-reference-integrity-is-roadmap-critical--2ss712xpmsfh77xf.md diff --git a/.flatbread-efforts/findings/fnd-relation-first-starter-reaches-a-typed-read--8anm4wxbjm9f348z.md b/.flatbread-proof/findings/fnd-relation-first-starter-reaches-a-typed-read--8anm4wxbjm9f348z.md similarity index 100% rename from .flatbread-efforts/findings/fnd-relation-first-starter-reaches-a-typed-read--8anm4wxbjm9f348z.md rename to .flatbread-proof/findings/fnd-relation-first-starter-reaches-a-typed-read--8anm4wxbjm9f348z.md diff --git a/.flatbread-efforts/findings/fnd-root-readme-roadmap-reference-is-already-removed--w56t43aa10v311hj.md b/.flatbread-proof/findings/fnd-root-readme-roadmap-reference-is-already-removed--w56t43aa10v311hj.md similarity index 100% rename from .flatbread-efforts/findings/fnd-root-readme-roadmap-reference-is-already-removed--w56t43aa10v311hj.md rename to .flatbread-proof/findings/fnd-root-readme-roadmap-reference-is-already-removed--w56t43aa10v311hj.md diff --git a/.flatbread-efforts/findings/fnd-root-readme-still-links-to-the-deleted-roadmap--k38zmv7pqv7z95ts.md b/.flatbread-proof/findings/fnd-root-readme-still-links-to-the-deleted-roadmap--k38zmv7pqv7z95ts.md similarity index 100% rename from .flatbread-efforts/findings/fnd-root-readme-still-links-to-the-deleted-roadmap--k38zmv7pqv7z95ts.md rename to .flatbread-proof/findings/fnd-root-readme-still-links-to-the-deleted-roadmap--k38zmv7pqv7z95ts.md diff --git a/.flatbread-efforts/findings/fnd-schemas-need-per-build-isolation--vdjfmtqb0dbjfcqk.md b/.flatbread-proof/findings/fnd-schemas-need-per-build-isolation--vdjfmtqb0dbjfcqk.md similarity index 100% rename from .flatbread-efforts/findings/fnd-schemas-need-per-build-isolation--vdjfmtqb0dbjfcqk.md rename to .flatbread-proof/findings/fnd-schemas-need-per-build-isolation--vdjfmtqb0dbjfcqk.md diff --git a/.flatbread-efforts/findings/fnd-skill-and-hard-constraint-still-teach-13-mutatio--gvg2btns0q7rp0eq.md b/.flatbread-proof/findings/fnd-skill-and-hard-constraint-still-teach-13-mutatio--gvg2btns0q7rp0eq.md similarity index 100% rename from .flatbread-efforts/findings/fnd-skill-and-hard-constraint-still-teach-13-mutatio--gvg2btns0q7rp0eq.md rename to .flatbread-proof/findings/fnd-skill-and-hard-constraint-still-teach-13-mutatio--gvg2btns0q7rp0eq.md diff --git a/.flatbread-efforts/findings/fnd-supersession-transitions-decision-state-on-the-r--2m807tcfjz2jz9gt.md b/.flatbread-proof/findings/fnd-supersession-transitions-decision-state-on-the-r--2m807tcfjz2jz9gt.md similarity index 100% rename from .flatbread-efforts/findings/fnd-supersession-transitions-decision-state-on-the-r--2m807tcfjz2jz9gt.md rename to .flatbread-proof/findings/fnd-supersession-transitions-decision-state-on-the-r--2m807tcfjz2jz9gt.md diff --git a/.flatbread-efforts/findings/fnd-unified-watch-loop-is-the-intended-runtime-contr--t9ghag8yqxgf3p5t.md b/.flatbread-proof/findings/fnd-unified-watch-loop-is-the-intended-runtime-contr--t9ghag8yqxgf3p5t.md similarity index 100% rename from .flatbread-efforts/findings/fnd-unified-watch-loop-is-the-intended-runtime-contr--t9ghag8yqxgf3p5t.md rename to .flatbread-proof/findings/fnd-unified-watch-loop-is-the-intended-runtime-contr--t9ghag8yqxgf3p5t.md diff --git a/.flatbread-efforts/findings/fnd-versioned-skill-distribution-passes-full-reposit--hm5cy9j2zts96dg4.md b/.flatbread-proof/findings/fnd-versioned-skill-distribution-passes-full-reposit--hm5cy9j2zts96dg4.md similarity index 100% rename from .flatbread-efforts/findings/fnd-versioned-skill-distribution-passes-full-reposit--hm5cy9j2zts96dg4.md rename to .flatbread-proof/findings/fnd-versioned-skill-distribution-passes-full-reposit--hm5cy9j2zts96dg4.md diff --git a/.flatbread-efforts/findings/fnd-workshop-shortlist-favors-crumb-graph-over-yeast--tv3ydt3wfb3n4y0g.md b/.flatbread-proof/findings/fnd-workshop-shortlist-favors-crumb-graph-over-yeast--tv3ydt3wfb3n4y0g.md similarity index 100% rename from .flatbread-efforts/findings/fnd-workshop-shortlist-favors-crumb-graph-over-yeast--tv3ydt3wfb3n4y0g.md rename to .flatbread-proof/findings/fnd-workshop-shortlist-favors-crumb-graph-over-yeast--tv3ydt3wfb3n4y0g.md diff --git a/.flatbread-efforts/issues/iss-agents-cannot-obtain-full-record-bodies-through--ekfpcg6hrkwgy287.md b/.flatbread-proof/issues/iss-agents-cannot-obtain-full-record-bodies-through--ekfpcg6hrkwgy287.md similarity index 100% rename from .flatbread-efforts/issues/iss-agents-cannot-obtain-full-record-bodies-through--ekfpcg6hrkwgy287.md rename to .flatbread-proof/issues/iss-agents-cannot-obtain-full-record-bodies-through--ekfpcg6hrkwgy287.md diff --git a/.flatbread-efforts/issues/iss-define-blocking-decision-semantics--3bj9ph7ppab2c7g2.md b/.flatbread-proof/issues/iss-define-blocking-decision-semantics--3bj9ph7ppab2c7g2.md similarity index 100% rename from .flatbread-efforts/issues/iss-define-blocking-decision-semantics--3bj9ph7ppab2c7g2.md rename to .flatbread-proof/issues/iss-define-blocking-decision-semantics--3bj9ph7ppab2c7g2.md diff --git a/.flatbread-efforts/issues/iss-implement-blob-collection-and-crumb-graph-cites--g2c7m6j39we5xy3z.md b/.flatbread-proof/issues/iss-implement-blob-collection-and-crumb-graph-cites--g2c7m6j39we5xy3z.md similarity index 100% rename from .flatbread-efforts/issues/iss-implement-blob-collection-and-crumb-graph-cites--g2c7m6j39we5xy3z.md rename to .flatbread-proof/issues/iss-implement-blob-collection-and-crumb-graph-cites--g2c7m6j39we5xy3z.md diff --git a/.flatbread-efforts/issues/iss-implement-crumb-graph-rename-across-packages-cli--dp6jvt2kafab7m4t.md b/.flatbread-proof/issues/iss-implement-crumb-graph-rename-across-packages-cli--dp6jvt2kafab7m4t.md similarity index 100% rename from .flatbread-efforts/issues/iss-implement-crumb-graph-rename-across-packages-cli--dp6jvt2kafab7m4t.md rename to .flatbread-proof/issues/iss-implement-crumb-graph-rename-across-packages-cli--dp6jvt2kafab7m4t.md diff --git a/.flatbread-efforts/issues/iss-implement-crumb-trail-rename-across-packages-cli--316rdzpt80sdxkw1.md b/.flatbread-proof/issues/iss-implement-crumb-trail-rename-across-packages-cli--316rdzpt80sdxkw1.md similarity index 100% rename from .flatbread-efforts/issues/iss-implement-crumb-trail-rename-across-packages-cli--316rdzpt80sdxkw1.md rename to .flatbread-proof/issues/iss-implement-crumb-trail-rename-across-packages-cli--316rdzpt80sdxkw1.md diff --git a/.flatbread-proof/issues/iss-implement-proof-and-oven-rename-across-both-repo--xr02e1wp62ry1ccq.md b/.flatbread-proof/issues/iss-implement-proof-and-oven-rename-across-both-repo--xr02e1wp62ry1ccq.md new file mode 100644 index 00000000..cd6216fd --- /dev/null +++ b/.flatbread-proof/issues/iss-implement-proof-and-oven-rename-across-both-repo--xr02e1wp62ry1ccq.md @@ -0,0 +1,18 @@ +--- +id: iss-implement-proof-and-oven-rename-across-both-repo--xr02e1wp62ry1ccq +effort: eff-flatbread-product-branding--zt7b35sa05kyvhdz +title: Implement Proof and Oven rename across both repos +kind: gap +status: resolved +created_at: '2026-08-12T17:27:41.751Z' +derives_from: + - dec-name-the-memory-product-proof-and-the-dag-runner--8e1qgp2032607pr2 +resolved_by: + - dec-name-the-memory-product-proof-and-the-dag-runner--8e1qgp2032607pr2 +--- + +Execute the identifier sweep committed by the accepted Decision. Neither product has been released, so this is a clean cut: no compatibility aliases, no npm deprecation window, no major-migration skill. + +Order: (1) rename the runner repo Proof → Oven until no `proof` identifiers remain; (2) in flatbread, retarget runner mentions and move `.cursor/skills/proof` → `oven`; (3) rename Effort Graph → Proof (package, CLI, skill, paths, types). + +Touchpoint map: `/var/folders/db/9znhb3490mz9l_c21v4f502r0000gn/T/handoff-XXXXXX.md.yhkZaByt5f`. Repos: `/Users/tonyketcham/Code/Github/personal/proof` (runner) and this monorepo (memory). diff --git a/.flatbread-efforts/issues/iss-live-reload-and-export-cli-remain-gaps--xe19gzqf654xeyg4.md b/.flatbread-proof/issues/iss-live-reload-and-export-cli-remain-gaps--xe19gzqf654xeyg4.md similarity index 100% rename from .flatbread-efforts/issues/iss-live-reload-and-export-cli-remain-gaps--xe19gzqf654xeyg4.md rename to .flatbread-proof/issues/iss-live-reload-and-export-cli-remain-gaps--xe19gzqf654xeyg4.md diff --git a/.flatbread-efforts/issues/iss-proof-output-retention-follow-ups-remain-open--4fkjb93v3pey43y0.md b/.flatbread-proof/issues/iss-proof-output-retention-follow-ups-remain-open--4fkjb93v3pey43y0.md similarity index 100% rename from .flatbread-efforts/issues/iss-proof-output-retention-follow-ups-remain-open--4fkjb93v3pey43y0.md rename to .flatbread-proof/issues/iss-proof-output-retention-follow-ups-remain-open--4fkjb93v3pey43y0.md diff --git a/.flatbread-efforts/issues/iss-skill-scoped-records-filter-example-over-constra--vd0gcnpc9cm6jzjh.md b/.flatbread-proof/issues/iss-skill-scoped-records-filter-example-over-constra--vd0gcnpc9cm6jzjh.md similarity index 100% rename from .flatbread-efforts/issues/iss-skill-scoped-records-filter-example-over-constra--vd0gcnpc9cm6jzjh.md rename to .flatbread-proof/issues/iss-skill-scoped-records-filter-example-over-constra--vd0gcnpc9cm6jzjh.md diff --git a/.flatbread-efforts/issues/iss-typed-selection-builder-remains-a-product-gap--4zawc913n4gnyfcw.md b/.flatbread-proof/issues/iss-typed-selection-builder-remains-a-product-gap--4zawc913n4gnyfcw.md similarity index 100% rename from .flatbread-efforts/issues/iss-typed-selection-builder-remains-a-product-gap--4zawc913n4gnyfcw.md rename to .flatbread-proof/issues/iss-typed-selection-builder-remains-a-product-gap--4zawc913n4gnyfcw.md diff --git a/.flatbread-efforts/issues/iss-writedecision-with-supersedes-leaves-the-superse--by624gyf21ex42sv.md b/.flatbread-proof/issues/iss-writedecision-with-supersedes-leaves-the-superse--by624gyf21ex42sv.md similarity index 100% rename from .flatbread-efforts/issues/iss-writedecision-with-supersedes-leaves-the-superse--by624gyf21ex42sv.md rename to .flatbread-proof/issues/iss-writedecision-with-supersedes-leaves-the-superse--by624gyf21ex42sv.md diff --git a/.flatbread-efforts/risks/rsk-full-transcripts-can-overflow-prompts-and-leak-s--3p7ybk07jqe5w593.md b/.flatbread-proof/risks/rsk-full-transcripts-can-overflow-prompts-and-leak-s--3p7ybk07jqe5w593.md similarity index 100% rename from .flatbread-efforts/risks/rsk-full-transcripts-can-overflow-prompts-and-leak-s--3p7ybk07jqe5w593.md rename to .flatbread-proof/risks/rsk-full-transcripts-can-overflow-prompts-and-leak-s--3p7ybk07jqe5w593.md diff --git a/.gitignore b/.gitignore index 0a5ba9ab..189ca10b 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,7 @@ # logs yarn-error.log .pnpm-debug.log -**/.flatbread-efforts/.journal/ -**/.flatbread/effort-graph/read-cache/ -# Local Proof DAG artifacts (external Proof tool may write here) -.flatbread/artifacts/ +**/.flatbread-proof/.journal/ +**/.flatbread/proof/read-cache/ +# Local Oven DAG artifacts (external Oven tool may write here) +.oven/artifacts/ diff --git a/AGENTS.md b/AGENTS.md index 7908798e..d51e0a54 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -47,7 +47,8 @@ See `CONTRIBUTING.md` for full details. Quick reference: - **Typecheck**: `pnpm typecheck` - **Test**: `pnpm test` (builds, then runs ava + vitest suites). Vitest packages use `pnpm -F @flatbread/utils exec vitest run` / `pnpm -F @flatbread/codegen exec vitest run` (`run` avoids watch mode). - **Full verify**: `pnpm verify` (lint + typecheck + build + test) -- **Proof**: the DAG task runner now lives at https://github.com/FlatbreadLabs/proof. +- **Oven**: the DAG task runner lives at https://github.com/FlatbreadLabs/oven. +- **Proof**: agent memory in this repo. CLI is `flatbread proof …`; records live under `.flatbread-proof/`. - **Dev server**: `pnpm play` (GraphQL on port 5057, Next.js on port 3000). From `examples/nextjs`, prefer `pnpm exec flatbread start -- next dev --turbopack`. Use `flatbread start` — `flatbread dev` is not a CLI command. ### Mergify Stacks diff --git a/CHANGELOG.md b/CHANGELOG.md index f1c71157..6470ecc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## Unreleased + +- The DAG runner is now `@flatbread/oven` (`pnpm exec oven`); the memory package is now `@flatbread/proof` with the `flatbread proof` CLI. + Notes for the Flatbread release train. Some packages also keep their own changelog; this file covers the repository as a whole. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index abc055ba..4cee09f2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,9 +34,9 @@ Optional **`pnpm play`** from the repo root is a shortcut for **`cd examples/nex - Build all packages: `pnpm build` - **Workspace libraries (watch-only):** `pnpm dev` — runs package `dev` scripts (e.g. `tsup --watch`) for `packages/*`; it does **not** start the Next.js example. - **Next.js example:** prefer the flow under [Recommended onboarding](#recommended-onboarding-try-flatbread-in-the-nextjs-example); or `pnpm play` as a convenience alias. -- **Effort Graph explorer:** +- **Proof explorer:** 1. Run `pnpm play:efforts` (builds `@flatbread/explorer` via `preplay:efforts`, then `flatbread start --watch --open`). - 2. When `flatbread.config.js` uses `effortGraphContent()`, Flatbread serves `@flatbread/explorer` at `http://localhost:5057/`. The Apollo sandbox is at `/graphql`. + 2. When `flatbread.config.js` uses `proofContent()`, Flatbread serves `@flatbread/explorer` at `http://localhost:5057/`. The Apollo sandbox is at `/graphql`. 3. For hot module replacement (HMR) on the single-page app (SPA) shell, run `pnpm exec flatbread start --watch` and `pnpm --filter @flatbread/explorer dev` in parallel. Vite on **5173** proxies API routes to **5057**. - Check local CI parity before opening a PR: `pnpm verify` @@ -83,8 +83,8 @@ pnpm build - Single package: `pnpm -F test` - Watch (where supported): `pnpm -F test:watch` -Proof (the DAG task runner for Cursor agents) now lives at -https://github.com/FlatbreadLabs/proof. +Oven (the DAG task runner for Cursor agents) now lives at +https://github.com/FlatbreadLabs/oven. ## Releasing packages @@ -100,10 +100,10 @@ letting each package carry its own alpha number. `pnpm bump` still works the same way: it preselects the packages that changed plus their workspace dependents. Only bump every package together again when a release calls for it. -`packages/effort-graph/skills/effort-graph/release.json` records the version an +`packages/proof/skills/proof/release.json` records the version an end user installs. Edit that file, not the copy in `.agents/`. Then run `pnpm skills:sync` to refresh the `.agents/` copy and `pnpm skills:pack-check`, -which fails unless `flatbreadVersion` and `effortGraphVersion` match the current +which fails unless `flatbreadVersion` and `proofVersion` match the current `package.json` versions and `gitTag` equals `v`. `pnpm verify` runs both checks. @@ -147,8 +147,8 @@ Notes: > Note: you must have access permissions on NPM -When changing the Effort Graph skill, edit the source files under -`packages/effort-graph/skills/effort-graph/`, then run these checks in order: +When changing the Proof skill, edit the source files under +`packages/proof/skills/proof/`, then run these checks in order: ```bash pnpm skills:sync @@ -156,10 +156,10 @@ pnpm skills:check pnpm skills:pack-check ``` -Bump and publish `@flatbread/effort-graph` and `flatbread` together when the +Bump and publish `@flatbread/proof` and `flatbread` together when the skill and runtime need matching versions. The publish script checks the copied skill files and package contents first. It then publishes ordinary packages, -`@flatbread/effort-graph`, and finally `flatbread`, stopping at the first +`@flatbread/proof`, and finally `flatbread`, stopping at the first failure. Publish all public packages (the script builds first and then attempts to publish each package): @@ -207,7 +207,7 @@ End users install the skill from that release tag and install the matching first stable release, so the tag is `v1.0.0`: ```bash -npx skills add https://github.com/FlatbreadLabs/flatbread/tree/vX/packages/effort-graph/skills/effort-graph --skill effort-graph +npx skills add https://github.com/FlatbreadLabs/flatbread/tree/vX/packages/proof/skills/proof --skill proof npm install --save-dev flatbread@X ``` diff --git a/docs/research/performant-context-search/README.md b/docs/research/performant-context-search/README.md index fd00ca2e..d331bf00 100644 --- a/docs/research/performant-context-search/README.md +++ b/docs/research/performant-context-search/README.md @@ -16,4 +16,4 @@ The intermediate filenames below name that pipeline only — **they are not chec ## Proof run artifacts -When reproducing or extending this research with `@flatbread/proof`, full DAG runs write per-task transcripts under **`/.flatbread/artifacts/`** by default. See [`packages/proof/README.md`](../../../packages/proof/README.md) (`--full-output-dir`, `--no-artifacts`). +When reproducing or extending this research with `@flatbread/oven`, full DAG runs write per-task transcripts under **`/.oven/artifacts/`** by default. See the [Oven README](https://github.com/FlatbreadLabs/oven#readme) (`--full-output-dir`, `--no-artifacts`). diff --git a/flatbread-agent-artifact-opportunity.md b/flatbread-agent-artifact-opportunity.md index 2ac70a10..8c8d71e5 100644 --- a/flatbread-agent-artifact-opportunity.md +++ b/flatbread-agent-artifact-opportunity.md @@ -4,7 +4,7 @@ Research and product perspective on relational agent artifacts stored in git, st ## 1. Executive Summary -The agent artifact layer in 2026 is dense with conventions and files (`AGENTS.md`, `SKILL.md`, `.handoff/*.md`, `.GCC/branches/*`, `.cs/discoveries.md`, vault MCPs) but thin on **typed relational schemas** over those artifacts. Teams get search, backlinks, versioned memory trees, and handoff packets; they rarely get reference integrity, stable cross-tool IDs, or filterable graph queries like "all blocking decisions for this effort with owning plan and producing sessions." Flatbread already models collections, refs, and rich filters over markdown/YAML in git. Positioning it as **the relational layer for agent efforts in git**—with MCP and generated TypeScript alongside GraphQL—is a credible category move. The recommended posture is an **Effort Graph**: a preset schema (Effort → Plan, Decision, Session, Artifact, Run) plus validation, append-oriented writes, and agent-facing query APIs, without building a CMS or competing on generic databases. +The agent artifact layer in 2026 is dense with conventions and files (`AGENTS.md`, `SKILL.md`, `.handoff/*.md`, `.GCC/branches/*`, `.cs/discoveries.md`, vault MCPs) but thin on **typed relational schemas** over those artifacts. Teams get search, backlinks, versioned memory trees, and handoff packets; they rarely get reference integrity, stable cross-tool IDs, or filterable graph queries like "all blocking decisions for this effort with owning plan and producing sessions." Flatbread already models collections, refs, and rich filters over markdown/YAML in git. Positioning it as **the relational layer for agent efforts in git**—with MCP and generated TypeScript alongside GraphQL—is a credible category move. The recommended posture is an **Proof**: a preset schema (Effort → Plan, Decision, Session, Artifact, Run) plus validation, append-oriented writes, and agent-facing query APIs, without building a CMS or competing on generic databases. ## 2. The Problem @@ -90,7 +90,7 @@ Flatbread becomes a full memory product: authoring UI, lifecycle, branching UX, Read-mostly preset: index existing harness folders, validate optional schemas, expose MCP + TS helpers. **Target:** harness engineers wiring Cursor/Claude/GCC without migrating storage. **Strength:** low displacement, fits today's read skew. **Risk:** commodity "nice indexer" unless paired with a sharp noun and integrity story. -### Posture C — Effort Graph (recommended) +### Posture C — Proof (recommended) Own the **Effort** aggregate explicitly: typed collections **Effort**, **Plan**, **Decision**, **Session**, **Artifact**, **Run** (and optional **Agent**, **Review**) with refs and validation; MCP + generated TS + GraphQL over one model; **append-oriented** agent writes into the graph. **Target:** multi-week agentic work in repos. **Strength:** differentiated category, testable MVP, uses every Flatbread primitive; clarifies the GraphQL pivot as "one of several query adapters." **Risk:** needs a minimal credible write path and a schema flexible enough for real harness diversity without dissolving into bespoke configs. @@ -126,27 +126,27 @@ export default defineConfig({ transformer: transformerMarkdown({ markdown: { gfm: true } }), content: [ { - path: '.flatbread-efforts/efforts', + path: '.flatbread-proof/efforts', collection: 'Effort', refs: { owner_agent: 'Agent' }, }, { - path: '.flatbread-efforts/plans', + path: '.flatbread-proof/plans', collection: 'Plan', refs: { effort: 'Effort' }, }, { - path: '.flatbread-efforts/decisions', + path: '.flatbread-proof/decisions', collection: 'Decision', refs: { effort: 'Effort', plan: 'Plan', session: 'Session' }, }, { - path: '.flatbread-efforts/sessions', + path: '.flatbread-proof/sessions', collection: 'Session', refs: { effort: 'Effort' }, }, { - path: '.flatbread-efforts/artifacts', + path: '.flatbread-proof/artifacts', collection: 'Artifact', refs: { effort: 'Effort', @@ -155,12 +155,12 @@ export default defineConfig({ }, }, { - path: '.flatbread-efforts/runs', + path: '.flatbread-proof/runs', collection: 'Run', refs: { session: 'Session', effort: 'Effort' }, }, { - path: '.flatbread-efforts/agents', + path: '.flatbread-proof/agents', collection: 'Agent', }, ], @@ -189,13 +189,13 @@ Frontmatter fields (e.g. `id`, `status`, `blocking`, `decided_at`, `tool`) would Cross-check against [What Not To Build Yet](flatbread-flow-pmf-audit.md) and related warnings. -| Audit constraint | Relationship to Posture C (Effort Graph) | +| Audit constraint | Relationship to Posture C (Proof) | | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Do not build hosted CMS, dashboard, or editing UI yet | **Respects.** MCP/CLI/codegen only; no mandated admin UI. | | Do not compete with full databases on transactions, auth, permissions, high-scale writes | **Respects** if writes stay append-oriented, local, and validation-focused; **stretches** if users demand multi-user locking or roles—then explicitly out of scope. | -| Do not over-invest in many source plugins before local filesystem relational workflow is excellent | **Respects** if Effort Graph ships as one filesystem preset + optional path mappings; **stretches** if many SaaS sources are added prematurely—avoid. | +| Do not over-invest in many source plugins before local filesystem relational workflow is excellent | **Respects** if Proof ships as one filesystem preset + optional path mappings; **stretches** if many SaaS sources are added prematurely—avoid. | | Do not keep GraphQL as the only story | **Aligns.** MCP + TS are first-class in this thesis. | -| Do not add complex migration systems before schemas, IDs, validation, exports, watch | **Aligns.** Effort Graph assumes those foundations land first; **reopens** migration only as import from handoff/GCC folders once core is stable. | +| Do not add complex migration systems before schemas, IDs, validation, exports, watch | **Aligns.** Proof assumes those foundations land first; **reopens** migration only as import from handoff/GCC folders once core is stable. | | Avoid database replacement framing until write path exists | **Stretches language**—"relational layer" must stay precise: **not** a serverless Postgres; **reopens** the need for a documented, minimal write story before marketing breadth. | Section **8** (schema sketch) and **9** (surfaces) should stay synchronized with audit honesty: no promise of generic mutations until shipped. @@ -205,7 +205,7 @@ Section **8** (schema sketch) and **9** (surfaces) should stay synchronized with Before roadmap commitment: 1. **Preset wire-up** — Point Flatbread at an existing agent folder in a real repo (e.g. `.agents/` or documented handoff layout). Can one MCP query return _all blocking decisions for the current effort with plan title_ without custom scripts? -2. **Adversarial schema** — One Effort Graph schema against three layouts: Claude Code-oriented tree, Cursor rules + skills layout, GCC `.GCC/` layout. Where does a single schema break? What mapping layer is minimal? +2. **Adversarial schema** — One Proof schema against three layouts: Claude Code-oriented tree, Cursor rules + skills layout, GCC `.GCC/` layout. Where does a single schema break? What mapping layer is minimal? 3. **Token budget** — Compare cold-start context stuffing vs Flatbread-mediated retrieval over a multi-session effort; benchmark against published handoff savings orders (e.g. AgentHandoff's reported range) as a directional bar, not a guarantee. ## 13. What Not To Build Yet @@ -213,7 +213,7 @@ Before roadmap commitment: - Hosted editing UI or CMS. - Mandatory vector index inside core (optional plugin later). - Arbitrary update/delete mutation API on arbitrary fields. -- New source plugins for proprietary SaaS artifact stores before filesystem Effort Graph is excellent. +- New source plugins for proprietary SaaS artifact stores before filesystem Proof is excellent. - Replacing Claude Code, Cursor, or Codex harnesses—Flatbread should **compose**, not compete. ## 14. Bottom Line diff --git a/flatbread-flow-agentic-workflows.md b/flatbread-flow-agentic-workflows.md index 43df26fc..3e87a2c6 100644 --- a/flatbread-flow-agentic-workflows.md +++ b/flatbread-flow-agentic-workflows.md @@ -84,22 +84,22 @@ For schema-breaking work, use the `flatbread-major-migration` project skill and ## DAG Topology -When running this workflow under the `proof` skill (the `@flatbread/proof` package; legacy alias `dag-task-runner`), map phases to ranks. The runner executes a rank concurrently, then proceeds to the next. +When running this workflow under the `oven` skill (the `@flatbread/oven` package; legacy alias `dag-task-runner`), map phases to ranks. The runner executes a rank concurrently, then proceeds to the next. ### Constraints (read before authoring a Flatbread DAG) -- **No sub-sub-agents in DAG runs.** Each DAG node is a Cursor SDK local agent. It cannot reliably delegate to `.cursor/agents/*` via `Task(subagent_type=…)`. Inline the relevant agent identity into the `subtask_prompt` instead — start the prompt with `You are acting as . Follow its responsibilities and output schema.` and **paste the full output-schema heading list verbatim into every prompt**, not just the first per identity. The runner only forwards `apiKey`/`model`/`cwd` to `Agent.create` (proof: `packages/proof/src/run_dag.ts`), so `.cursor/agents/*` system prompts do not propagate. +- **No sub-sub-agents in DAG runs.** Each DAG node is a Cursor SDK local agent. It cannot reliably delegate to `.cursor/agents/*` via `Task(subagent_type=…)`. Inline the relevant agent identity into the `subtask_prompt` instead — start the prompt with `You are acting as . Follow its responsibilities and output schema.` and **paste the full output-schema heading list verbatim into every prompt**, not just the first per identity. The runner only forwards `apiKey`/`model`/`cwd` to `Agent.create` (proof: `https://github.com/FlatbreadLabs/oven`), so `.cursor/agents/*` system prompts do not propagate. - **`readonly: true` and `tools:` frontmatter are advisory in DAG mode.** A subagent acting as `flatbread-architecture-planner` can still write files because the runner does not pass agent frontmatter to `Agent.create`. `Do not edit files.` is purely a prompt-level instruction; reinforce it in the prompt body for read-only tasks. -- **Project skills do auto-attach.** `proof` and `flatbread-major-migration` are visible to subagents via description, so subtask prompts can reference them by name without re-explaining their contents. +- **Project skills do auto-attach.** `flatbread-major-migration` are visible to subagents via description, so subtask prompts can reference them by name without re-explaining their contents. - **Same-rank file-write safety for Flatbread.** The coupled chain `packages/core` → `packages/codegen` → `examples/nextjs` is the most common contention. Treat the safe parallel cuts list below as the source of truth. - **Same-rank port-5057 safety.** `flatbread start` binds port `5057` over plain HTTP. Never put two tasks that invoke `flatbread start`, `pnpm dev`, `pnpm build`, or `agent-browser` against `examples/nextjs` in the same rank. - **2000-char upstream stitch cap on a 4000-char `STREAM_CAP`.** Each child sees at most 2000 chars of each parent's `resultText`, and the parent's output is itself capped at 4000 chars. Subagent output must lead with the structured headings the downstream task needs and group related entries (e.g. `packages/core/src/{generators,resolvers,types}.ts`) to fit in the window. ### Default DAG shape per phase -"Rank" is computed by the runner via Kahn topo-sort over `depends_on`. Author the DAG by `depends_on` only and let the runner derive ranks. Run `pnpm exec proof --init-only --dag ` after editing to confirm the rank count didn't regress. +"Rank" is computed by the runner via Kahn topo-sort over `depends_on`. Author the DAG by `depends_on` only and let the runner derive ranks. Run `pnpm exec oven --init-only --dag ` after editing to confirm the rank count didn't regress. -The schema-migration starter (`.cursor/skills/proof/examples/flatbread/dag-schema-migration.json`, 21 tasks) collapses to 7 ranks: +The schema-migration starter (`https://github.com/FlatbreadLabs/oven/tree/main/examples/flatbread/dag-schema-migration.json`, 21 tasks) collapses to 7 ranks: | Phase | Rank | Tasks | Identity | | --------------------------------- | ---- | -------------------------------------------------------------------------------------------------------------- | -------------------------------- | @@ -142,7 +142,7 @@ Every DAG subtask whose work touches positioning, docs, README, examples, or roa ### Templates -Reusable DAG JSONs live at `.cursor/skills/proof/examples/flatbread/`. Start from the closest template and edit task-level details rather than re-deriving the rank structure each time. +Reusable DAG JSONs live at `https://github.com/FlatbreadLabs/oven/tree/main/examples/flatbread/`. Start from the closest template and edit task-level details rather than re-deriving the rank structure each time. ## Failure Recovery diff --git a/flatbread-flow-pmf-audit.md b/flatbread-flow-pmf-audit.md index 1ba55403..0fe6e5b9 100644 --- a/flatbread-flow-pmf-audit.md +++ b/flatbread-flow-pmf-audit.md @@ -147,7 +147,7 @@ Agent harnesses emit large markdown artifacts but rarely persist them as a **typ Flatbread can pivot query surfaces beyond GraphQL-only by positioning as **the relational layer for agent efforts in git**: collections and refs over markdown/YAML, with **MCP and generated TypeScript** as agent-first adapters alongside GraphQL. That use case **raises the priority** of work already called out near term—config typing, ID normalization, relation validation, and watch mode—and stays compatible with “no hosted CMS/UI yet” if writes stay narrow (e.g. append-oriented artifact deposits). -Full survey, five-layer SOTA map, product postures (including recommended **Effort Graph**), schema sketch, validation experiments, and explicit tensions with this audit’s “What Not To Build Yet” list: **[flatbread-agent-artifact-opportunity.md](./flatbread-agent-artifact-opportunity.md)**. +Full survey, five-layer SOTA map, product postures (including recommended **Proof**), schema sketch, validation experiments, and explicit tensions with this audit’s “What Not To Build Yet” list: **[flatbread-agent-artifact-opportunity.md](./flatbread-agent-artifact-opportunity.md)**. ## Near-Term Experiments diff --git a/flatbread.config.js b/flatbread.config.js index cee007df..a55de925 100644 --- a/flatbread.config.js +++ b/flatbread.config.js @@ -1,13 +1,13 @@ import { source as filesystem } from '@flatbread/source-filesystem'; import { transformer as markdownTransformer } from '@flatbread/transformer-markdown'; import { defineConfig } from '@flatbread/config'; -import { effortGraphContent } from '@flatbread/effort-graph'; +import { proofContent } from '@flatbread/proof'; /** - * For development, we use Flatbread's Effort Graph on itself as a long-running agent memory layer. + * For development, we use Flatbread's Proof on itself as a long-running agent memory layer. */ export default defineConfig({ source: filesystem(), transformer: markdownTransformer(), - content: effortGraphContent(), + content: proofContent(), }); diff --git a/package.json b/package.json index 3b00968d..fb138048 100644 --- a/package.json +++ b/package.json @@ -18,9 +18,9 @@ "build:examples": "pnpm -r --filter {examples/*} build", "build:types": "pnpm -r --filter !{examples/*} exec -- tsup --dts-only", "dev": "pnpm -r --parallel --filter !{examples/*} dev", - "skills:sync": "pnpm --filter @flatbread/effort-graph skills:sync", - "skills:check": "pnpm --filter @flatbread/effort-graph skills:check", - "skills:pack-check": "pnpm --filter @flatbread/effort-graph skills:pack-check", + "skills:sync": "pnpm --filter @flatbread/proof skills:sync", + "skills:check": "pnpm --filter @flatbread/proof skills:check", + "skills:pack-check": "pnpm --filter @flatbread/proof skills:pack-check", "lint:eslint": "eslint packages/**/src", "lint:prettier": "prettier --check --plugin-search-dir=. .", "lint": "pnpm lint:prettier", @@ -66,7 +66,7 @@ "devDependencies": { "@ava/typescript": "3.0.1", "@cursor/sdk": "^1.0.9", - "@flatbread/effort-graph": "workspace:*", + "@flatbread/proof": "workspace:*", "@nrwl/workspace": "14.4.3", "@types/inquirer": "8.2.1", "@types/node": "16.11.47", diff --git a/packages/explorer/README.md b/packages/explorer/README.md index 0227709e..93bc40df 100644 --- a/packages/explorer/README.md +++ b/packages/explorer/README.md @@ -1,13 +1,13 @@ # `@flatbread/explorer` Content-relation explorer for Flatbread. v1 ships a generic single-page app -(SPA) shell plus an **Effort Graph** preset. When your config uses -`effortGraphContent()`, `flatbread start` serves this UI at `/`. +(SPA) shell plus an **Proof** preset. When your config uses +`proofContent()`, `flatbread start` serves this UI at `/`. ## Try it locally ```bash -# flatbread.config.js includes effortGraphContent() +# flatbread.config.js includes proofContent() npx flatbread start --watch --open # → http://localhost:5057/ explorer # → http://localhost:5057/graphql Apollo sandbox @@ -36,7 +36,7 @@ Same-origin deploys (assets served by Flatbread) need no query param. | ------------------------------ | ------------------------------------------ | | `getExplorerStaticDir()` | Absolute path to `dist/static` for Express | | `explorerAssetsPresent()` | Whether prebuilt `index.html` exists | -| `matchExplorerPreset(content)` | Detect Effort Graph (and later presets) | +| `matchExplorerPreset(content)` | Detect Proof (and later presets) | | `EXPLORER_BOOTSTRAP_PATH` | Bootstrap JSON path Flatbread injects | There is no public React component export in v1. diff --git a/packages/explorer/package.json b/packages/explorer/package.json index adc391e7..23adf6d5 100644 --- a/packages/explorer/package.json +++ b/packages/explorer/package.json @@ -1,7 +1,7 @@ { "name": "@flatbread/explorer", "version": "1.0.0", - "description": "Single-page app for browsing a Flatbread content graph, served by flatbread start. Ships an Effort Graph preset.", + "description": "Single-page app for browsing a Flatbread content graph, served by flatbread start. Ships an Proof preset.", "type": "module", "scripts": { "build": "pnpm build:node && pnpm build:web", @@ -9,7 +9,7 @@ "build:web": "vite build", "dev": "vite", "typecheck": "tsc -p tsconfig.json --noEmit", - "test": "node --import tsx --test src/node/matchPreset.test.ts src/node/staticDir.test.ts src/web/core/endpoints.test.ts src/web/core/physics/forces.test.ts src/web/core/physics/simulation.test.ts src/web/presets/effort-graph/glyphs.test.ts src/web/presets/effort-graph/lifecycle.test.ts src/web/presets/effort-graph/normalize.test.ts src/web/presets/effort-graph/query.test.ts src/web/presets/effort-graph/useEffortGraphLive.test.ts" + "test": "node --import tsx --test src/node/matchPreset.test.ts src/node/staticDir.test.ts src/web/core/endpoints.test.ts src/web/core/physics/forces.test.ts src/web/core/physics/simulation.test.ts src/web/presets/proof/glyphs.test.ts src/web/presets/proof/lifecycle.test.ts src/web/presets/proof/normalize.test.ts src/web/presets/proof/query.test.ts src/web/presets/proof/useProofLive.test.ts" }, "repository": { "type": "git", @@ -36,7 +36,7 @@ "node": ">=20.19" }, "dependencies": { - "@flatbread/effort-graph": "workspace:*" + "@flatbread/proof": "workspace:*" }, "devDependencies": { "@react-three/drei": "^10.0.6", diff --git a/packages/explorer/src/node/matchPreset.test.ts b/packages/explorer/src/node/matchPreset.test.ts index 86c6a3d5..d6f210e5 100644 --- a/packages/explorer/src/node/matchPreset.test.ts +++ b/packages/explorer/src/node/matchPreset.test.ts @@ -1,14 +1,14 @@ import assert from 'node:assert/strict'; import { describe, it } from 'node:test'; -import { effortGraphContent } from '@flatbread/effort-graph'; +import { proofContent } from '@flatbread/proof'; import { matchExplorerPreset } from './matchPreset.js'; describe('matchExplorerPreset', () => { - it('matches a full effortGraphContent() preset', () => { - const match = matchExplorerPreset(effortGraphContent('.flatbread-efforts')); + it('matches a full proofContent() preset', () => { + const match = matchExplorerPreset(proofContent('.flatbread-proof')); assert.deepEqual(match, { - preset: 'effort-graph', - root: '.flatbread-efforts', + preset: 'proof', + root: '.flatbread-proof', }); }); @@ -19,8 +19,8 @@ describe('matchExplorerPreset', () => { ); }); - it('returns null when the Effort Graph preset is incomplete', () => { - const partial = effortGraphContent('.flatbread-efforts').filter( + it('returns null when the Proof preset is incomplete', () => { + const partial = proofContent('.flatbread-proof').filter( (entry) => entry.collection !== 'Blob' ); assert.equal(matchExplorerPreset(partial), null); diff --git a/packages/explorer/src/node/matchPreset.ts b/packages/explorer/src/node/matchPreset.ts index 95a0f94a..c76ceaf1 100644 --- a/packages/explorer/src/node/matchPreset.ts +++ b/packages/explorer/src/node/matchPreset.ts @@ -1,10 +1,10 @@ -import { findEffortGraphContentRoot } from '@flatbread/effort-graph'; +import { findProofContentRoot } from '@flatbread/proof'; -export type ExplorerPresetId = 'effort-graph'; +export type ExplorerPresetId = 'proof'; export interface ExplorerPresetMatch { preset: ExplorerPresetId; - /** Content root for the matched preset (Effort Graph markdown tree). */ + /** Content root for the matched preset (Proof markdown tree). */ root: string; } @@ -21,9 +21,9 @@ type ContentLike = readonly { export function matchExplorerPreset( content: ContentLike ): ExplorerPresetMatch | null { - const root = findEffortGraphContentRoot( - content as Parameters[0] + const root = findProofContentRoot( + content as Parameters[0] ); if (!root) return null; - return { preset: 'effort-graph', root }; + return { preset: 'proof', root }; } diff --git a/packages/explorer/src/web/app/components/DetailDrawer.tsx b/packages/explorer/src/web/app/components/DetailDrawer.tsx index 31f2e801..e79bf2c4 100644 --- a/packages/explorer/src/web/app/components/DetailDrawer.tsx +++ b/packages/explorer/src/web/app/components/DetailDrawer.tsx @@ -1,11 +1,11 @@ import { useEffect, useMemo, useRef } from 'react'; import { oklchCss, effortColor, retiredOklch } from '@/core/oklch'; -import { PRIMITIVES, primitiveOklch } from '@/presets/effort-graph/primitives'; +import { PRIMITIVES, primitiveOklch } from '@/presets/proof/primitives'; import { effectiveLifecycle, type LifecycleIndex, -} from '@/presets/effort-graph/lifecycle'; -import type { GraphEdge, GraphNode } from '@/presets/effort-graph/types'; +} from '@/presets/proof/lifecycle'; +import type { GraphEdge, GraphNode } from '@/presets/proof/types'; import { useTheme } from '../hooks/useTheme'; import { MarkdownSurface } from './MarkdownSurface'; import { diff --git a/packages/explorer/src/web/app/components/GraphCanvas.tsx b/packages/explorer/src/web/app/components/GraphCanvas.tsx index 09837e45..1ae8ec6a 100644 --- a/packages/explorer/src/web/app/components/GraphCanvas.tsx +++ b/packages/explorer/src/web/app/components/GraphCanvas.tsx @@ -29,25 +29,25 @@ import { structuralOklch, type Oklch, } from '@/core/oklch'; -import { PRIMITIVES, primitiveOklch } from '@/presets/effort-graph/primitives'; +import { PRIMITIVES, primitiveOklch } from '@/presets/proof/primitives'; import { CIRCLE_SEGMENTS, GLYPH_OUTLINES, RING_INNER_RATIO, glyphExtent, type GlyphId, -} from '@/presets/effort-graph/glyphs'; +} from '@/presets/proof/glyphs'; import { buildAlivenessMap, isOpenBlocker, type Aliveness, type EffectiveLifecycle, -} from '@/presets/effort-graph/lifecycle'; +} from '@/presets/proof/lifecycle'; import type { GraphEdge, GraphEdgeKind, GraphNode, -} from '@/presets/effort-graph/types'; +} from '@/presets/proof/types'; import { useTheme, type ColorMode } from '../hooks/useTheme'; import { RELATION_META, @@ -238,7 +238,7 @@ export default function GraphCanvas(props: GraphCanvasProps) { ref={wrapperRef} role="application" tabIndex={0} - aria-label="Effort Graph canvas" + aria-label="Proof canvas" aria-describedby="graph-canvas-help" onKeyDown={handleKeyDown} onWheel={takeover.onWheel} diff --git a/packages/explorer/src/web/app/components/Legend.tsx b/packages/explorer/src/web/app/components/Legend.tsx index a6575d1a..e281689e 100644 --- a/packages/explorer/src/web/app/components/Legend.tsx +++ b/packages/explorer/src/web/app/components/Legend.tsx @@ -11,8 +11,8 @@ import { PRIMITIVES, PRIMITIVE_ORDER, primitiveOklch, -} from '@/presets/effort-graph/primitives'; -import type { GraphNode } from '@/presets/effort-graph/types'; +} from '@/presets/proof/primitives'; +import type { GraphNode } from '@/presets/proof/types'; import { useTheme } from '../hooks/useTheme'; import { PrimitiveGlyph, diff --git a/packages/explorer/src/web/app/components/EffortGraphApp.tsx b/packages/explorer/src/web/app/components/ProofApp.tsx similarity index 90% rename from packages/explorer/src/web/app/components/EffortGraphApp.tsx rename to packages/explorer/src/web/app/components/ProofApp.tsx index 6a11d464..aa15b94e 100644 --- a/packages/explorer/src/web/app/components/EffortGraphApp.tsx +++ b/packages/explorer/src/web/app/components/ProofApp.tsx @@ -1,13 +1,13 @@ import { lazy, Suspense, useEffect, useMemo } from 'react'; import { resolveGraphqlEndpoint } from '@/core/endpoints'; -import { useEffortGraphLive } from '@/presets/effort-graph/useEffortGraphLive'; +import { useProofLive } from '@/presets/proof/useProofLive'; import { buildAlivenessMap, buildLifecycleIndex, summarizeGraph, -} from '@/presets/effort-graph/lifecycle'; -import type { GraphNode } from '@/presets/effort-graph/types'; +} from '@/presets/proof/lifecycle'; +import type { GraphNode } from '@/presets/proof/types'; import { TopBar } from './TopBar'; import { Legend } from './Legend'; @@ -16,10 +16,10 @@ import { RELATION_META, type RelationGroupId } from './RelationLegend'; const GraphCanvas = lazy(() => import('./GraphCanvas')); -export function EffortGraphApp() { +export function ProofApp() { const endpoint = resolveGraphqlEndpoint(); const { nodes, edges, status, generation, error, selectedId, setSelectedId } = - useEffortGraphLive({ endpoint }); + useProofLive({ endpoint }); const nodesById = useMemo(() => { const map = new Map(); @@ -113,7 +113,7 @@ function EmptyState({ status, error, }: { - status: ReturnType['status']; + status: ReturnType['status']; error: Error | null; }) { const [heading, message] = @@ -126,8 +126,8 @@ function EmptyState({ 'Run `flatbread start --watch --open` so GraphQL is served (default port 5057).', ] : [ - 'No Effort Graph records yet', - 'Nothing found in the Effort Graph content root. Journal a record and it will grow in here.', + 'No Proof records yet', + 'Nothing found in the Proof content root. Journal a record and it will grow in here.', ]; return ( diff --git a/packages/explorer/src/web/app/components/RelationLegend.tsx b/packages/explorer/src/web/app/components/RelationLegend.tsx index 8f2b8191..f30b20ea 100644 --- a/packages/explorer/src/web/app/components/RelationLegend.tsx +++ b/packages/explorer/src/web/app/components/RelationLegend.tsx @@ -1,14 +1,8 @@ -import type { - GraphEdgeKind, - GraphNodeKind, -} from '@/presets/effort-graph/types'; +import type { GraphEdgeKind, GraphNodeKind } from '@/presets/proof/types'; import type { ColorMode } from '@/core/oklch'; import { oklchCss, structuralOklch } from '@/core/oklch'; -import { PRIMITIVES, primitiveOklch } from '@/presets/effort-graph/primitives'; -import { - RING_INNER_RATIO, - glyphSvgPoints, -} from '@/presets/effort-graph/glyphs'; +import { PRIMITIVES, primitiveOklch } from '@/presets/proof/primitives'; +import { RING_INNER_RATIO, glyphSvgPoints } from '@/presets/proof/glyphs'; export type RelationGroupId = | 'lineage' diff --git a/packages/explorer/src/web/app/components/TopBar.tsx b/packages/explorer/src/web/app/components/TopBar.tsx index c64a1395..68747a61 100644 --- a/packages/explorer/src/web/app/components/TopBar.tsx +++ b/packages/explorer/src/web/app/components/TopBar.tsx @@ -1,9 +1,6 @@ import { useTheme } from '../hooks/useTheme'; -import type { GraphSummary } from '@/presets/effort-graph/lifecycle'; -import { - liveStatusLabel, - type LiveStatus, -} from '@/presets/effort-graph/useEffortGraphLive'; +import type { GraphSummary } from '@/presets/proof/lifecycle'; +import { liveStatusLabel, type LiveStatus } from '@/presets/proof/useProofLive'; interface TopBarProps { status: LiveStatus; @@ -16,7 +13,7 @@ export function TopBar({ status, generation, summary }: TopBarProps) {

- Effort Graph + Proof

{/* Counts are phrased in primitives, not nodes and edges: roughly half of diff --git a/packages/explorer/src/web/app/main.tsx b/packages/explorer/src/web/app/main.tsx index 21c744a2..9a66f220 100644 --- a/packages/explorer/src/web/app/main.tsx +++ b/packages/explorer/src/web/app/main.tsx @@ -1,7 +1,7 @@ import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import { ThemeProvider } from './hooks/useTheme'; -import { EffortGraphApp } from './components/EffortGraphApp'; +import { ProofApp } from './components/ProofApp'; import './globals.css'; const root = document.getElementById('root'); @@ -12,7 +12,7 @@ if (!root) { createRoot(root).render( - + ); diff --git a/packages/explorer/src/web/core/endpoints.test.ts b/packages/explorer/src/web/core/endpoints.test.ts index a897fa55..92bac3b5 100644 --- a/packages/explorer/src/web/core/endpoints.test.ts +++ b/packages/explorer/src/web/core/endpoints.test.ts @@ -8,7 +8,7 @@ import { } from './endpoints.js'; const DEFAULT_BOOTSTRAP: ExplorerBootstrap = { - preset: 'effort-graph', + preset: 'proof', graphqlPath: '/graphql', eventsPath: '/events', }; @@ -214,7 +214,7 @@ describe('resolveEventsUrl', () => { it('uses custom eventsPath from window bootstrap', () => { withExplorerBootstrap( { - preset: 'effort-graph', + preset: 'proof', graphqlPath: '/graphql', eventsPath: '/custom-events', }, @@ -230,7 +230,7 @@ describe('resolveEventsUrl', () => { it('derives custom eventsPath from the GraphQL endpoint origin only', () => { withExplorerBootstrap( { - preset: 'effort-graph', + preset: 'proof', graphqlPath: '/graphql', eventsPath: '/sse/stream', }, diff --git a/packages/explorer/src/web/core/physics/index.ts b/packages/explorer/src/web/core/physics/index.ts index 0642ace2..53cd9911 100644 --- a/packages/explorer/src/web/core/physics/index.ts +++ b/packages/explorer/src/web/core/physics/index.ts @@ -1,5 +1,5 @@ /** - * Public entry point for the Effort Graph 2D physics + growth engine. + * Public entry point for the Proof 2D physics + growth engine. * * Import from here, not from the submodules, so we can freely refactor * internals without breaking consumers. diff --git a/packages/explorer/src/web/core/physics/simulation.ts b/packages/explorer/src/web/core/physics/simulation.ts index 26d1c3d2..05b9878f 100644 --- a/packages/explorer/src/web/core/physics/simulation.ts +++ b/packages/explorer/src/web/core/physics/simulation.ts @@ -1,5 +1,5 @@ /** - * `createGraphSimulation` — the primary entry point for the Effort Graph + * `createGraphSimulation` — the primary entry point for the Proof * physics + growth engine. * * The engine keeps its own `SimNode` / `SimEdge` for each id it has ever diff --git a/packages/explorer/src/web/core/physics/types.ts b/packages/explorer/src/web/core/physics/types.ts index 30c2a75f..fce8cfd1 100644 --- a/packages/explorer/src/web/core/physics/types.ts +++ b/packages/explorer/src/web/core/physics/types.ts @@ -1,5 +1,5 @@ /** - * Public types for the Effort Graph physics + growth engine. + * Public types for the Proof physics + growth engine. * * The engine is a pure-TypeScript layer intended to be stepped from an R3F * `useFrame` callback. It knows nothing about React or Three.js — it produces diff --git a/packages/explorer/src/web/presets/effort-graph/glyphs.test.ts b/packages/explorer/src/web/presets/proof/glyphs.test.ts similarity index 100% rename from packages/explorer/src/web/presets/effort-graph/glyphs.test.ts rename to packages/explorer/src/web/presets/proof/glyphs.test.ts diff --git a/packages/explorer/src/web/presets/effort-graph/glyphs.ts b/packages/explorer/src/web/presets/proof/glyphs.ts similarity index 100% rename from packages/explorer/src/web/presets/effort-graph/glyphs.ts rename to packages/explorer/src/web/presets/proof/glyphs.ts diff --git a/packages/explorer/src/web/presets/effort-graph/lifecycle.test.ts b/packages/explorer/src/web/presets/proof/lifecycle.test.ts similarity index 100% rename from packages/explorer/src/web/presets/effort-graph/lifecycle.test.ts rename to packages/explorer/src/web/presets/proof/lifecycle.test.ts diff --git a/packages/explorer/src/web/presets/effort-graph/lifecycle.ts b/packages/explorer/src/web/presets/proof/lifecycle.ts similarity index 100% rename from packages/explorer/src/web/presets/effort-graph/lifecycle.ts rename to packages/explorer/src/web/presets/proof/lifecycle.ts diff --git a/packages/explorer/src/web/presets/effort-graph/normalize.test.ts b/packages/explorer/src/web/presets/proof/normalize.test.ts similarity index 81% rename from packages/explorer/src/web/presets/effort-graph/normalize.test.ts rename to packages/explorer/src/web/presets/proof/normalize.test.ts index 74360dac..e5546d5e 100644 --- a/packages/explorer/src/web/presets/effort-graph/normalize.test.ts +++ b/packages/explorer/src/web/presets/proof/normalize.test.ts @@ -1,11 +1,11 @@ import assert from 'node:assert/strict'; import { describe, it } from 'node:test'; -import { normalizeEffortGraph } from './normalize'; -import type { EffortGraphQueryResult } from './query'; +import { normalizeProof } from './normalize'; +import type { ProofQueryResult } from './query'; -describe('normalizeEffortGraph', () => { - const emptyGraph = (): EffortGraphQueryResult => ({ +describe('normalizeProof', () => { + const emptyGraph = (): ProofQueryResult => ({ allEfforts: [], allIssues: [], allFindings: [], @@ -15,7 +15,7 @@ describe('normalizeEffortGraph', () => { }); it('maps _content.raw to node.body (trimmed)', () => { - const data: EffortGraphQueryResult = { + const data: ProofQueryResult = { ...emptyGraph(), allEfforts: [ { @@ -26,13 +26,13 @@ describe('normalizeEffortGraph', () => { ], }; - const graph = normalizeEffortGraph(data); + const graph = normalizeProof(data); assert.equal(graph.nodes.length, 1); assert.equal(graph.nodes[0]?.body, '## Context\n\nBody text.'); }); it('omits body when _content.raw is empty or whitespace', () => { - const data: EffortGraphQueryResult = { + const data: ProofQueryResult = { ...emptyGraph(), allDecisions: [ { @@ -47,7 +47,7 @@ describe('normalizeEffortGraph', () => { ], }; - const graph = normalizeEffortGraph(data); + const graph = normalizeProof(data); const byId = new Map(graph.nodes.map((n) => [n.id, n])); assert.equal(byId.get('dec-1')?.body, undefined); assert.equal(byId.get('dec-2')?.body, undefined); @@ -56,7 +56,7 @@ describe('normalizeEffortGraph', () => { it('keeps one directed edge for a supersession pair', () => { // The writer materializes both sides. Rendering both drew two opposing // arrows between the same records and listed the relation twice. - const data: EffortGraphQueryResult = { + const data: ProofQueryResult = { ...emptyGraph(), allDecisions: [ { @@ -72,7 +72,7 @@ describe('normalizeEffortGraph', () => { ], }; - const graph = normalizeEffortGraph(data); + const graph = normalizeProof(data); const pair = graph.edges.filter( (e) => e.kind === 'supersedes' || e.kind === 'superseded_by' ); @@ -84,7 +84,7 @@ describe('normalizeEffortGraph', () => { }); it('keeps a lone superseded_by when the forward edge is absent', () => { - const data: EffortGraphQueryResult = { + const data: ProofQueryResult = { ...emptyGraph(), allDecisions: [ { id: 'dec-old', title: 'Old', superseded_by: [{ id: 'dec-new' }] }, @@ -92,7 +92,7 @@ describe('normalizeEffortGraph', () => { ], }; - const graph = normalizeEffortGraph(data); + const graph = normalizeProof(data); const pair = graph.edges.filter( (e) => e.kind === 'supersedes' || e.kind === 'superseded_by' ); @@ -102,14 +102,14 @@ describe('normalizeEffortGraph', () => { }); it('keeps superseded_by when the superseder is absent from the query', () => { - const data: EffortGraphQueryResult = { + const data: ProofQueryResult = { ...emptyGraph(), allDecisions: [ { id: 'dec-old', title: 'Old', superseded_by: [{ id: 'dec-missing' }] }, ], }; - const graph = normalizeEffortGraph(data); + const graph = normalizeProof(data); const pair = graph.edges.filter((e) => e.kind === 'superseded_by'); assert.equal(pair.length, 1); diff --git a/packages/explorer/src/web/presets/effort-graph/normalize.ts b/packages/explorer/src/web/presets/proof/normalize.ts similarity index 97% rename from packages/explorer/src/web/presets/effort-graph/normalize.ts rename to packages/explorer/src/web/presets/proof/normalize.ts index e738dde6..31488e71 100644 --- a/packages/explorer/src/web/presets/effort-graph/normalize.ts +++ b/packages/explorer/src/web/presets/proof/normalize.ts @@ -1,6 +1,6 @@ -import type { EffortGraphQueryResult, GraphRef } from './query'; +import type { ProofQueryResult, GraphRef } from './query'; import type { - EffortGraph, + Proof, GraphEdge, GraphEdgeKind, GraphNode, @@ -187,9 +187,7 @@ function dropRedundantReverseEdges(edges: Map): void { * prevent. */ -export function normalizeEffortGraph( - data: EffortGraphQueryResult -): EffortGraph { +export function normalizeProof(data: ProofQueryResult): Proof { const nodes = new Map(); const edges = new Map(); diff --git a/packages/explorer/src/web/presets/effort-graph/primitives.ts b/packages/explorer/src/web/presets/proof/primitives.ts similarity index 98% rename from packages/explorer/src/web/presets/effort-graph/primitives.ts rename to packages/explorer/src/web/presets/proof/primitives.ts index d53730f6..2695faa8 100644 --- a/packages/explorer/src/web/presets/effort-graph/primitives.ts +++ b/packages/explorer/src/web/presets/proof/primitives.ts @@ -1,5 +1,5 @@ /** - * Primitive metadata — the single source of truth for how each Effort Graph + * Primitive metadata — the single source of truth for how each Proof * primitive looks and what it is called. * * Encoding decisions, in short: @@ -14,7 +14,7 @@ * - **Effort hubs keep their cluster hue** at low chroma and render as a ring, * so a hub is never mistaken for a record and the cluster key survives. * - * Vocabulary follows `.agents/skills/effort-graph/glossary.md` — these are + * Vocabulary follows `.agents/skills/proof/glossary.md` — these are * primitives, not "node kinds", and the descriptions paraphrase the glossary * rather than inventing parallel definitions. */ diff --git a/packages/explorer/src/web/presets/effort-graph/query.test.ts b/packages/explorer/src/web/presets/proof/query.test.ts similarity index 87% rename from packages/explorer/src/web/presets/effort-graph/query.test.ts rename to packages/explorer/src/web/presets/proof/query.test.ts index 232b2fbe..29b0badb 100644 --- a/packages/explorer/src/web/presets/effort-graph/query.test.ts +++ b/packages/explorer/src/web/presets/proof/query.test.ts @@ -1,7 +1,7 @@ import assert from 'node:assert/strict'; import test, { describe } from 'node:test'; -import { buildEffortGraphQuery, type SchemaProbeResult } from './query'; +import { buildProofQuery, type SchemaProbeResult } from './query'; /** Slice one collection selection out of the assembled document. */ function collectionBlock(query: string, name: string): string { @@ -10,7 +10,7 @@ function collectionBlock(query: string, name: string): string { return match[0]; } -describe('buildEffortGraphQuery', () => { +describe('buildProofQuery', () => { test('includes Risk supersedes/superseded_by when schema lists them', () => { // Risk has no superseded frontmatter state; the query must select these // edges or retired Risks render as live. @@ -27,7 +27,7 @@ describe('buildEffortGraphQuery', () => { }, }; - const risks = collectionBlock(buildEffortGraphQuery(schema), 'allRisks'); + const risks = collectionBlock(buildProofQuery(schema), 'allRisks'); assert.match(risks, /supersedes \{ id \}/); assert.match(risks, /superseded_by \{ id \}/); @@ -36,7 +36,7 @@ describe('buildEffortGraphQuery', () => { test('with null schema does not emit the full RELATION_FIELDS catalog', () => { // Selecting every known relation before a probe is a hard query error — // Flatbread only exposes a relation once some record uses it. - const query = buildEffortGraphQuery(null); + const query = buildProofQuery(null); assert.match(query, /allRisks \{/); assert.match(query, / title/); @@ -58,7 +58,7 @@ describe('buildEffortGraphQuery', () => { }, }; - const risks = collectionBlock(buildEffortGraphQuery(schema), 'allRisks'); + const risks = collectionBlock(buildProofQuery(schema), 'allRisks'); assert.match(risks, /mitigated_by \{ id \}/); assert.doesNotMatch(risks, /\bsupersedes\b/); diff --git a/packages/explorer/src/web/presets/effort-graph/query.ts b/packages/explorer/src/web/presets/proof/query.ts similarity index 94% rename from packages/explorer/src/web/presets/effort-graph/query.ts rename to packages/explorer/src/web/presets/proof/query.ts index 0feb69a7..72be1075 100644 --- a/packages/explorer/src/web/presets/effort-graph/query.ts +++ b/packages/explorer/src/web/presets/proof/query.ts @@ -15,7 +15,7 @@ export interface ContentField { * `superseded_by` selection would render retired evidence as live. */ -/** Every relation field the Effort Graph preset can produce, per collection. */ +/** Every relation field the Proof preset can produce, per collection. */ const RELATION_FIELDS: Record = { allEfforts: [], allIssues: ['derives_from', 'resolved_by', 'supersedes', 'superseded_by'], @@ -75,9 +75,9 @@ export type CollectionName = export const COLLECTIONS = Object.keys(COLLECTION_TYPE) as CollectionName[]; -/** Introspects which fields each Effort Graph type actually exposes. */ +/** Introspects which fields each Proof type actually exposes. */ export const SCHEMA_PROBE_QUERY = ` - query EffortGraphSchema { + query ProofSchema { ${COLLECTIONS.map( (name) => ` ${name}: __type(name: "${COLLECTION_TYPE[name]}") { fields { @@ -104,9 +104,7 @@ const REF_SUBSELECTION = new Set([ 'mitigated_by', ]); -export function buildEffortGraphQuery( - schema: SchemaProbeResult | null -): string { +export function buildProofQuery(schema: SchemaProbeResult | null): string { const body = COLLECTIONS.map((name) => { const available = new Set( (schema?.[name]?.fields ?? []).map((field) => field.name) @@ -137,7 +135,7 @@ export function buildEffortGraphQuery( ].join('\n'); }).join('\n'); - return `query EffortGraph {\n${body}\n}`; + return `query Proof {\n${body}\n}`; } export interface GraphRef { @@ -213,7 +211,7 @@ export interface RiskRecord extends RelationFields { _content?: ContentField | null; } -export interface EffortGraphQueryResult { +export interface ProofQueryResult { allEfforts: EffortRecord[]; allIssues: IssueRecord[]; allFindings: FindingRecord[]; diff --git a/packages/explorer/src/web/presets/effort-graph/types.ts b/packages/explorer/src/web/presets/proof/types.ts similarity index 96% rename from packages/explorer/src/web/presets/effort-graph/types.ts rename to packages/explorer/src/web/presets/proof/types.ts index c16a3412..19d8ba5b 100644 --- a/packages/explorer/src/web/presets/effort-graph/types.ts +++ b/packages/explorer/src/web/presets/proof/types.ts @@ -41,7 +41,7 @@ export interface GraphEdge { target: string; } -export interface EffortGraph { +export interface Proof { nodes: GraphNode[]; edges: GraphEdge[]; } diff --git a/packages/explorer/src/web/presets/effort-graph/useEffortGraphLive.test.ts b/packages/explorer/src/web/presets/proof/useProofLive.test.ts similarity index 98% rename from packages/explorer/src/web/presets/effort-graph/useEffortGraphLive.test.ts rename to packages/explorer/src/web/presets/proof/useProofLive.test.ts index 98b20298..01d0ed10 100644 --- a/packages/explorer/src/web/presets/effort-graph/useEffortGraphLive.test.ts +++ b/packages/explorer/src/web/presets/proof/useProofLive.test.ts @@ -9,7 +9,7 @@ import { rollbackRequestedGeneration, shouldCommitGeneration, type LiveStatus, -} from './useEffortGraphLive'; +} from './useProofLive'; import type { SchemaProbeResult } from './query'; const SAMPLE_SCHEMA: SchemaProbeResult = { diff --git a/packages/explorer/src/web/presets/effort-graph/useEffortGraphLive.ts b/packages/explorer/src/web/presets/proof/useProofLive.ts similarity index 94% rename from packages/explorer/src/web/presets/effort-graph/useEffortGraphLive.ts rename to packages/explorer/src/web/presets/proof/useProofLive.ts index ff4db3d4..410a1adc 100644 --- a/packages/explorer/src/web/presets/effort-graph/useEffortGraphLive.ts +++ b/packages/explorer/src/web/presets/proof/useProofLive.ts @@ -1,11 +1,11 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import { resolveEventsUrl, resolveGraphqlEndpoint } from '../../core/endpoints'; import { graphqlFetch } from '../../core/graphql'; -import { normalizeEffortGraph } from './normalize'; +import { normalizeProof } from './normalize'; import { SCHEMA_PROBE_QUERY, - buildEffortGraphQuery, - type EffortGraphQueryResult, + buildProofQuery, + type ProofQueryResult, type SchemaProbeResult, } from './query'; import type { GraphEdge, GraphNode } from './types'; @@ -14,7 +14,7 @@ const INITIAL_RETRY_MS = 1_000; const MAX_RETRY_MS = 30_000; /** - * Live connection / query state for the Effort Graph viz. + * Live connection / query state for the Proof viz. * * - `live` — fetch succeeded with a known schema, so relationship fields * (including retirement links) were selected when the server exposes them. @@ -31,11 +31,11 @@ export type LiveStatus = | 'disconnected' | 'error'; -export interface UseEffortGraphLiveOptions { +export interface UseProofLiveOptions { endpoint?: string; } -export interface UseEffortGraphLiveResult { +export interface UseProofLiveResult { nodes: GraphNode[]; edges: GraphEdge[]; generation: number | null; @@ -133,9 +133,9 @@ function parseGeneration(data: string): number | null { } } -export function useEffortGraphLive( - options: UseEffortGraphLiveOptions = {} -): UseEffortGraphLiveResult { +export function useProofLive( + options: UseProofLiveOptions = {} +): UseProofLiveResult { const endpoint = options.endpoint ?? resolveGraphqlEndpoint(); const eventsUrl = resolveEventsUrl(endpoint); @@ -177,16 +177,16 @@ export function useEffortGraphLive( } catch { // Sticky last-good: a transient introspection failure must not wipe the // filtered relation selection. On first load (no cache) pass null so - // buildEffortGraphQuery takes the scalars-only safe path. + // buildProofQuery takes the scalars-only safe path. } const schema = resolveSchemaForQuery(probed, lastGoodSchemaRef.current); - const data = await graphqlFetch( - buildEffortGraphQuery(schema), + const data = await graphqlFetch( + buildProofQuery(schema), undefined, endpoint ); - const graph = normalizeEffortGraph(data); + const graph = normalizeProof(data); return { nodes: graph.nodes, edges: graph.edges, diff --git a/packages/explorer/tsconfig.json b/packages/explorer/tsconfig.json index d021a351..729f6761 100644 --- a/packages/explorer/tsconfig.json +++ b/packages/explorer/tsconfig.json @@ -18,7 +18,7 @@ "@flatbread/resolver-svimg": ["./packages/resolver-svimg/src/index.ts"], "@flatbread/utils": ["./packages/utils/src/index.ts"], "@flatbread/explorer": ["./packages/explorer/src/node/index.ts"], - "@flatbread/effort-graph": ["./packages/effort-graph/src/index.ts"], + "@flatbread/proof": ["./packages/proof/src/index.ts"], "@flatbread/source-filesystem": [ "./packages/source-filesystem/src/index.ts" ], diff --git a/packages/explorer/tsup.config.ts b/packages/explorer/tsup.config.ts index 52f0c653..06a45f71 100644 --- a/packages/explorer/tsup.config.ts +++ b/packages/explorer/tsup.config.ts @@ -10,5 +10,5 @@ export default defineConfig({ minify: false, treeshake: true, tsconfig: 'tsconfig.node.json', - external: ['@flatbread/effort-graph', 'node:path', 'node:url'], + external: ['@flatbread/proof', 'node:path', 'node:url'], }); diff --git a/packages/flatbread/README.md b/packages/flatbread/README.md index 56d44fe8..d004926b 100644 --- a/packages/flatbread/README.md +++ b/packages/flatbread/README.md @@ -24,15 +24,15 @@ CLI. People use it two ways. **Durable memory for coding agents.** The -[Effort Graph](https://github.com/FlatbreadLabs/flatbread/tree/main/packages/effort-graph) +[Proof](https://github.com/FlatbreadLabs/flatbread/tree/main/packages/proof) stores an agent's reasoning as markdown records in the repository: Efforts, Issues, Findings, Decisions, Constraints, Risks, Citations, and Blobs. An agent -writes them with `flatbread effort write` and reads them back through bounded -queries such as `flatbread effort list` and -`flatbread effort blocking-decisions`. Records live under -`.flatbread-efforts/`, so you commit, review, diff, and revert them like any +writes them with `flatbread proof write` and reads them back through bounded +queries such as `flatbread proof list` and +`flatbread proof blocking-decisions`. Records live under +`.flatbread-proof/`, so you commit, review, diff, and revert them like any other file, and the memory outlives the session that produced it. The bundled -[Effort Graph skill](https://github.com/FlatbreadLabs/flatbread/blob/main/packages/effort-graph/skills/effort-graph/SKILL.md) +[Proof skill](https://github.com/FlatbreadLabs/flatbread/blob/main/packages/proof/skills/proof/SKILL.md) teaches an agent the commands. **Relational content for sites, docs, and internal tools.** Markdown and YAML @@ -288,10 +288,10 @@ Point **`content`** entries at **your** `posts/` and **`authors/`** folders, reu More detail on the bundled example is in the [Next.js example README](https://github.com/FlatbreadLabs/flatbread/blob/main/examples/nextjs/README.md). -For agent memory instead of site content, add `effortGraphContent()` to your -config, then run `flatbread effort bootstrap` to check the setup and -`flatbread effort bootstrap --verify` to fail when something is missing. The -[Effort Graph README](https://github.com/FlatbreadLabs/flatbread/blob/main/packages/effort-graph/README.md) +For agent memory instead of site content, add `proofContent()` to your +config, then run `flatbread proof bootstrap` to check the setup and +`flatbread proof bootstrap --verify` to fail when something is missing. The +[Proof README](https://github.com/FlatbreadLabs/flatbread/blob/main/packages/proof/README.md) has the install commands. ## Query arguments (GraphQL read interface) diff --git a/packages/flatbread/package.json b/packages/flatbread/package.json index c519714c..4531ad23 100644 --- a/packages/flatbread/package.json +++ b/packages/flatbread/package.json @@ -40,7 +40,7 @@ "@flatbread/codegen": "workspace:*", "@flatbread/config": "workspace:*", "@flatbread/core": "workspace:*", - "@flatbread/effort-graph": "workspace:*", + "@flatbread/proof": "workspace:*", "@flatbread/explorer": "workspace:*", "@flatbread/source-filesystem": "workspace:*", "@flatbread/transformer-markdown": "workspace:*", diff --git a/packages/flatbread/src/cli/index.ts b/packages/flatbread/src/cli/index.ts index e1767119..49d5f7f0 100644 --- a/packages/flatbread/src/cli/index.ts +++ b/packages/flatbread/src/cli/index.ts @@ -7,7 +7,7 @@ import { networkInterfaces, release } from 'node:os'; import orchestrateProcesses from './runner'; import initConfig from './initConfig'; import { createCodegenCommand } from '@flatbread/codegen'; -import { registerEffortCommands } from './effort'; +import { registerProofCommands } from './proof'; import { EXPLORER_ENDPOINT, GRAPHQL_ENDPOINT, @@ -137,7 +137,7 @@ prog }); }); -registerEffortCommands(prog); +registerProofCommands(prog); prog.parse(process.argv, { unknown: (arg) => `Unknown option: ${arg}` }); diff --git a/packages/flatbread/src/cli/openPath.test.ts b/packages/flatbread/src/cli/openPath.test.ts index 2beed373..255ab2ba 100644 --- a/packages/flatbread/src/cli/openPath.test.ts +++ b/packages/flatbread/src/cli/openPath.test.ts @@ -1,5 +1,5 @@ import test from 'ava'; -import { effortGraphContent } from '@flatbread/effort-graph'; +import { proofContent } from '@flatbread/proof'; import { explorerAssetsPresent, setExplorerStaticDirOverride, @@ -28,10 +28,10 @@ test.serial( ); return; } - t.is(resolveOpenPath(effortGraphContent()), EXPLORER_ENDPOINT); - t.is(resolveOpenPath(effortGraphContent()), '/'); - t.is(resolveCliOpenPath(effortGraphContent()), EXPLORER_ENDPOINT); - t.is(resolveCliOpenPath(effortGraphContent()), '/'); + t.is(resolveOpenPath(proofContent()), EXPLORER_ENDPOINT); + t.is(resolveOpenPath(proofContent()), '/'); + t.is(resolveCliOpenPath(proofContent()), EXPLORER_ENDPOINT); + t.is(resolveCliOpenPath(proofContent()), '/'); } ); @@ -60,14 +60,14 @@ test.serial( await rm(emptyDir, { recursive: true, force: true }); }); - t.is(resolveOpenPath(effortGraphContent()), GRAPHQL_ENDPOINT); - t.is(resolveOpenPath(effortGraphContent()), '/graphql'); - t.not(resolveOpenPath(effortGraphContent()), EXPLORER_ENDPOINT); - t.not(resolveOpenPath(effortGraphContent()), '/'); + t.is(resolveOpenPath(proofContent()), GRAPHQL_ENDPOINT); + t.is(resolveOpenPath(proofContent()), '/graphql'); + t.not(resolveOpenPath(proofContent()), EXPLORER_ENDPOINT); + t.not(resolveOpenPath(proofContent()), '/'); - t.is(resolveCliOpenPath(effortGraphContent()), GRAPHQL_ENDPOINT); - t.is(resolveCliOpenPath(effortGraphContent()), '/graphql'); - t.not(resolveCliOpenPath(effortGraphContent()), EXPLORER_ENDPOINT); - t.not(resolveCliOpenPath(effortGraphContent()), '/'); + t.is(resolveCliOpenPath(proofContent()), GRAPHQL_ENDPOINT); + t.is(resolveCliOpenPath(proofContent()), '/graphql'); + t.not(resolveCliOpenPath(proofContent()), EXPLORER_ENDPOINT); + t.not(resolveCliOpenPath(proofContent()), '/'); } ); diff --git a/packages/flatbread/src/cli/effort.test.ts b/packages/flatbread/src/cli/proof.test.ts similarity index 91% rename from packages/flatbread/src/cli/effort.test.ts rename to packages/flatbread/src/cli/proof.test.ts index 8a222af0..9b297d82 100644 --- a/packages/flatbread/src/cli/effort.test.ts +++ b/packages/flatbread/src/cli/proof.test.ts @@ -13,9 +13,9 @@ import { } from 'node:fs/promises'; import { join, relative } from 'node:path'; import { tmpdir } from 'node:os'; -import { effortGraphContent } from '@flatbread/effort-graph'; -import { effortGraphContent as publicEffortGraphContent } from '../index.js'; -import { EffortGraphValidationError } from '@flatbread/effort-graph'; +import { proofContent } from '@flatbread/proof'; +import { proofContent as publicProofContent } from '../index.js'; +import { ProofValidationError } from '@flatbread/proof'; import { handleEffortBlockingDecisions, handleEffortBootstrap, @@ -26,7 +26,7 @@ import { handleEffortWrite, inspectEffortBootstrap, mapEffortCliOptions, -} from './effort.js'; +} from './proof.js'; type TeardownContext = { teardown(callback: () => void | Promise): void; @@ -75,15 +75,15 @@ function runCli( }); } -test('public flatbread facade exposes the Effort Graph preset', (t) => { - t.deepEqual(publicEffortGraphContent(), effortGraphContent()); +test('public flatbread facade exposes the Proof preset', (t) => { + t.deepEqual(publicProofContent(), proofContent()); }); test.serial( 'spawned CLI emits JSON bootstrap errors without traces', async (t) => { const cwd = await createTempProject('flatbread-bootstrap-process-', t); - const result = await runCli(cwd, 'effort', 'bootstrap', '--verify'); + const result = await runCli(cwd, 'proof', 'bootstrap', '--verify'); t.not(result.code, 0); t.is(JSON.parse(result.stdout).status, 'action_required'); t.is(result.stderr, ''); @@ -94,14 +94,14 @@ test.serial( 'spawned CLI emits typed JSON validation errors without traces', async (t) => { for (const args of [ - ['effort', 'list', '--status', 'invalid'], - ['effort', 'list', '--limit', '0'], - ['effort', 'list', '--strict-min-generation', '1.5'], + ['proof', 'list', '--status', 'invalid'], + ['proof', 'list', '--limit', '0'], + ['proof', 'list', '--strict-min-generation', '1.5'], ]) { const result = await runCli(process.cwd(), ...args); t.not(result.code, 0); const payload = JSON.parse(result.stderr); - t.regex(payload.error.code, /^EFFORT_GRAPH_INVALID_/); + t.regex(payload.error.code, /^PROOF_INVALID_/); t.false(result.stderr.includes(' at ')); t.is(result.stdout, ''); } @@ -135,19 +135,19 @@ test.serial( 'citations', 'blobs', ]) - await mkdir(join(cwd, '.flatbread-efforts', directory), { + await mkdir(join(cwd, '.flatbread-proof', directory), { recursive: true, }); await writeFile( join(cwd, 'flatbread.config.js'), `import { source } from '@flatbread/source-filesystem'; import { transformer } from '@flatbread/transformer-markdown'; -import { effortGraphContent } from '@flatbread/effort-graph'; +import { proofContent } from '@flatbread/proof'; export default { source: source(), transformer: transformer(), - content: effortGraphContent(${JSON.stringify( - relative(cwd, join(cwd, '.flatbread-efforts')) + content: proofContent(${JSON.stringify( + relative(cwd, join(cwd, '.flatbread-proof')) )}), };` ); @@ -237,18 +237,18 @@ test.serial( 'citations', 'blobs', ]) - await mkdir(join(cwd, '.flatbread-efforts', directory), { + await mkdir(join(cwd, '.flatbread-proof', directory), { recursive: true, }); await writeFile( join(cwd, 'flatbread.config.js'), `import { source } from '@flatbread/source-filesystem'; import { transformer } from '@flatbread/transformer-markdown'; -import { effortGraphContent } from '@flatbread/effort-graph'; +import { proofContent } from '@flatbread/proof'; export default { source: source(), transformer: transformer(), - content: effortGraphContent('.flatbread-efforts'), + content: proofContent('.flatbread-proof'), };` ); const result = await handleEffortGet('dec-missing--0123456789abcdef', { @@ -273,18 +273,18 @@ test.serial( 'citations', 'blobs', ]) - await mkdir(join(cwd, '.flatbread-efforts', directory), { + await mkdir(join(cwd, '.flatbread-proof', directory), { recursive: true, }); await writeFile( join(cwd, 'flatbread.config.js'), `import { source } from '@flatbread/source-filesystem'; import { transformer } from '@flatbread/transformer-markdown'; -import { effortGraphContent } from '@flatbread/effort-graph'; +import { proofContent } from '@flatbread/proof'; export default { source: source(), transformer: transformer(), - content: effortGraphContent('.flatbread-efforts'), + content: proofContent('.flatbread-proof'), };` ); const longBody = [ @@ -342,15 +342,15 @@ test.serial( 'citations', 'blobs', ]) - await mkdir(join(cwd, '.flatbread-efforts', directory), { + await mkdir(join(cwd, '.flatbread-proof', directory), { recursive: true, }); await writeFile( join(cwd, 'flatbread.config.js'), `import { source } from '@flatbread/source-filesystem'; import { transformer } from '@flatbread/transformer-markdown'; -import { effortGraphContent } from '@flatbread/effort-graph'; -export default { source: source(), transformer: transformer(), content: effortGraphContent() };` +import { proofContent } from '@flatbread/proof'; +export default { source: source(), transformer: transformer(), content: proofContent() };` ); const active = await handleEffortWrite( JSON.stringify({ type: 'CreateEffort', title: 'Active', body: '' }), @@ -454,18 +454,18 @@ test.serial( 'citations', 'blobs', ]) - await mkdir(join(cwd, '.flatbread-efforts', directory), { + await mkdir(join(cwd, '.flatbread-proof', directory), { recursive: true, }); await writeFile( join(cwd, 'flatbread.config.js'), `import { source } from '@flatbread/source-filesystem'; import { transformer } from '@flatbread/transformer-markdown'; -import { effortGraphContent } from '@flatbread/effort-graph'; +import { proofContent } from '@flatbread/proof'; export default { source: source(), transformer: transformer(), - content: effortGraphContent('.flatbread-efforts'), + content: proofContent('.flatbread-proof'), };` ); const effort = await handleEffortWrite( @@ -499,7 +499,7 @@ export default { { cwd } ), { - instanceOf: EffortGraphValidationError, + instanceOf: ProofValidationError, message: /CreateEffort does not accept cites/, } ); @@ -541,7 +541,7 @@ export default { { cwd } ), { - instanceOf: EffortGraphValidationError, + instanceOf: ProofValidationError, message: new RegExp( `Citation\\.blob ${foreignBlob.artifacts[0].id} belongs to a different effort` ), @@ -594,7 +594,7 @@ export default { { cwd } ), { - instanceOf: EffortGraphValidationError, + instanceOf: ProofValidationError, message: new RegExp( `cites target ${foreignCitation.artifacts[0].id} belongs to a different effort` ), @@ -661,12 +661,12 @@ test.serial( join(cwd, 'flatbread.config.js'), `import { source } from '@flatbread/source-filesystem'; import { transformer } from '@flatbread/transformer-markdown'; -import { effortGraphContent } from '@flatbread/effort-graph'; -export default { source: source(), transformer: transformer(), content: effortGraphContent('memory/graph') };` +import { proofContent } from '@flatbread/proof'; +export default { source: source(), transformer: transformer(), content: proofContent('memory/graph') };` ); await writeFile( join(cwd, '.gitignore'), - '**/memory/graph/.journal/\n**/.flatbread/effort-graph/read-cache/\n' + '**/memory/graph/.journal/\n**/.flatbread/proof/read-cache/\n' ); const ready = await inspectEffortBootstrap(cwd); t.deepEqual(ready, { diff --git a/packages/flatbread/src/cli/effort.ts b/packages/flatbread/src/cli/proof.ts similarity index 84% rename from packages/flatbread/src/cli/effort.ts rename to packages/flatbread/src/cli/proof.ts index 91598c2e..081164a2 100644 --- a/packages/flatbread/src/cli/effort.ts +++ b/packages/flatbread/src/cli/proof.ts @@ -3,23 +3,23 @@ import { resolve } from 'node:path'; import { loadConfig } from '@flatbread/config'; import { pruneReadCache, - createEffortGraphWriter, - EffortGraphMutationSchema, - EffortGraphValidationError, - EffortGraphReadValidationError, + createProofWriter, + ProofMutationSchema, + ProofValidationError, + ProofReadValidationError, parseGenerationToken, - findEffortGraphContentRoot, + findProofContentRoot, type EffortStatus, type ReadEnvelope, -} from '@flatbread/effort-graph'; +} from '@flatbread/proof'; import { blockingDecisions, effortRecords, relations, getRecord, listEfforts, -} from '../effort/read.js'; -import type { PrimitiveKind, ReadRelation } from '@flatbread/effort-graph'; +} from '../proof/read.js'; +import type { PrimitiveKind, ReadRelation } from '@flatbread/proof'; export interface EffortCliOptions { cwd?: string; @@ -89,10 +89,10 @@ function numberOption(value: unknown): number | undefined { async function rootFor(cwd: string): Promise { const loaded = await loadConfig({ cwd }); - const root = findEffortGraphContentRoot(loaded.config?.content ?? []); + const root = findProofContentRoot(loaded.config?.content ?? []); if (!root) throw new Error( - 'No complete effort-graph preset found in flatbread.config; add effortGraphContent() to content.' + 'No complete proof preset found in flatbread.config; add proofContent() to content.' ); return resolve(cwd, root); } @@ -124,12 +124,12 @@ export async function handleEffortWrite( (raw as Record).type === 'CreateEffort' && 'cites' in raw ) - throw new EffortGraphValidationError( + throw new ProofValidationError( 'CreateEffort does not accept cites; create the Effort before its Citations.' ); - const input = EffortGraphMutationSchema.parse(raw); + const input = ProofMutationSchema.parse(raw); const cwd = options.cwd ?? process.cwd(); - const writer = createEffortGraphWriter({ rootDir: await rootFor(cwd) }); + const writer = createProofWriter({ rootDir: await rootFor(cwd) }); const result = await writer.mutate(input); return { generation: result.generation, @@ -150,7 +150,7 @@ export async function handleEffortGet( return getRecord(id, { cwd, rootDir: await rootFor(cwd), - cacheRoot: resolve(cwd, '.flatbread/effort-graph'), + cacheRoot: resolve(cwd, '.flatbread/proof'), consistency: consistency(options), resolve: options.resolve, }); @@ -165,7 +165,7 @@ export async function handleEffortRecords( return effortRecords(effortId, { cwd, rootDir: await rootFor(cwd), - cacheRoot: resolve(cwd, '.flatbread/effort-graph'), + cacheRoot: resolve(cwd, '.flatbread/proof'), consistency: consistency(options), kinds: options.kinds as PrimitiveKind[] | undefined, where: { @@ -194,7 +194,7 @@ export async function handleEffortRelations( { cwd, rootDir: await rootFor(cwd), - cacheRoot: resolve(cwd, '.flatbread/effort-graph'), + cacheRoot: resolve(cwd, '.flatbread/proof'), consistency: consistency(options), page: { limit: options.limit, cursor: options.cursor }, } @@ -209,7 +209,7 @@ export async function handleEffortBlockingDecisions( return blockingDecisions(effortId, { cwd, rootDir: await rootFor(cwd), - cacheRoot: resolve(cwd, '.flatbread/effort-graph'), + cacheRoot: resolve(cwd, '.flatbread/proof'), consistency: consistency(options), }); } @@ -226,7 +226,7 @@ export interface EffortBootstrapReport { } const CONFIG_PATTERN = /^flatbread\.config\.[mc]?[jt]s$/; -const DEFAULT_GRAPH_ROOT = '.flatbread-efforts'; +const DEFAULT_GRAPH_ROOT = '.flatbread-proof'; function requirement( code: string, @@ -298,15 +298,14 @@ export async function inspectEffortBootstrap( ); } const graphRoot = - findEffortGraphContentRoot(loaded.config?.content ?? []) ?? - DEFAULT_GRAPH_ROOT; + findProofContentRoot(loaded.config?.content ?? []) ?? DEFAULT_GRAPH_ROOT; const requirements: EffortBootstrapReport['requirements'][number][] = []; - if (!findEffortGraphContentRoot(loaded.config?.content ?? [])) + if (!findProofContentRoot(loaded.config?.content ?? [])) requirements.push( requirement( 'EFFORT_BOOTSTRAP_PRESET_MISSING', - 'The config does not contain a complete effortGraphContent preset.', - "Import { effortGraphContent } from 'flatbread' and preserve existing content with content: [...(existingContent ?? []), ...effortGraphContent()]." + 'The config does not contain a complete proofContent preset.', + "Import { proofContent } from 'flatbread' and preserve existing content with content: [...(existingContent ?? []), ...proofContent()]." ) ); let gitignore = ''; @@ -326,21 +325,21 @@ export async function inspectEffortBootstrap( requirements.push( requirement( 'EFFORT_BOOTSTRAP_JOURNAL_IGNORE_MISSING', - `The Effort Graph journal for ${graphRoot} is not ignored.`, + `The Proof journal for ${graphRoot} is not ignored.`, `Add **/${graphRoot}/.journal/ to .gitignore.` ) ); if ( !ignored(lines, [ - '.flatbread/effort-graph/read-cache/', - '.flatbread/effort-graph/read-cache', + '.flatbread/proof/read-cache/', + '.flatbread/proof/read-cache', ]) ) requirements.push( requirement( 'EFFORT_BOOTSTRAP_CACHE_IGNORE_MISSING', - 'The derived Effort Graph read cache is not ignored.', - 'Add **/.flatbread/effort-graph/read-cache/ to .gitignore.' + 'The derived Proof read cache is not ignored.', + 'Add **/.flatbread/proof/read-cache/ to .gitignore.' ) ); return { @@ -372,7 +371,7 @@ export async function handleEffortList( return listEfforts(statuses as EffortStatus[], { cwd, rootDir: await rootFor(cwd), - cacheRoot: resolve(cwd, '.flatbread/effort-graph'), + cacheRoot: resolve(cwd, '.flatbread/proof'), consistency: consistency(options), page: { limit: options.limit, cursor: options.cursor }, }); @@ -384,13 +383,13 @@ function validateLimit(limit: number | undefined): void { (Number.isInteger(limit) && limit >= 1 && limit <= 25) ) return; - throw new EffortGraphReadValidationError( - 'EFFORT_GRAPH_INVALID_ARGUMENT', + throw new ProofReadValidationError( + 'PROOF_INVALID_ARGUMENT', 'page.limit must be an integer between 1 and 25' ); } -export function registerEffortCommands(prog: any): void { +export function registerProofCommands(prog: any): void { const hasShape = ( value: unknown ): value is { shape: Record } => { @@ -410,12 +409,12 @@ export function registerEffortCommands(prog: any): void { payload = JSON.parse(error.message); } catch { payload = { - error: { code: 'EFFORT_CLI_ERROR', message: error.message }, + error: { code: 'PROOF_CLI_ERROR', message: error.message }, }; } } else { payload = { - error: { code: 'EFFORT_CLI_ERROR', message: String(error) }, + error: { code: 'PROOF_CLI_ERROR', message: String(error) }, }; } console.error(JSON.stringify(payload)); @@ -424,12 +423,12 @@ export function registerEffortCommands(prog: any): void { }; prog - .command('effort write ', 'Write a validated Effort Graph mutation') + .command('proof write ', 'Write a validated Proof mutation') .action(async (json: string, options: Record) => printResult(handleEffortWrite(json, mapEffortCliOptions(options))) ); prog - .command('effort get ', 'Read one Effort Graph record') + .command('proof get ', 'Read one Proof record') .option( '--strict-min-generation ', 'Require a durable journal generation' @@ -441,7 +440,7 @@ export function registerEffortCommands(prog: any): void { ); prog .command( - 'effort blocking-decisions ', + 'proof blocking-decisions ', 'Read proposed decisions linked to open blockers' ) .option( @@ -476,13 +475,13 @@ export function registerEffortCommands(prog: any): void { .option('--until ', 'Created-at upper bound') ); recordsOptions( - prog.command('effort records ', 'Read records in an Effort') + prog.command('proof records ', 'Read records in an Effort') ).action(async (effortId: string, options: Record) => printResult(handleEffortRecords(effortId, mapEffortCliOptions(options))) ); paginationOptions( consistencyOptions( - prog.command('effort list', 'List Efforts by lifecycle status') + prog.command('proof list', 'List Efforts by lifecycle status') ) ) .option('--status ', 'Comma-separated Effort statuses', 'active') @@ -490,7 +489,7 @@ export function registerEffortCommands(prog: any): void { printResult(handleEffortList(mapEffortCliOptions(options))) ); prog - .command('effort bootstrap', 'Inspect Effort Graph activation requirements') + .command('proof bootstrap', 'Inspect Proof activation requirements') .option('--verify', 'Exit nonzero when activation is incomplete', false) .action(async (options: Record) => printResult(handleEffortBootstrap(mapEffortCliOptions(options))) @@ -498,7 +497,7 @@ export function registerEffortCommands(prog: any): void { paginationOptions( consistencyOptions( prog.command( - 'effort relations ', + 'proof relations ', 'Read one-hop relations' ) ) @@ -515,10 +514,8 @@ export function registerEffortCommands(prog: any): void { ) ); prog - .command('effort cache prune', 'Prune derived read cache') + .command('proof cache prune', 'Prune derived read cache') .action(async () => - printResult( - pruneReadCache(resolve(process.cwd(), '.flatbread/effort-graph')) - ) + printResult(pruneReadCache(resolve(process.cwd(), '.flatbread/proof'))) ); } diff --git a/packages/flatbread/src/graphql/effortGraphComposition.test.ts b/packages/flatbread/src/graphql/effortGraphComposition.test.ts deleted file mode 100644 index e7395c4b..00000000 --- a/packages/flatbread/src/graphql/effortGraphComposition.test.ts +++ /dev/null @@ -1,68 +0,0 @@ -import test from 'ava'; -import { mkdtemp, rm } from 'node:fs/promises'; -import { tmpdir } from 'node:os'; -import { join } from 'node:path'; -import { effortGraphContent } from '@flatbread/effort-graph'; -import type { - ContentEntry, - LiveSchemaReloader, - SchemaSnapshot, -} from '@flatbread/core'; -import { createEffortGraphComposition } from './effortGraphComposition.js'; - -function fakeReloader(): LiveSchemaReloader { - let generation = 0; - return { - get generation() { - return generation; - }, - getSnapshot: () => ({} as SchemaSnapshot), - notifyChanged: async () => ({ - status: 'committed', - generation: ++generation, - }), - replaceConfig: async () => ({ - status: 'committed', - generation: ++generation, - }), - waitForGeneration: async () => ({} as SchemaSnapshot), - subscribe: () => () => {}, - }; -} - -test.serial( - 'activates for the complete effortGraphContent preset', - async (t) => { - const cwd = await mkdtemp(join(tmpdir(), 'eg-composition-')); - t.teardown(() => rm(cwd, { recursive: true, force: true })); - const content = [ - ...effortGraphContent(), - { collection: 'Other', path: 'other' }, - ]; - const composition = createEffortGraphComposition(content, { cwd }); - t.truthy(composition); - t.is(composition!.rootDir, join(cwd, '.flatbread-efforts')); - t.truthy(composition!.barrier); - const bridge = await composition!.attach(fakeReloader()); - t.is(bridge.rootDir, composition!.rootDir); - t.truthy(bridge.writer); - await bridge.writer.mutate({ type: 'CreateEffort', title: 'E', body: '' }); - t.pass(); - } -); - -test.serial('stays inert for ordinary and lookalike content', (t) => { - t.is( - createEffortGraphComposition([{ collection: 'Post', path: 'posts' }], { - cwd: '/tmp', - }), - undefined - ); - const altered = effortGraphContent().map((entry, index) => - index === 2 ? { ...entry, path: `${entry.path}-altered` } : entry - ); - t.is( - createEffortGraphComposition(altered as ContentEntry[], { cwd: '/tmp' }), - undefined - ); -}); diff --git a/packages/flatbread/src/graphql/explorerMount.test.ts b/packages/flatbread/src/graphql/explorerMount.test.ts index c2cadb97..b97c6470 100644 --- a/packages/flatbread/src/graphql/explorerMount.test.ts +++ b/packages/flatbread/src/graphql/explorerMount.test.ts @@ -10,7 +10,7 @@ import { } from 'node:fs/promises'; import os from 'node:os'; import { join } from 'node:path'; -import { effortGraphContent } from '@flatbread/effort-graph'; +import { proofContent } from '@flatbread/proof'; import { EXPLORER_BOOTSTRAP_PATH, explorerAssetsPresent, @@ -56,7 +56,7 @@ test.serial( if (!requireExplorerAssets(t)) return; const app = express(); - const mounted = mountExplorerIfMatched(app, effortGraphContent()); + const mounted = mountExplorerIfMatched(app, proofContent()); t.truthy(mounted); t.is(mounted!.openPath, '/'); @@ -76,7 +76,7 @@ test.serial( t.is(home.status, 200); const html = await home.text(); t.true(html.includes('__FLATBREAD_EXPLORER__')); - t.true(html.includes('effort-graph')); + t.true(html.includes('proof')); const boot = await fetch(`${server.base}${EXPLORER_BOOTSTRAP_PATH}`); t.is(boot.status, 200); @@ -85,7 +85,7 @@ test.serial( graphqlPath: string; eventsPath: string; }; - t.is(json.preset, 'effort-graph'); + t.is(json.preset, 'proof'); t.is(json.graphqlPath, '/graphql'); t.is(json.eventsPath, '/events'); @@ -113,17 +113,17 @@ test.serial( if (!requireExplorerAssets(t)) return; const app = express(); - const mounted = mountExplorerIfMatched(app, effortGraphContent()); + const mounted = mountExplorerIfMatched(app, proofContent()); t.truthy(mounted); const server = await listen(app); t.teardown(server.close); - const clientRoute = await fetch(`${server.base}/effort-graph/view`); + const clientRoute = await fetch(`${server.base}/proof/view`); t.is(clientRoute.status, 200); const html = await clientRoute.text(); t.true(html.includes('__FLATBREAD_EXPLORER__')); - t.true(html.includes('effort-graph')); + t.true(html.includes('proof')); } ); @@ -133,7 +133,7 @@ test.serial( if (!requireExplorerAssets(t)) return; const app = express(); - const mounted = mountExplorerIfMatched(app, effortGraphContent()); + const mounted = mountExplorerIfMatched(app, proofContent()); t.truthy(mounted); app.use((_req, res) => { @@ -167,7 +167,7 @@ test.serial( } const app = express(); - const mounted = mountExplorerIfMatched(app, effortGraphContent()); + const mounted = mountExplorerIfMatched(app, proofContent()); t.truthy(mounted); const server = await listen(app); @@ -225,7 +225,7 @@ test.serial( }); const app = express(); - const mounted = mountExplorerIfMatched(app, effortGraphContent()); + const mounted = mountExplorerIfMatched(app, proofContent()); t.is(mounted, null); t.true( warnings.some((message) => @@ -264,7 +264,7 @@ test.serial( }); const app = express(); - const handle = mountExplorer(app, effortGraphContent()); + const handle = mountExplorer(app, proofContent()); t.true(handle.isActive()); const server = await listen(app); @@ -275,7 +275,7 @@ test.serial( t.true((await homeActive.text()).includes('__FLATBREAD_EXPLORER__')); setExplorerStaticDirOverride(emptyDir); - handle.update(effortGraphContent()); + handle.update(proofContent()); t.false(handle.isActive()); t.is( warnings.filter((message) => @@ -287,7 +287,7 @@ test.serial( const homeInactive = await fetch(`${server.base}/`); t.false((await homeInactive.text()).includes('__FLATBREAD_EXPLORER__')); - handle.update(effortGraphContent()); + handle.update(proofContent()); t.false(handle.isActive()); t.is( warnings.filter((message) => @@ -297,7 +297,7 @@ test.serial( ); setExplorerStaticDirOverride(undefined); - handle.update(effortGraphContent()); + handle.update(proofContent()); t.true(handle.isActive()); const homeRestored = await fetch(`${server.base}/`); @@ -334,7 +334,7 @@ test.serial( }); const app = express(); - const handle = mountExplorer(app, effortGraphContent()); + const handle = mountExplorer(app, proofContent()); t.true(handle.isActive()); const server = await listen(app); @@ -343,7 +343,7 @@ test.serial( await unlink(indexHtmlPath); await mkdir(indexHtmlPath); - handle.update(effortGraphContent()); + handle.update(proofContent()); t.false(handle.isActive()); t.is( warnings.filter((message) => diff --git a/packages/flatbread/src/graphql/explorerMount.ts b/packages/flatbread/src/graphql/explorerMount.ts index 806c069d..9b5d4de1 100644 --- a/packages/flatbread/src/graphql/explorerMount.ts +++ b/packages/flatbread/src/graphql/explorerMount.ts @@ -55,7 +55,7 @@ export function mountExplorer( let active = false; let indexHtml = ''; let bootstrap: ExplorerBootstrap = { - preset: 'effort-graph', + preset: 'proof', graphqlPath: GRAPHQL_PATH, eventsPath: EVENTS_PATH, }; diff --git a/packages/flatbread/src/graphql/liveServer.ts b/packages/flatbread/src/graphql/liveServer.ts index 01fabad2..8cec1b51 100644 --- a/packages/flatbread/src/graphql/liveServer.ts +++ b/packages/flatbread/src/graphql/liveServer.ts @@ -10,7 +10,7 @@ import { createWatchCoordinator, type WatchCoordinator, } from '@flatbread/core'; -import type { EffortGraphLiveBridge } from '@flatbread/effort-graph'; +import type { ProofLiveBridge } from '@flatbread/proof'; import { ApolloServer } from '@apollo/server'; import { expressMiddleware } from '@as-integrations/express5'; import { InMemoryLRUCache } from '@apollo/utils.keyvaluecache'; @@ -18,7 +18,7 @@ import cors from 'cors'; import express, { type RequestHandler } from 'express'; import http from 'http'; import { loadFlatbreadConfig } from '../utils/getSchema'; -import { createEffortGraphComposition } from './effortGraphComposition'; +import { createProofComposition } from './proofComposition'; import { mountExplorer } from './explorerMount'; import { buildWatchIgnore } from './watchIgnore'; @@ -61,7 +61,7 @@ export interface GraphqlServerOptions { export interface RunningGraphqlServer { readonly port: number; readonly reloader: LiveSchemaReloader; - readonly effortGraph?: EffortGraphLiveBridge; + readonly proof?: ProofLiveBridge; /** * Whether the explorer SPA currently answers `/`. * May change under `--watch` when config reload adds or removes a matching @@ -77,10 +77,10 @@ export async function startGraphqlServer( const cwd = options.cwd ?? process.cwd(); if (!options.config.config) throw new Error('Config is not defined'); const config = options.config.config; - const composition = createEffortGraphComposition(config.content, { cwd }); + const composition = createProofComposition(config.content, { cwd }); if (composition && !config.source.fetchPaths) { throw new Error( - 'Flatbread effort-graph mode requires the configured source to implement fetchPaths(paths).' + 'Flatbread proof mode requires the configured source to implement fetchPaths(paths).' ); } if (options.watch && !config.source.fetchPaths) { @@ -218,12 +218,12 @@ export async function startGraphqlServer( res.on('error', cleanup); }); app.use((req, res, next) => currentMiddleware(req, res, next)); - const effortGraph = await composition?.attach(reloader); - if (effortGraph) { + const proof = await composition?.attach(reloader); + if (proof) { try { - await effortGraph.writer.recover(); + await proof.writer.recover(); } catch (error) { - console.error('Flatbread effort-graph recovery failed:', error); + console.error('Flatbread proof recovery failed:', error); } } await new Promise((listenResolve) => @@ -324,7 +324,7 @@ export async function startGraphqlServer( return { port, reloader, - effortGraph, + proof, get explorer() { return explorerHandle.isActive(); }, diff --git a/packages/flatbread/src/graphql/liveServerExplorerWatch.test.ts b/packages/flatbread/src/graphql/liveServerExplorerWatch.test.ts index 977f9a1f..6d8d7d95 100644 --- a/packages/flatbread/src/graphql/liveServerExplorerWatch.test.ts +++ b/packages/flatbread/src/graphql/liveServerExplorerWatch.test.ts @@ -5,7 +5,7 @@ import { join, relative } from 'node:path'; import filesystem from '@flatbread/source-filesystem'; import markdownTransformer from '@flatbread/transformer-markdown'; import { initializeConfig } from '@flatbread/core'; -import { effortGraphContent } from '@flatbread/effort-graph'; +import { proofContent } from '@flatbread/proof'; import { explorerAssetsPresent, setExplorerStaticDirOverride, @@ -41,7 +41,7 @@ function config( source: filesystem(), transformer: markdownTransformer(), content: active - ? effortGraphContent(root) + ? proofContent(root) : [{ collection: 'Plain', path: `${root}/plain` }], }), }; @@ -91,7 +91,7 @@ test.serial( requireExplorerAssets(); const app = express(); - const handle = mountExplorer(app, effortGraphContent('.flatbread-efforts')); + const handle = mountExplorer(app, proofContent('.flatbread-proof')); t.true(handle.isActive()); app.post('/graphql', (_req, res) => { @@ -120,7 +120,7 @@ test.serial( t.is(graphql.status, 200); t.true((await graphql.text()).includes('"ok":true')); - handle.update(effortGraphContent('.flatbread-efforts')); + handle.update(proofContent('.flatbread-proof')); t.true(handle.isActive()); const homeReenabled = await fetch(`${server.base}/`); diff --git a/packages/flatbread/src/graphql/liveServerEffortGraph.test.ts b/packages/flatbread/src/graphql/liveServerProof.test.ts similarity index 90% rename from packages/flatbread/src/graphql/liveServerEffortGraph.test.ts rename to packages/flatbread/src/graphql/liveServerProof.test.ts index 9b8f3d92..28004cdc 100644 --- a/packages/flatbread/src/graphql/liveServerEffortGraph.test.ts +++ b/packages/flatbread/src/graphql/liveServerProof.test.ts @@ -6,13 +6,13 @@ import { join, relative } from 'node:path'; import filesystem from '@flatbread/source-filesystem'; import markdownTransformer from '@flatbread/transformer-markdown'; import { initializeConfig } from '@flatbread/core'; -import { effortGraphContent } from '@flatbread/effort-graph'; +import { proofContent } from '@flatbread/proof'; import { explorerAssetsPresent, setExplorerStaticDirOverride, } from '@flatbread/explorer'; import type { ConfigResult, LoadedFlatbreadConfig } from '@flatbread/core'; -import type { EffortGraphMutation } from '@flatbread/effort-graph'; +import type { ProofMutation } from '@flatbread/proof'; import { startGraphqlServer } from './liveServer.js'; async function makeDir() { @@ -42,7 +42,7 @@ function config( source: filesystem(), transformer: markdownTransformer(), content: active - ? effortGraphContent(root) + ? proofContent(root) : [{ collection: 'Plain', path: `${root}/plain` }], }), }; @@ -182,17 +182,17 @@ test.serial( port: 0, }); t.teardown(() => server.close()); - t.truthy(server.effortGraph); + t.truthy(server.proof); t.true(server.explorer); const home = await fetch(`http://localhost:${server.port}/`); t.is(home.status, 200); t.true((await home.text()).includes('__FLATBREAD_EXPLORER__')); - const result = await server.effortGraph!.writer.mutate({ + const result = await server.proof!.writer.mutate({ type: 'CreateEffort', title: 'Committed effort', body: '', }); - await server.effortGraph!.waitForCommittedGeneration(result.generation); + await server.proof!.waitForCommittedGeneration(result.generation); const response = await query(server.port, '{ allEfforts { title } }'); t.deepEqual(response.errors, undefined); t.deepEqual(response.data?.allEfforts, [{ title: 'Committed effort' }]); @@ -256,18 +256,18 @@ test.serial( t.teardown(() => server.close()); t.false(server.explorer); - t.truthy(server.effortGraph); + t.truthy(server.proof); const home = await fetch(`http://localhost:${server.port}/`); t.not(home.headers.get('content-type') ?? '', 'text/html'); t.false((await home.text()).includes('__FLATBREAD_EXPLORER__')); - const created = await server.effortGraph!.writer.mutate({ + const created = await server.proof!.writer.mutate({ type: 'CreateEffort', title: 'GraphQL without explorer assets', body: '', }); - await server.effortGraph!.waitForCommittedGeneration(created.generation); + await server.proof!.waitForCommittedGeneration(created.generation); const response = await query(server.port, '{ allEfforts { title } }'); t.deepEqual(response.errors, undefined); t.deepEqual(response.data?.allEfforts, [ @@ -277,7 +277,7 @@ test.serial( ); test.serial( - 'inactive config exposes no effortGraph and behaves as before', + 'inactive config exposes no proof and behaves as before', async (t) => { const fixture = await makeDir(); t.teardown(() => rm(fixture.dir, { recursive: true, force: true })); @@ -286,7 +286,7 @@ test.serial( port: 0, }); t.teardown(() => server.close()); - t.is(server.effortGraph, undefined); + t.is(server.proof, undefined); t.false(server.explorer); const home = await fetch(`http://localhost:${server.port}/`); // Without an explorer preset, Apollo still owns `/` (catch-all mount). @@ -306,27 +306,27 @@ test.serial( }); t.teardown(() => server.close()); await t.throwsAsync( - server.effortGraph!.writer.mutate({ + server.proof!.writer.mutate({ type: 'CreateEffort', title: 'Invalid', body: '', cites: ['cit-paper--0123456789abcdef'], - } as unknown as EffortGraphMutation), + } as unknown as ProofMutation), { message: /CreateEffort does not accept cites/ } ); - const effort = await server.effortGraph!.writer.mutate({ + const effort = await server.proof!.writer.mutate({ type: 'CreateEffort', title: 'GraphQL cite chain', body: '', }); const effortId = effort.artifacts[0].id; - const otherEffort = await server.effortGraph!.writer.mutate({ + const otherEffort = await server.proof!.writer.mutate({ type: 'CreateEffort', title: 'Other chain', body: '', }); const otherEffortId = otherEffort.artifacts[0].id; - const blob = await server.effortGraph!.writer.mutate({ + const blob = await server.proof!.writer.mutate({ type: 'WriteBlob', effort: effortId, title: 'Payload', @@ -334,7 +334,7 @@ test.serial( kind: 'markdown', }); const blobId = blob.artifacts[0].id; - const citation = await server.effortGraph!.writer.mutate({ + const citation = await server.proof!.writer.mutate({ type: 'WriteCitation', effort: effortId, title: 'Paper', @@ -342,7 +342,7 @@ test.serial( role: 'evidence', blob: blobId, }); - await server.effortGraph!.waitForCommittedGeneration(citation.generation); + await server.proof!.waitForCommittedGeneration(citation.generation); const response = await query( server.port, `{ allCitations { title blob { id title } } allBlobs { id title } }` @@ -352,14 +352,14 @@ test.serial( { title: 'Paper', blob: { id: blobId, title: 'Payload' } }, ]); t.deepEqual(response.data?.allBlobs, [{ id: blobId, title: 'Payload' }]); - const foreignBlob = await server.effortGraph!.writer.mutate({ + const foreignBlob = await server.proof!.writer.mutate({ type: 'WriteBlob', effort: otherEffortId, title: 'Foreign payload', body: '', }); await t.throwsAsync( - server.effortGraph!.writer.mutate({ + server.proof!.writer.mutate({ type: 'WriteCitation', effort: effortId, title: 'Bad source', @@ -372,14 +372,14 @@ test.serial( ), } ); - const foreignCitation = await server.effortGraph!.writer.mutate({ + const foreignCitation = await server.proof!.writer.mutate({ type: 'WriteCitation', effort: otherEffortId, title: 'Foreign paper', body: 'https://example.com/foreign-paper', }); await t.throwsAsync( - server.effortGraph!.writer.mutate({ + server.proof!.writer.mutate({ type: 'WriteFinding', effort: effortId, title: 'Bad cite', @@ -393,7 +393,7 @@ test.serial( ), } ); - const finding = await server.effortGraph!.writer.mutate({ + const finding = await server.proof!.writer.mutate({ type: 'WriteFinding', effort: effortId, title: 'Measured', @@ -401,7 +401,7 @@ test.serial( kind: 'measurement', cites: [citation.artifacts[0].id], }); - await server.effortGraph!.waitForCommittedGeneration(finding.generation); + await server.proof!.waitForCommittedGeneration(finding.generation); const findingResponse = await query( server.port, `{ allFindings { title cites { id } } }` @@ -458,7 +458,7 @@ test.serial( ).generation, 7 ); - const snapshot = await server.effortGraph!.waitForCommittedGeneration('7'); + const snapshot = await server.proof!.waitForCommittedGeneration('7'); t.is(snapshot.generation, 1); } ); diff --git a/packages/flatbread/src/graphql/proofComposition.test.ts b/packages/flatbread/src/graphql/proofComposition.test.ts new file mode 100644 index 00000000..8245565c --- /dev/null +++ b/packages/flatbread/src/graphql/proofComposition.test.ts @@ -0,0 +1,62 @@ +import test from 'ava'; +import { mkdtemp, rm } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { proofContent } from '@flatbread/proof'; +import type { + ContentEntry, + LiveSchemaReloader, + SchemaSnapshot, +} from '@flatbread/core'; +import { createProofComposition } from './proofComposition.js'; + +function fakeReloader(): LiveSchemaReloader { + let generation = 0; + return { + get generation() { + return generation; + }, + getSnapshot: () => ({} as SchemaSnapshot), + notifyChanged: async () => ({ + status: 'committed', + generation: ++generation, + }), + replaceConfig: async () => ({ + status: 'committed', + generation: ++generation, + }), + waitForGeneration: async () => ({} as SchemaSnapshot), + subscribe: () => () => {}, + }; +} + +test.serial('activates for the complete proofContent preset', async (t) => { + const cwd = await mkdtemp(join(tmpdir(), 'eg-composition-')); + t.teardown(() => rm(cwd, { recursive: true, force: true })); + const content = [...proofContent(), { collection: 'Other', path: 'other' }]; + const composition = createProofComposition(content, { cwd }); + t.truthy(composition); + t.is(composition!.rootDir, join(cwd, '.flatbread-proof')); + t.truthy(composition!.barrier); + const bridge = await composition!.attach(fakeReloader()); + t.is(bridge.rootDir, composition!.rootDir); + t.truthy(bridge.writer); + await bridge.writer.mutate({ type: 'CreateEffort', title: 'E', body: '' }); + t.pass(); +}); + +test.serial('stays inert for ordinary and lookalike content', (t) => { + t.is( + createProofComposition([{ collection: 'Post', path: 'posts' }], { + cwd: '/tmp', + }), + undefined + ); + const altered = proofContent().map((entry, index) => + index === 2 ? { ...entry, path: `${entry.path}-altered` } : entry + ); + t.is( + createProofComposition(altered as ContentEntry[], { cwd: '/tmp' }), + undefined + ); +}); diff --git a/packages/flatbread/src/graphql/effortGraphComposition.ts b/packages/flatbread/src/graphql/proofComposition.ts similarity index 50% rename from packages/flatbread/src/graphql/effortGraphComposition.ts rename to packages/flatbread/src/graphql/proofComposition.ts index e7d13b28..1523941a 100644 --- a/packages/flatbread/src/graphql/effortGraphComposition.ts +++ b/packages/flatbread/src/graphql/proofComposition.ts @@ -5,28 +5,28 @@ import type { ReindexBarrier, } from '@flatbread/core'; import { - createEffortGraphLiveBridge, + createProofLiveBridge, createJournalReindexBarrier, - findEffortGraphContentRoot, - type EffortGraphLiveBridge, -} from '@flatbread/effort-graph'; + findProofContentRoot, + type ProofLiveBridge, +} from '@flatbread/proof'; -export interface EffortGraphComposition { +export interface ProofComposition { readonly rootDir: string; readonly barrier: ReindexBarrier; - attach(reloader: LiveSchemaReloader): Promise; + attach(reloader: LiveSchemaReloader): Promise; } -export function createEffortGraphComposition( +export function createProofComposition( content: readonly ContentEntry[], options: { cwd: string } -): EffortGraphComposition | undefined { - const presetRoot = findEffortGraphContentRoot(content); +): ProofComposition | undefined { + const presetRoot = findProofContentRoot(content); if (!presetRoot) return undefined; const rootDir = resolve(options.cwd, presetRoot); return { rootDir, barrier: createJournalReindexBarrier({ rootDir }), - attach: (reloader) => createEffortGraphLiveBridge({ rootDir, reloader }), + attach: (reloader) => createProofLiveBridge({ rootDir, reloader }), }; } diff --git a/packages/flatbread/src/index.ts b/packages/flatbread/src/index.ts index 4a3de262..9893c980 100644 --- a/packages/flatbread/src/index.ts +++ b/packages/flatbread/src/index.ts @@ -5,4 +5,4 @@ export { default as defineConfig, loadConfig } from '@flatbread/config'; export { source as sourceFilesystem } from '@flatbread/source-filesystem'; export { transformer as transformerMarkdown } from '@flatbread/transformer-markdown'; export { transformer as transformerYaml } from '@flatbread/transformer-yaml'; -export { effortGraphContent } from '@flatbread/effort-graph'; +export { proofContent } from '@flatbread/proof'; diff --git a/packages/flatbread/src/effort/read.ts b/packages/flatbread/src/proof/read.ts similarity index 96% rename from packages/flatbread/src/effort/read.ts rename to packages/flatbread/src/proof/read.ts index 720dba8e..f19646f7 100644 --- a/packages/flatbread/src/effort/read.ts +++ b/packages/flatbread/src/proof/read.ts @@ -1,9 +1,9 @@ import { FlatbreadProvider, type LoadedFlatbreadConfig } from '@flatbread/core'; import { canonicalizeReadQuery, - EffortGraphConsistencyError, - EffortGraphInvalidCursorError, - EffortGraphReadValidationError, + ProofConsistencyError, + ProofInvalidCursorError, + ProofReadValidationError, READ_RELATIONS, readQueryHash, renderDigest, @@ -13,7 +13,7 @@ import { type ReadRelation, type ConsistencyErrorShape, type PrimitiveKind, -} from '@flatbread/effort-graph'; +} from '@flatbread/proof'; import { loadConfig } from '@flatbread/config'; import { relative, resolve } from 'node:path'; @@ -220,8 +220,8 @@ function decodeCursor( throw new Error('cursor does not match query or served generation'); return value.offset as number; } catch (error) { - if (error instanceof EffortGraphInvalidCursorError) throw error; - throw new EffortGraphInvalidCursorError(`Invalid cursor: ${String(error)}`); + if (error instanceof ProofInvalidCursorError) throw error; + throw new ProofInvalidCursorError(`Invalid cursor: ${String(error)}`); } } @@ -263,13 +263,13 @@ async function servedGeneration( const requestedGeneration = strict?.min_generation ?? String(wanted); const shape: ConsistencyErrorShape = { error: { - code: 'EFFORT_GRAPH_GENERATION_WAIT_TIMEOUT', - message: `Durable Effort Graph generation ${wanted} was not observed (current: ${current})`, + code: 'PROOF_GENERATION_WAIT_TIMEOUT', + message: `Durable Proof generation ${wanted} was not observed (current: ${current})`, requested_generation: requestedGeneration, timeout_ms: timeout, }, }; - throw new EffortGraphConsistencyError(shape); + throw new ProofConsistencyError(shape); } return String(current); } @@ -280,8 +280,8 @@ function parseGenerationToken(value: unknown): number { !/^(0|[1-9]\d*)$/.test(value) || !Number.isSafeInteger(Number(value)) ) - throw new EffortGraphReadValidationError( - 'EFFORT_GRAPH_INVALID_GENERATION', + throw new ProofReadValidationError( + 'PROOF_INVALID_GENERATION', 'strict-min-generation must be a canonical non-negative safe integer string' ); return Number(value); @@ -435,8 +435,8 @@ async function render( const page = query.page as { cursor?: string; limit?: number } | undefined; const limit = page?.limit ?? 25; if (!Number.isInteger(limit) || limit < 1 || limit > 25) - throw new EffortGraphReadValidationError( - 'EFFORT_GRAPH_INVALID_ARGUMENT', + throw new ProofReadValidationError( + 'PROOF_INVALID_ARGUMENT', 'page.limit must be an integer between 1 and 25' ); const offset = page?.cursor @@ -604,8 +604,8 @@ export async function listEfforts( const normalizedStatuses = [...new Set(statuses)]; const invalid = normalizedStatuses.filter((status) => !allowed.has(status)); if (invalid.length) - throw new EffortGraphReadValidationError( - 'EFFORT_GRAPH_INVALID_ARGUMENT', + throw new ProofReadValidationError( + 'PROOF_INVALID_ARGUMENT', `Invalid effort status: ${invalid.join( ', ' )}. Expected active, paused, completed, or abandoned.` diff --git a/packages/effort-graph/README.md b/packages/proof/README.md similarity index 68% rename from packages/effort-graph/README.md rename to packages/proof/README.md index 0b5b40fe..c58f8921 100644 --- a/packages/effort-graph/README.md +++ b/packages/proof/README.md @@ -1,4 +1,4 @@ -# `@flatbread/effort-graph` +# `@flatbread/proof` Git-native memory for coding agents. Installing this package gives you three things: @@ -8,7 +8,7 @@ things: **Decisions**, **Constraints**, **Risks**, **Citations**, and **Blobs**. - **Write operations.** A typed mutation turns into Markdown files on disk, and the writer checks the links between records before it commits them. -- **A Flatbread content model.** `effortGraphContent()` adds those eight record +- **A Flatbread content model.** `proofContent()` adds those eight record types to a Flatbread configuration, so the same files come back as a typed graph you can query and page through. @@ -31,45 +31,45 @@ optional `blob` ref attaches a long payload such as a document, JSON, or image. ## Where records live, and what to ignore -`effortGraphContent()` stores the graph under `.flatbread-efforts` in your +`proofContent()` stores the graph under `.flatbread-proof` in your project root. Pass a path to choose another root: -`effortGraphContent('path/to/graph')`. +`proofContent('path/to/graph')`. Two paths hold working state that Git should not track: the write journal at `/.journal`, and the derived read cache at -`.flatbread/effort-graph/read-cache`. Nothing adds them to `.gitignore` for +`.flatbread/proof/read-cache`. Nothing adds them to `.gitignore` for you, so add these lines yourself: ```gitignore -**/.flatbread-efforts/.journal/ -**/.flatbread/effort-graph/read-cache/ +**/.flatbread-proof/.journal/ +**/.flatbread/proof/read-cache/ ``` -For a custom root, replace `.flatbread-efforts` with that root. The read cache +For a custom root, replace `.flatbread-proof` with that root. The read cache path stays the same. -`flatbread effort bootstrap` reports what is still missing — the config entry -or either ignore rule. `flatbread effort bootstrap --verify` reports the same +`flatbread proof bootstrap` reports what is still missing — the config entry +or either ignore rule. `flatbread proof bootstrap --verify` reports the same and exits nonzero when anything is missing, which makes it usable in CI. ## The domain model and the packaged skill -Read [`skills/effort-graph/glossary.md`](./skills/effort-graph/glossary.md) for -the portable Effort Graph domain model. +Read [`skills/proof/glossary.md`](./skills/proof/glossary.md) for +the portable Proof domain model. -The packaged Agent Skill is in `skills/effort-graph/`. The repository copy in -`.agents/skills/effort-graph/` is generated from those files. Run +The packaged Agent Skill is in `skills/proof/`. The repository copy in +`.agents/skills/proof/` is generated from those files. Run `pnpm skills:sync` from the repository root after changing the skill. -## Install the Effort Graph skill +## Install the Proof skill Install from a release tag, then activate the skill for setup: ```bash -npx skills add https://github.com/FlatbreadLabs/flatbread/tree//packages/effort-graph/skills/effort-graph --skill effort-graph +npx skills add https://github.com/FlatbreadLabs/flatbread/tree//packages/proof/skills/proof --skill proof npm install --save-dev flatbread@ ``` The tag and version come from `gitTag` and `flatbreadVersion` in -`skills/effort-graph/release.json`. See `skills/effort-graph/setup.md` for the +`skills/proof/release.json`. See `skills/proof/setup.md` for the equivalent `pnpm`, `yarn`, and `bun` commands. diff --git a/packages/effort-graph/package.json b/packages/proof/package.json similarity index 88% rename from packages/effort-graph/package.json rename to packages/proof/package.json index 96452944..61eda4ca 100644 --- a/packages/effort-graph/package.json +++ b/packages/proof/package.json @@ -1,5 +1,5 @@ { - "name": "@flatbread/effort-graph", + "name": "@flatbread/proof", "version": "1.0.0", "description": "Git-native memory records for coding agents. Writes typed Effort, Issue, Finding, Decision, Constraint, Risk, Citation, and Blob records to Markdown as journaled changes, and reads them back in bounded pages.", "type": "module", @@ -9,13 +9,13 @@ "skills:sync": "node scripts/sync-skills.mjs", "skills:check": "node scripts/sync-skills.mjs --check", "skills:pack-check": "node scripts/pack-skills.mjs", - "test": "pnpm --dir ../.. exec ava \"packages/effort-graph/src/__tests__/**/*.test.{js,ts}\"", + "test": "pnpm --dir ../.. exec ava \"packages/proof/src/__tests__/**/*.test.{js,ts}\"", "typecheck": "tsc -p tsconfig.json --noEmit" }, "repository": { "type": "git", "url": "git+https://github.com/FlatbreadLabs/flatbread.git", - "directory": "packages/effort-graph" + "directory": "packages/proof" }, "homepage": "https://github.com/FlatbreadLabs/flatbread#readme", "author": "Tony Ketcham ", diff --git a/packages/effort-graph/scripts/pack-skills.mjs b/packages/proof/scripts/pack-skills.mjs similarity index 92% rename from packages/effort-graph/scripts/pack-skills.mjs rename to packages/proof/scripts/pack-skills.mjs index 6f0794f2..2452d963 100644 --- a/packages/effort-graph/scripts/pack-skills.mjs +++ b/packages/proof/scripts/pack-skills.mjs @@ -11,7 +11,7 @@ export const forbiddenInvocation = 'node packages/flatbread/bin/flatbread.js'; export function verifyReleaseIdentity(canonicalTexts, packageVersions) { const entry = canonicalTexts.find( - ({ path }) => path === 'skills/effort-graph/release.json' + ({ path }) => path === 'skills/proof/release.json' ); if (!entry) throw new Error('Canonical skill payload is missing release.json'); @@ -29,7 +29,7 @@ export function verifyReleaseIdentity(canonicalTexts, packageVersions) { if ( release.format !== 1 || release.flatbreadVersion !== packageVersions.flatbreadVersion || - release.effortGraphVersion !== packageVersions.effortGraphVersion || + release.proofVersion !== packageVersions.proofVersion || release.gitTag !== expectedTag ) { throw new Error( @@ -64,7 +64,7 @@ export function verifyPackPayload( if (missing.length > 0) { throw new Error( [ - 'Effort Graph package payload is missing canonical skill files:', + 'Proof package payload is missing canonical skill files:', ...missing.map((file) => ` ${file}`), 'Check the package "files" configuration and run pnpm skills:sync.', ].join('\n') @@ -110,7 +110,7 @@ export async function verifyPackagePayload() { const flatbreadPackage = JSON.parse( await fs.readFile(resolve(packageRoot, '../flatbread/package.json'), 'utf8') ); - const effortGraphPackage = JSON.parse( + const proofPackage = JSON.parse( await fs.readFile(resolve(packageRoot, 'package.json'), 'utf8') ); let output; @@ -142,7 +142,7 @@ export async function verifyPackagePayload() { } verifyPackPayload(payload, canonicalFiles, canonicalTexts, { flatbreadVersion: flatbreadPackage.version, - effortGraphVersion: effortGraphPackage.version, + proofVersion: proofPackage.version, }); return canonicalFiles; } @@ -151,7 +151,7 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) { verifyPackagePayload() .then((files) => { console.log( - `Effort Graph package payload verified (${files.length} skill files).` + `Proof package payload verified (${files.length} skill files).` ); }) .catch((error) => { diff --git a/packages/effort-graph/scripts/sync-skills.mjs b/packages/proof/scripts/sync-skills.mjs similarity index 95% rename from packages/effort-graph/scripts/sync-skills.mjs rename to packages/proof/scripts/sync-skills.mjs index 2b9e7371..5d4a1eda 100644 --- a/packages/effort-graph/scripts/sync-skills.mjs +++ b/packages/proof/scripts/sync-skills.mjs @@ -6,19 +6,19 @@ const scriptDirectory = dirname(fileURLToPath(import.meta.url)); export const repositoryRoot = resolve(scriptDirectory, '../../..'); export const defaultSource = resolve( repositoryRoot, - 'packages/effort-graph/skills/effort-graph' + 'packages/proof/skills/proof' ); export const defaultDestination = resolve( repositoryRoot, - '.agents/skills/effort-graph' + '.agents/skills/proof' ); export const managedSkillNames = [ - 'effort-graph', + 'proof', 'effort-modeling', 'grill-with-efforts', ]; export const managedSkillSources = managedSkillNames.map((name) => - resolve(repositoryRoot, 'packages/effort-graph/skills', name) + resolve(repositoryRoot, 'packages/proof/skills', name) ); async function entries(root) { @@ -139,7 +139,7 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) { if (options.check && changed > 0) { console.error( [ - 'Effort Graph skill projection is out of date:', + 'Proof skill projection is out of date:', ...drift.missing.map((file) => ` missing: ${file}`), ...drift.different.map((file) => ` different: ${file}`), ...drift.stale.map((file) => ` stale: ${file}`), diff --git a/packages/effort-graph/scripts/watch-skills.mjs b/packages/proof/scripts/watch-skills.mjs similarity index 100% rename from packages/effort-graph/scripts/watch-skills.mjs rename to packages/proof/scripts/watch-skills.mjs diff --git a/packages/effort-graph/skills/effort-modeling/CONTEXT-FORMAT.md b/packages/proof/skills/effort-modeling/CONTEXT-FORMAT.md similarity index 91% rename from packages/effort-graph/skills/effort-modeling/CONTEXT-FORMAT.md rename to packages/proof/skills/effort-modeling/CONTEXT-FORMAT.md index 6f0a6461..088a7fc1 100644 --- a/packages/effort-graph/skills/effort-modeling/CONTEXT-FORMAT.md +++ b/packages/proof/skills/effort-modeling/CONTEXT-FORMAT.md @@ -11,4 +11,4 @@ that prevents a common ambiguity. ``` Do not put implementation plans, alternatives, or commitments here. Journal -those in Effort Graph records. +those in Proof records. diff --git a/packages/effort-graph/skills/effort-modeling/DECISION-BODY.md b/packages/proof/skills/effort-modeling/DECISION-BODY.md similarity index 100% rename from packages/effort-graph/skills/effort-modeling/DECISION-BODY.md rename to packages/proof/skills/effort-modeling/DECISION-BODY.md diff --git a/packages/effort-graph/skills/effort-modeling/SKILL.md b/packages/proof/skills/effort-modeling/SKILL.md similarity index 88% rename from packages/effort-graph/skills/effort-modeling/SKILL.md rename to packages/proof/skills/effort-modeling/SKILL.md index fad4dba7..fa9f6504 100644 --- a/packages/effort-graph/skills/effort-modeling/SKILL.md +++ b/packages/proof/skills/effort-modeling/SKILL.md @@ -1,20 +1,20 @@ --- name: effort-modeling -description: Sharpen a project's vocabulary and planning through one-question-at-a-time grilling, then journal Decisions, Constraints, Findings, Issues, and Risks into the Flatbread Effort Graph. Use when a plan needs durable reasoning instead of ADRs. +description: Sharpen a project's vocabulary and planning through one-question-at-a-time grilling, then journal Decisions, Constraints, Findings, Issues, and Risks into the Flatbread Proof. Use when a plan needs durable reasoning instead of ADRs. disable-model-invocation: true --- # Effort modeling Use this discipline while a plan or design is being shaped. Store planning -records in the Effort Graph. Keep project terms in a glossary such as +records in the Proof. Keep project terms in a glossary such as `CONTEXT.md` or `docs/glossary.md`. ## Resume before asking -From the project root, use the `effort-graph` skill's bounded reads: +From the project root, use the `proof` skill's bounded reads: -1. `flatbread effort list --status active` +1. `flatbread proof list --status active` 2. For the relevant Effort, inspect open Issues and blocking Decisions. 3. Read a record or digest when a prior conclusion affects the question. @@ -35,8 +35,8 @@ answer, and resolve prerequisite choices before dependent ones. ## Journal the right speech act -Use `flatbread effort write` for the current Effort, following -[the Effort Graph reference](../effort-graph/reference.md): +Use `flatbread proof write` for the current Effort, following +[the Proof reference](../proof/reference.md): - **Finding** — evidence about code, users, or runtime behavior. - **Issue** — a question, defect, gap, or blocker needing attention. diff --git a/packages/effort-graph/skills/grill-with-efforts/SKILL.md b/packages/proof/skills/grill-with-efforts/SKILL.md similarity index 90% rename from packages/effort-graph/skills/grill-with-efforts/SKILL.md rename to packages/proof/skills/grill-with-efforts/SKILL.md index 16eea0db..0b1f9599 100644 --- a/packages/effort-graph/skills/grill-with-efforts/SKILL.md +++ b/packages/proof/skills/grill-with-efforts/SKILL.md @@ -1,6 +1,6 @@ --- name: grill-with-efforts -description: Run a relentless one-question-at-a-time planning interview that sharpens vocabulary and journals durable reasoning into the Flatbread Effort Graph. Use when a plan is fuzzy and needs an Effort Graph trail instead of ADRs. +description: Run a relentless one-question-at-a-time planning interview that sharpens vocabulary and journals durable reasoning into the Flatbread Proof. Use when a plan is fuzzy and needs an Proof trail instead of ADRs. disable-model-invocation: true --- diff --git a/packages/effort-graph/skills/effort-graph/SKILL.md b/packages/proof/skills/proof/SKILL.md similarity index 74% rename from packages/effort-graph/skills/effort-graph/SKILL.md rename to packages/proof/skills/proof/SKILL.md index 477dc6bc..c711a77d 100644 --- a/packages/effort-graph/skills/effort-graph/SKILL.md +++ b/packages/proof/skills/proof/SKILL.md @@ -1,11 +1,11 @@ --- -name: effort-graph -description: Journal reasoning (decisions, findings, issues, constraints, risks, citations, blobs) into a Flatbread Effort Graph and recall it with bounded reads. Use when starting or resuming a thread of work, recording a decision or finding, resolving an issue, checking what is blocking or still open on an effort, or when the user mentions effort graph, journaling, blocking decisions, agent memory, citation, blob, cites, longform, WriteCitation, or WriteBlob. +name: proof +description: Journal reasoning (decisions, findings, issues, constraints, risks, citations, blobs) into a Flatbread Proof and recall it with bounded reads. Use when starting or resuming a thread of work, recording a decision or finding, resolving an issue, checking what is blocking or still open on an effort, or when the user mentions effort graph, journaling, blocking decisions, agent memory, citation, blob, cites, longform, WriteCitation, or WriteBlob. --- -# Effort Graph — agent journaling and recall +# Proof — agent journaling and recall -The Effort Graph stores durable project memory as markdown records in the +The Proof stores durable project memory as markdown records in the repository. It has eight record types: **Effort**, **Issue**, **Finding**, **Decision**, **Constraint**, and **Risk** capture the work and reasoning; **Citation** stores a source or reference; and **Blob** stores attached @@ -24,7 +24,7 @@ errors print JSON to stderr and exit 1. ## First activation Read [setup.md](./setup.md), make the reviewed config and gitignore edits, then -run `flatbread effort bootstrap` followed by `flatbread effort bootstrap --verify`. Bootstrap is report-only and never edits project files. +run `flatbread proof bootstrap` followed by `flatbread proof bootstrap --verify`. Bootstrap is report-only and never edits project files. ## Prerequisites @@ -35,26 +35,26 @@ import { defineConfig, sourceFilesystem, transformerMarkdown, - effortGraphContent, + proofContent, } from 'flatbread'; export default defineConfig({ source: sourceFilesystem(), transformer: transformerMarkdown(), - content: [...effortGraphContent()], + content: [...proofContent()], }); ``` Records live under `/{efforts,issues,findings,decisions,constraints,risks,citations,blobs}/`. The write journal is `/.journal/`; read digests cache under -`.flatbread/effort-graph/read-cache/` (both gitignored). +`.flatbread/proof/read-cache/` (both gitignored). ## Writing (journaling) One command for all 15 mutations — pass the payload as a single JSON argument: ```bash -flatbread effort write '{"type":"WriteDecision","effort":"","title":"...","body":"...","derives_from":[""]}' +flatbread proof write '{"type":"WriteDecision","effort":"","title":"...","body":"...","derives_from":[""]}' ``` Response: `{"generation":"","artifacts":[{"id","path","operation"}],"touched":[...]}`. @@ -79,7 +79,7 @@ Critical semantics: `cites: [""]` when creating an Issue, Finding, Decision, Constraint, or Risk. Both the Citation in `cites` and the Blob in `Citation.blob` must belong to the same Effort as the record that links to - them. Bounded digests omit Blob bodies; use `effort get ` to read + them. Bounded digests omit Blob bodies; use `proof get ` to read one. - When superseding, open the new record's body with a short rollup of what changed and why — reads render ancestors only as one-line checkpoints. @@ -97,29 +97,29 @@ Read on it, or grep it), `served_generation`, page info, and ≤10 executable `hints`. Digests cap at 25 records / one-hop expansion / 50 edges / 64 KiB. Browse digests (`list`, `records`, `relations`, `blocking-decisions`) excerpt -each body at 600 chars / 12 lines (`[…truncated]`). **`effort get` digests +each body at 600 chars / 12 lines (`[…truncated]`). **`proof get` digests always include the full record body** (still subject to the 64 KiB digest byte cap). Zoom in with `get`, then Read/grep that digest — do not open -`.flatbread-efforts/**/*.md` for normal full-body recall. +`.flatbread-proof/**/*.md` for normal full-body recall. ```bash # What's gating this effort? (proposed Decisions deriving from open blocker Issues) -flatbread effort blocking-decisions +flatbread proof blocking-decisions # Resume: discover active Efforts first -flatbread effort list --status active +flatbread proof list --status active # Scoped listing with filters (AND across flags, OR within comma lists). # --status filters Issues and --state filters Decisions, so combining them in # one call ANDs across kinds and matches nothing — query each kind separately. -flatbread effort records --kinds issue --status open --since 2026-07-01T00:00:00Z --limit 10 -flatbread effort records --kinds decision --state proposed --limit 10 +flatbread proof records --kinds issue --status open --since 2026-07-01T00:00:00Z --limit 10 +flatbread proof records --kinds decision --state proposed --limit 10 # One-hop neighbors of a record -flatbread effort relations --relations derives_from,superseded_by +flatbread proof relations --relations derives_from,superseded_by # Single record with full body; --resolve head follows supersession to the tip -flatbread effort get [--resolve head] +flatbread proof get [--resolve head] ``` Flags shared by reads: `--strict-min-generation ` (with optional @@ -127,33 +127,33 @@ Flags shared by reads: `--strict-min-generation ` (with optional (≤25) and `--cursor` (opaque `next_cursor` from a prior page; only valid for the same query at the same generation). -`effort list` is bounded Effort discovery. It defaults to `active`; valid +`proof list` is bounded Effort discovery. It defaults to `active`; valid statuses are exactly `active`, `paused`, `completed`, and `abandoned`. Comma-separated statuses are ORed. Results use the shared `created_at`, then `id` ordering. After discovery, use bounded effort-scoped reads. **Consistency:** reads are eventual by default. Immediately after a write, pass the returned generation as `--strict-min-generation` — you get either -fresh data or an `EFFORT_GRAPH_GENERATION_WAIT_TIMEOUT` error (exit 1), +fresh data or a `PROOF_GENERATION_WAIT_TIMEOUT` error (exit 1), never silently stale results. Do not build polling loops; the wait is server-side. ## Recommended session workflow -1. **Resume / status briefing (bounded fast-path):** `effort list --status active` +1. **Resume / status briefing (bounded fast-path):** `proof list --status active` and trust the returned digest. For each active Effort, run - `effort records --kinds issue,decision` and read each record's - status/state from that one digest. Run `effort blocking-decisions ` + `proof records --kinds issue,decision` and read each record's + status/state from that one digest. Run `proof blocking-decisions ` only for an Effort whose digest shows an open `blocker` Issue — skip it - otherwise. Do not open raw `.flatbread-efforts/**/*.md` for briefing; + otherwise. Do not open raw `.flatbread-proof/**/*.md` for briefing; browse digests are authoritative for status/state. Budget ≈ (1 + number of active Efforts) digest reads. A 12-run experiment across three model families showed this roughly halves recall tool calls with no loss of answer quality (Decision `dec-adopt-a-bounded-status-briefing-fast-path-for-ef--kcw0rw39g3b2ym2h`). 2. **When a browse digest shows `[…truncated]` and you need the body:** run - `flatbread effort get `, then Read/grep that digest (`artifact_path`) - for the full body. Reserve opening `.flatbread-efforts/**/*.md` for rare + `flatbread proof get `, then Read/grep that digest (`artifact_path`) + for the full body. Reserve opening `.flatbread-proof/**/*.md` for rare cases (e.g. digest byte-cap miss on an oversized record), not normal zoom-in. 3. **During work:** when outside material supports a record, save large @@ -165,5 +165,5 @@ server-side. they respond to. 4. **On commitment:** `AcceptDecision` (mind `rejectSiblings`), `ResolveIssue` with `resolvedBy` citing the closing Decision/Findings. -5. Maintenance: `flatbread effort cache prune` deletes digests older than +5. Maintenance: `flatbread proof cache prune` deletes digests older than 24h / over the 100 MiB ceiling. diff --git a/packages/effort-graph/skills/effort-graph/glossary.md b/packages/proof/skills/proof/glossary.md similarity index 92% rename from packages/effort-graph/skills/effort-graph/glossary.md rename to packages/proof/skills/proof/glossary.md index 7ca533e5..fd002a10 100644 --- a/packages/effort-graph/skills/effort-graph/glossary.md +++ b/packages/proof/skills/proof/glossary.md @@ -1,6 +1,6 @@ -# Effort Graph glossary +# Proof glossary -The Effort Graph is persistent, queryable memory for long-horizon software +The Proof is persistent, queryable memory for long-horizon software work. It builds on Flatbread's content vocabulary: each primitive is a Collection, its instances are Records, and cross-primitive references are Relations in frontmatter. @@ -63,7 +63,7 @@ have a proposed/accepted lifecycle. They are ordinary Flatbread content: filesystem-backed today, with other sources such as S3 or a CDN possible later. Records do not cite Blobs directly. Instead, they cite a Citation, which may optionally point to a Blob. Bounded digests omit Blob bodies by -default; use `effort get ` to read the content. +default; use `proof get ` to read the content. ## Edges @@ -74,8 +74,8 @@ writer-materialized reverse projections. `cites` links an Issue, Finding, Decision, Constraint, or Risk to a Citation. It accepts Citation ids only, never Blob ids. A Citation may optionally point -to a Blob. Both links must stay within the same Effort. `flatbread effort relations` follows `cites` links, but does not follow Blob attachments; use -`flatbread effort get ` to read an attachment. +to a Blob. Both links must stay within the same Effort. `flatbread proof relations` follows `cites` links, but does not follow Blob attachments; use +`flatbread proof get ` to read an attachment. New edge vocabulary needs a dogfooded query the existing vocabulary cannot express. diff --git a/packages/effort-graph/skills/effort-graph/reference.md b/packages/proof/skills/proof/reference.md similarity index 77% rename from packages/effort-graph/skills/effort-graph/reference.md rename to packages/proof/skills/proof/reference.md index 8f544677..7ebeb271 100644 --- a/packages/effort-graph/skills/effort-graph/reference.md +++ b/packages/proof/skills/proof/reference.md @@ -1,4 +1,4 @@ -# Effort Graph — full API reference +# Proof — full API reference Ground truth: the installed `flatbread` CLI and this reference (mutations), reads, and configuration examples. Repository implementation files are not @@ -11,7 +11,7 @@ Generated as `---<16-char-crockford>` with prefixes `eff`, identity. Let the writer generate ids; capture them from mutation results (`artifacts[0].id` for creates). -## The 15 mutations (`flatbread effort write ''`) +## The 15 mutations (`flatbread proof write ''`) Common optional fields on all creates: `id`, `created_at` (ISO with offset), `produced_in`, `created_by` (opaque provenance strings). Forward edge fields @@ -95,7 +95,7 @@ the generated schema) and return a `ReadEnvelope`: ```json { "summary": "2 records; proposed 2; complete", - "artifact_path": ".flatbread/effort-graph/read-cache//.md", + "artifact_path": ".flatbread/proof/read-cache//.md", "artifact_sha256": "...", "served_generation": "55", "consistency": { "mode": "eventual|strict", "min_generation": null }, @@ -108,11 +108,11 @@ The digest at `artifact_path` is deterministic markdown: YAML query header, anchor index, per-record sections (selected frontmatter, body, relation lists), one-hop related records, and an edge table. Body policy: -- **`effort get`:** full record body (the normal zoom-in path), including +- **`proof get`:** full record body (the normal zoom-in path), including Blob payloads and Citation bodies (URLs / short notes). - **`list` / `records` / `relations` / `blocking-decisions`:** body excerpt capped at 600 chars / 12 lines (`[…truncated]`). **Blob bodies are omitted** - from these digests — use `effort get` for the payload. Citation bodies + from these digests — use `proof get` for the payload. Citation bodies (usually short) still excerpt normally. Caps: 25 primary records, one hop, 50 edges, 64 KiB; hitting a cap sets @@ -124,12 +124,12 @@ full body via the 600/12 excerpt). ### Commands ```bash -flatbread effort get [--resolve exact|head] [consistency flags] -flatbread effort list [--status active,paused,...] [--limit n] [--cursor c] [consistency flags] -flatbread effort records [--kinds k1,k2] [--state s1,s2] [--status s1,s2] [--kind k1,k2] [--since iso] [--until iso] [--limit n] [--cursor c] [consistency flags] -flatbread effort relations --relations r1,r2 [--limit n] [--cursor c] [consistency flags] -flatbread effort blocking-decisions [consistency flags] -flatbread effort cache prune +flatbread proof get [--resolve exact|head] [consistency flags] +flatbread proof list [--status active,paused,...] [--limit n] [--cursor c] [consistency flags] +flatbread proof records [--kinds k1,k2] [--state s1,s2] [--status s1,s2] [--kind k1,k2] [--since iso] [--until iso] [--limit n] [--cursor c] [consistency flags] +flatbread proof relations --relations r1,r2 [--limit n] [--cursor c] [consistency flags] +flatbread proof blocking-decisions [consistency flags] +flatbread proof cache prune ``` - `--kinds`: `effort|issue|finding|decision|constraint|risk|citation|blob`. @@ -155,20 +155,20 @@ flatbread effort cache prune - `--strict-min-generation `: serve at or after that journal generation, or fail. `--timeout-ms ` bounds the wait (default 3000). -- Errors (stderr JSON, exit 1): `EFFORT_GRAPH_GENERATION_WAIT_TIMEOUT`, - `EFFORT_GRAPH_INVALID_CURSOR` (cursor reused across a different query or +- Errors (stderr JSON, exit 1): `PROOF_GENERATION_WAIT_TIMEOUT`, + `PROOF_INVALID_CURSOR` (cursor reused across a different query or generation). ## Configuration surface -| Option | Where | Default | Notes | -| ---------------- | --------------------------------------------------- | ------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | -| Graph root | `effortGraphContent(root)` in `flatbread.config.js` | `.flatbread-efforts` | All eight collection paths + refs derive from it; the preset must appear complete and unmodified for detection. | -| Config discovery | cwd of the CLI invocation | — | Exactly one `flatbread.config.*` must exist in cwd. | -| Digest cache | fixed | `/.flatbread/effort-graph/read-cache/` | Generation-keyed; gitignore it. `cache prune`: >24h old deleted, then oldest-first to ≤100 MiB. | -| Journal | fixed | `/.journal/` | Writer-owned; gitignored. Never edit. | -| Strict timeout | `--timeout-ms` per read | 3000 ms | | -| Page limit | `--limit` per read | 25 | Hard max 25. | +| Option | Where | Default | Notes | +| ---------------- | --------------------------------------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------- | +| Graph root | `proofContent(root)` in `flatbread.config.js` | `.flatbread-proof` | All eight collection paths + refs derive from it; the preset must appear complete and unmodified for detection. | +| Config discovery | cwd of the CLI invocation | — | Exactly one `flatbread.config.*` must exist in cwd. | +| Digest cache | fixed | `/.flatbread/proof/read-cache/` | Generation-keyed; gitignore it. `cache prune`: >24h old deleted, then oldest-first to ≤100 MiB. | +| Journal | fixed | `/.journal/` | Writer-owned; gitignored. Never edit. | +| Strict timeout | `--timeout-ms` per read | 3000 ms | | +| Page limit | `--limit` per read | 25 | Hard max 25. | ## What not to do @@ -182,4 +182,4 @@ flatbread effort cache prune `produced_in` / `created_by` fields. - Do not put citation metadata objects into `cites` — use Citation records (body/role/optional blob) and bare Citation ids in `cites`. -- Do not expect Blob bodies in list/records digests; zoom with `effort get`. +- Do not expect Blob bodies in list/records digests; zoom with `proof get`. diff --git a/.agents/skills/effort-graph/release.json b/packages/proof/skills/proof/release.json similarity index 68% rename from .agents/skills/effort-graph/release.json rename to packages/proof/skills/proof/release.json index 26e56748..882486f6 100644 --- a/.agents/skills/effort-graph/release.json +++ b/packages/proof/skills/proof/release.json @@ -1,6 +1,6 @@ { "format": 1, "flatbreadVersion": "1.0.0", - "effortGraphVersion": "1.0.0", + "proofVersion": "1.0.0", "gitTag": "v1.0.0" } diff --git a/packages/effort-graph/skills/effort-graph/setup.md b/packages/proof/skills/proof/setup.md similarity index 75% rename from packages/effort-graph/skills/effort-graph/setup.md rename to packages/proof/skills/proof/setup.md index d961a875..aad39548 100644 --- a/packages/effort-graph/skills/effort-graph/setup.md +++ b/packages/proof/skills/proof/setup.md @@ -1,7 +1,7 @@ -# Effort Graph setup +# Proof setup The canonical skill files live in this package. The repository -`.agents/skills/effort-graph/` directory is an exclusively generated +`.agents/skills/proof/` directory is an exclusively generated projection: do not edit it directly, and stale projected files are deleted by `pnpm skills:sync`. @@ -18,20 +18,20 @@ values exactly. `skills-lock.json` is installation provenance/restore data only; do not use its optional ref or version fields as release identity: ```bash -npx skills add https://github.com/FlatbreadLabs/flatbread/tree//packages/effort-graph/skills/effort-graph --skill effort-graph +npx skills add https://github.com/FlatbreadLabs/flatbread/tree//packages/proof/skills/proof --skill proof npm install --save-dev flatbread@ ``` Equivalent commands are: ```bash -pnpm dlx skills add https://github.com/FlatbreadLabs/flatbread/tree//packages/effort-graph/skills/effort-graph --skill effort-graph +pnpm dlx skills add https://github.com/FlatbreadLabs/flatbread/tree//packages/proof/skills/proof --skill proof pnpm add -D flatbread@ -yarn dlx skills add https://github.com/FlatbreadLabs/flatbread/tree//packages/effort-graph/skills/effort-graph --skill effort-graph +yarn dlx skills add https://github.com/FlatbreadLabs/flatbread/tree//packages/proof/skills/proof --skill proof yarn add -D flatbread@ -bunx skills add https://github.com/FlatbreadLabs/flatbread/tree//packages/effort-graph/skills/effort-graph --skill effort-graph +bunx skills add https://github.com/FlatbreadLabs/flatbread/tree//packages/proof/skills/proof --skill proof bun add -d flatbread@ ``` @@ -49,7 +49,7 @@ import { defineConfig, sourceFilesystem, transformerMarkdown, - effortGraphContent, + proofContent, } from 'flatbread'; export default defineConfig({ @@ -57,7 +57,7 @@ export default defineConfig({ transformer: transformerMarkdown(), content: [ // existing entries - ...effortGraphContent(), // or effortGraphContent('path/to/graph') + ...proofContent(), // or proofContent('path/to/graph') ], }); ``` @@ -65,29 +65,29 @@ export default defineConfig({ Add these entries to `.gitignore` (using the selected graph root): ```gitignore -**/.flatbread-efforts/.journal/ -**/.flatbread/effort-graph/read-cache/ +**/.flatbread-proof/.journal/ +**/.flatbread/proof/read-cache/ ``` -For a custom root, replace `.flatbread-efforts` with that root. Review both +For a custom root, replace `.flatbread-proof` with that root. Review both edits before saving; the bootstrap command never creates or rewrites them. ## 3. Verify activation ```bash -flatbread effort bootstrap -flatbread effort bootstrap --verify +flatbread proof bootstrap +flatbread proof bootstrap --verify ``` The second command must print `{"status":"ready",...}` and exit successfully. -On resume, begin with `flatbread effort list --status active`, then use bounded +On resume, begin with `flatbread proof list --status active`, then use bounded effort-scoped reads. Capture mutation `generation` tokens and use `--strict-min-generation` for immediate read-after-write checks; never implement -client polling loops. Semantic changes go through `flatbread effort write`. +client polling loops. Semantic changes go through `flatbread proof write`. ## 4. Open the explorer (optional) -With a complete `effortGraphContent()` preset in config, Flatbread serves the +With a complete `proofContent()` preset in config, Flatbread serves the content-relation explorer automatically (`@flatbread/explorer` ships with `flatbread`): diff --git a/packages/effort-graph/src/__tests__/decision-lifecycle.test.ts b/packages/proof/src/__tests__/decision-lifecycle.test.ts similarity index 92% rename from packages/effort-graph/src/__tests__/decision-lifecycle.test.ts rename to packages/proof/src/__tests__/decision-lifecycle.test.ts index 07528834..4ab39a09 100644 --- a/packages/effort-graph/src/__tests__/decision-lifecycle.test.ts +++ b/packages/proof/src/__tests__/decision-lifecycle.test.ts @@ -1,6 +1,6 @@ import test from 'ava'; -import { EffortGraphValidationError } from '../errors.js'; -import { createEffortGraphSnapshot } from '../snapshot.js'; +import { ProofValidationError } from '../errors.js'; +import { createProofSnapshot } from '../snapshot.js'; import { acceptDecisionLifecycle, supersedeDecisionLifecycle, @@ -16,7 +16,7 @@ function snapshot( states = ['proposed', 'proposed', 'rejected'], foreign = false ) { - return createEffortGraphSnapshot( + return createProofSnapshot( ids.map((id, i) => ({ id, kind: 'decision' as const, @@ -91,7 +91,7 @@ test('25 accepting a non-proposed Decision throws', async (t) => { }) ), { - instanceOf: EffortGraphValidationError, + instanceOf: ProofValidationError, message: 'Decision is not proposed', } ); @@ -103,7 +103,7 @@ test('25 accepting a non-proposed Decision throws', async (t) => { }) ), { - instanceOf: EffortGraphValidationError, + instanceOf: ProofValidationError, message: 'Decision is not proposed', } ); diff --git a/packages/effort-graph/src/__tests__/digest.test.ts b/packages/proof/src/__tests__/digest.test.ts similarity index 99% rename from packages/effort-graph/src/__tests__/digest.test.ts rename to packages/proof/src/__tests__/digest.test.ts index 7d9c9562..c84ae46e 100644 --- a/packages/effort-graph/src/__tests__/digest.test.ts +++ b/packages/proof/src/__tests__/digest.test.ts @@ -198,7 +198,7 @@ test('renderDigest omits Blob bodies from bounded digests', async (t) => { const digest = await readFile(result.artifact_path, 'utf8'); t.false(digest.includes(secret)); t.true(digest.includes('Blob body omitted from bounded digests')); - t.true(digest.includes('effort get ')); + t.true(digest.includes('proof get ')); }); test('renderDigest includes Blob body on fullBody get', async (t) => { diff --git a/packages/effort-graph/src/__tests__/ids.test.ts b/packages/proof/src/__tests__/ids.test.ts similarity index 93% rename from packages/effort-graph/src/__tests__/ids.test.ts rename to packages/proof/src/__tests__/ids.test.ts index d1a07303..87078019 100644 --- a/packages/effort-graph/src/__tests__/ids.test.ts +++ b/packages/proof/src/__tests__/ids.test.ts @@ -3,8 +3,8 @@ import { mkdtemp, readdir } from 'node:fs/promises'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { generateArtifactId, slugify, validateArtifactId } from '../ids.js'; -import { createEffortGraphWriter } from '../writer.js'; -import { EffortGraphValidationError } from '../errors.js'; +import { createProofWriter } from '../writer.js'; +import { ProofValidationError } from '../errors.js'; import type { PrimitiveKind } from '../types.js'; const kinds: [PrimitiveKind, string][] = [ @@ -76,14 +76,14 @@ test('validateArtifactId rejects malformed ids', (t) => { test('writer rejects a stubbed randomBytes collision before writing', async (t) => { const root = await mkdtemp(join(tmpdir(), 'eg-ids-')); - const writer = createEffortGraphWriter({ + const writer = createProofWriter({ rootDir: root, randomBytes: () => new Uint8Array(10).fill(7), }); await writer.mutate({ type: 'CreateEffort', title: 'Same Title', body: '' }); const error = await t.throwsAsync( writer.mutate({ type: 'CreateEffort', title: 'Same Title', body: '' }), - { instanceOf: EffortGraphValidationError } + { instanceOf: ProofValidationError } ); t.truthy(error); const files = await readdir(join(root, 'efforts')); diff --git a/packages/effort-graph/src/__tests__/journal-barrier.test.ts b/packages/proof/src/__tests__/journal-barrier.test.ts similarity index 94% rename from packages/effort-graph/src/__tests__/journal-barrier.test.ts rename to packages/proof/src/__tests__/journal-barrier.test.ts index bc5547d0..ed16d66b 100644 --- a/packages/effort-graph/src/__tests__/journal-barrier.test.ts +++ b/packages/proof/src/__tests__/journal-barrier.test.ts @@ -4,8 +4,8 @@ import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { createJournalReindexBarrier } from '../journalBarrier.js'; import { - EffortGraphBarrierTimeoutError, - EffortGraphCorruptJournalError, + ProofBarrierTimeoutError, + ProofCorruptJournalError, } from '../errors.js'; async function fixture() { @@ -84,7 +84,7 @@ test.serial('fails closed on a malformed active intent', async (t) => { await writeFile(join(txn, 'intent.json'), '{broken'); await t.throwsAsync( createJournalReindexBarrier({ rootDir: root }).waitUntilReadable([path]), - { instanceOf: EffortGraphCorruptJournalError } + { instanceOf: ProofCorruptJournalError } ); }); @@ -98,7 +98,7 @@ test.serial( pollIntervalMs: 2, maxWaitMs: 10, }).waitUntilReadable([path]), - { instanceOf: EffortGraphBarrierTimeoutError } + { instanceOf: ProofBarrierTimeoutError } ); } ); diff --git a/packages/effort-graph/src/__tests__/journal-recovery.test.ts b/packages/proof/src/__tests__/journal-recovery.test.ts similarity index 97% rename from packages/effort-graph/src/__tests__/journal-recovery.test.ts rename to packages/proof/src/__tests__/journal-recovery.test.ts index e022d2cc..cb491ed0 100644 --- a/packages/effort-graph/src/__tests__/journal-recovery.test.ts +++ b/packages/proof/src/__tests__/journal-recovery.test.ts @@ -5,7 +5,7 @@ import { existsSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { recoverJournal } from '../journal.js'; -import { EffortGraphCorruptJournalError } from '../errors.js'; +import { ProofCorruptJournalError } from '../errors.js'; function writeEntry( relativePath: string, @@ -129,7 +129,7 @@ test('corrupt intent.json fails closed', async (t) => { await t.throwsAsync( recoverJournal(root, async () => {}), { - instanceOf: EffortGraphCorruptJournalError, + instanceOf: ProofCorruptJournalError, } ); // The corrupt transaction is left untouched — never guess. diff --git a/packages/effort-graph/src/__tests__/live-bridge.test.ts b/packages/proof/src/__tests__/live-bridge.test.ts similarity index 95% rename from packages/effort-graph/src/__tests__/live-bridge.test.ts rename to packages/proof/src/__tests__/live-bridge.test.ts index d171fe5d..796195bb 100644 --- a/packages/effort-graph/src/__tests__/live-bridge.test.ts +++ b/packages/proof/src/__tests__/live-bridge.test.ts @@ -3,10 +3,10 @@ import { createHash } from 'node:crypto'; import { mkdir, mkdtemp, readdir, readFile, writeFile } from 'node:fs/promises'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; -import { createEffortGraphLiveBridge } from '../live.js'; +import { createProofLiveBridge } from '../live.js'; import { - EffortGraphGenerationWaitTimeoutError, - EffortGraphReindexFailedError, + ProofGenerationWaitTimeoutError, + ProofReindexFailedError, } from '../errors.js'; import type { LiveSchemaReloader, SchemaSnapshot } from '@flatbread/core'; @@ -68,7 +68,7 @@ function fakeReloader(): { async function makeBridge() { const root = await mkdtemp(join(tmpdir(), 'eg-live-')); const fake = fakeReloader(); - const bridge = await createEffortGraphLiveBridge({ + const bridge = await createProofLiveBridge({ rootDir: root, reloader: fake.reloader, }); @@ -142,7 +142,7 @@ test.serial( fake.reject.value = true; await t.throwsAsync( bridge.writer.mutate({ type: 'CreateEffort', title: 'E', body: '' }), - { instanceOf: EffortGraphReindexFailedError } + { instanceOf: ProofReindexFailedError } ); const txns = await readdir(join(root, '.journal', 'txns')); t.is(txns.length, 1); @@ -204,7 +204,7 @@ test.serial( await t.throwsAsync( bridge.waitForCommittedGeneration('1', { timeoutMs: 10 }), { - instanceOf: EffortGraphGenerationWaitTimeoutError, + instanceOf: ProofGenerationWaitTimeoutError, } ); } @@ -219,7 +219,7 @@ test.serial( title: 'E', body: '', }); - const recreated = await createEffortGraphLiveBridge({ + const recreated = await createProofLiveBridge({ rootDir: root, reloader: fake.reloader, }); diff --git a/packages/effort-graph/src/__tests__/lock.test.ts b/packages/proof/src/__tests__/lock.test.ts similarity index 86% rename from packages/effort-graph/src/__tests__/lock.test.ts rename to packages/proof/src/__tests__/lock.test.ts index 11169774..158c1d44 100644 --- a/packages/effort-graph/src/__tests__/lock.test.ts +++ b/packages/proof/src/__tests__/lock.test.ts @@ -5,11 +5,8 @@ import { hostname } from 'node:os'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { acquireWriterLock } from '../lock.js'; -import { createEffortGraphWriter } from '../writer.js'; -import { - EffortGraphLockedError, - EffortGraphValidationError, -} from '../errors.js'; +import { createProofWriter } from '../writer.js'; +import { ProofLockedError, ProofValidationError } from '../errors.js'; // A pid above the platform maximum, guaranteed dead. const DEAD_PID = 2 ** 30; @@ -24,13 +21,13 @@ function lockPath(root: string) { return join(root, '.journal', 'writer.lock'); } -test('second concurrent acquire throws EffortGraphLockedError', async (t) => { +test('second concurrent acquire throws ProofLockedError', async (t) => { const root = await makeRoot(); const lock = await acquireWriterLock(root); const error = (await t.throwsAsync(acquireWriterLock(root), { - instanceOf: EffortGraphLockedError, - })) as EffortGraphLockedError; - t.is(error.code, 'EFFORT_GRAPH_LOCKED'); + instanceOf: ProofLockedError, + })) as ProofLockedError; + t.is(error.code, 'PROOF_LOCKED'); t.true(error.retryAfterMs > 0); await lock.release(); // After release a new writer can acquire. @@ -70,7 +67,7 @@ test('expired lease with a live pid is NOT reclaimed', async (t) => { }) ); await t.throwsAsync(acquireWriterLock(root, { leaseMs: 1000 }), { - instanceOf: EffortGraphLockedError, + instanceOf: ProofLockedError, }); }); @@ -87,7 +84,7 @@ test('fresh lease with a dead pid is NOT reclaimed', async (t) => { }) ); await t.throwsAsync(acquireWriterLock(root, { leaseMs: 60_000 }), { - instanceOf: EffortGraphLockedError, + instanceOf: ProofLockedError, }); }); @@ -109,14 +106,14 @@ test('release with a mismatched on-disk token leaves the lock file', async (t) = test('lock is released after a failed mutate so the next mutate succeeds', async (t) => { const root = await mkdtemp(join(tmpdir(), 'eg-lock-writer-')); - const writer = createEffortGraphWriter({ rootDir: root }); + const writer = createProofWriter({ rootDir: root }); await t.throwsAsync( writer.mutate({ type: 'SetEffortStatus', effortId: 'eff-missing--0123456789abcdef', status: 'paused', }), - { instanceOf: EffortGraphValidationError } + { instanceOf: ProofValidationError } ); t.false(existsSync(lockPath(root))); const result = await writer.mutate({ diff --git a/packages/effort-graph/src/__tests__/pack-skills.test.js b/packages/proof/src/__tests__/pack-skills.test.js similarity index 89% rename from packages/effort-graph/src/__tests__/pack-skills.test.js rename to packages/proof/src/__tests__/pack-skills.test.js index 3fd2a324..56f3b469 100644 --- a/packages/effort-graph/src/__tests__/pack-skills.test.js +++ b/packages/proof/src/__tests__/pack-skills.test.js @@ -5,15 +5,15 @@ import { } from '../../scripts/pack-skills.mjs'; const canonicalFiles = [ - 'skills/effort-graph/release.json', - 'skills/effort-graph/SKILL.md', - 'skills/effort-graph/reference.md', - 'skills/effort-graph/setup.md', + 'skills/proof/release.json', + 'skills/proof/SKILL.md', + 'skills/proof/reference.md', + 'skills/proof/setup.md', ]; const release = JSON.stringify({ format: 1, flatbreadVersion: '1.0.0-alpha.22', - effortGraphVersion: '0.1.0-alpha.0', + proofVersion: '0.1.0-alpha.0', gitTag: 'v1.0.0-alpha.22', }); const canonicalTexts = canonicalFiles.map((path) => ({ @@ -22,7 +22,7 @@ const canonicalTexts = canonicalFiles.map((path) => ({ })); const packageVersions = { flatbreadVersion: '1.0.0-alpha.22', - effortGraphVersion: '0.1.0-alpha.0', + proofVersion: '0.1.0-alpha.0', }; test('pack verification accepts canonical skills and release identity', (t) => { diff --git a/packages/effort-graph/src/__tests__/planner.test.ts b/packages/proof/src/__tests__/planner.test.ts similarity index 98% rename from packages/effort-graph/src/__tests__/planner.test.ts rename to packages/proof/src/__tests__/planner.test.ts index 9e699168..92f7370d 100644 --- a/packages/effort-graph/src/__tests__/planner.test.ts +++ b/packages/proof/src/__tests__/planner.test.ts @@ -1,6 +1,6 @@ import test from 'ava'; import { parseDocument, serializeDocument } from '../frontmatter.js'; -import { createEffortGraphSnapshot } from '../snapshot.js'; +import { createProofSnapshot } from '../snapshot.js'; import { planMutation } from '../planner.js'; import type { PrimitiveKind } from '../types.js'; @@ -28,7 +28,7 @@ function snap(extra: any[] = []) { body: 'eb', }, ]; - return createEffortGraphSnapshot( + return createProofSnapshot( [...base, ...extra].map((x) => ({ ...x, rawBytes: serializeDocument(x.body, x.frontmatter), @@ -85,7 +85,7 @@ test('CreateEffort rejects cites before planning a write', (t) => { title: 'New', body: '', cites: ['cit-paper--0123456789abcdef'], - } as unknown as import('../schemas.js').EffortGraphMutation; + } as unknown as import('../schemas.js').ProofMutation; t.throws(() => planMutation(input, snap(), '/root', now), { message: 'CreateEffort does not accept cites; create the Effort before its Citations.', @@ -537,7 +537,7 @@ test('WriteCitation rejects cites before planning a write', (t) => { title: 'Paper', body: 'https://example.com/paper', cites: ['cit-other--0123456789abcdef'], - } as unknown as import('../schemas.js').EffortGraphMutation, + } as unknown as import('../schemas.js').ProofMutation, snap(), '/root', now @@ -556,7 +556,7 @@ test('WriteBlob rejects cites before planning a write', (t) => { title: 'Payload', body: '# longform research\n', cites: ['cit-paper--0123456789abcdef'], - } as unknown as import('../schemas.js').EffortGraphMutation, + } as unknown as import('../schemas.js').ProofMutation, snap(), '/root', now diff --git a/packages/effort-graph/src/__tests__/preset.test.ts b/packages/proof/src/__tests__/preset.test.ts similarity index 80% rename from packages/effort-graph/src/__tests__/preset.test.ts rename to packages/proof/src/__tests__/preset.test.ts index 3dea0aed..1eab63c5 100644 --- a/packages/effort-graph/src/__tests__/preset.test.ts +++ b/packages/proof/src/__tests__/preset.test.ts @@ -1,16 +1,16 @@ import test from 'ava'; -import { effortGraphContent } from '../preset.js'; +import { proofContent } from '../preset.js'; test('returns exactly eight entries with exact paths and refs', (t) => { - const entries = effortGraphContent(); + const entries = proofContent(); t.deepEqual(entries, [ { collection: 'Effort', - path: '.flatbread-efforts/efforts', + path: '.flatbread-proof/efforts', }, { collection: 'Issue', - path: '.flatbread-efforts/issues', + path: '.flatbread-proof/issues', refs: { effort: 'Effort', supersedes: 'Issue', @@ -20,7 +20,7 @@ test('returns exactly eight entries with exact paths and refs', (t) => { }, { collection: 'Finding', - path: '.flatbread-efforts/findings', + path: '.flatbread-proof/findings', refs: { effort: 'Effort', supersedes: 'Finding', @@ -30,7 +30,7 @@ test('returns exactly eight entries with exact paths and refs', (t) => { }, { collection: 'Decision', - path: '.flatbread-efforts/decisions', + path: '.flatbread-proof/decisions', refs: { effort: 'Effort', supersedes: 'Decision', @@ -41,7 +41,7 @@ test('returns exactly eight entries with exact paths and refs', (t) => { }, { collection: 'Constraint', - path: '.flatbread-efforts/constraints', + path: '.flatbread-proof/constraints', refs: { effort: 'Effort', supersedes: 'Constraint', @@ -51,7 +51,7 @@ test('returns exactly eight entries with exact paths and refs', (t) => { }, { collection: 'Risk', - path: '.flatbread-efforts/risks', + path: '.flatbread-proof/risks', refs: { effort: 'Effort', supersedes: 'Risk', @@ -62,19 +62,19 @@ test('returns exactly eight entries with exact paths and refs', (t) => { }, { collection: 'Citation', - path: '.flatbread-efforts/citations', + path: '.flatbread-proof/citations', refs: { effort: 'Effort', blob: 'Blob' }, }, { collection: 'Blob', - path: '.flatbread-efforts/blobs', + path: '.flatbread-proof/blobs', refs: { effort: 'Effort' }, }, ]); }); test('a custom root is respected in every path', (t) => { - const entries = effortGraphContent('memory/graph'); + const entries = proofContent('memory/graph'); t.deepEqual( entries.map((e) => e.path), [ @@ -99,7 +99,7 @@ test('polymorphic union fields are absent from every refs map', (t) => { 'evidence', 'cite_meta', ]; - for (const entry of effortGraphContent()) { + for (const entry of proofContent()) { for (const field of polymorphic) { t.false( Object.keys(entry.refs ?? {}).includes(field), @@ -110,7 +110,7 @@ test('polymorphic union fields are absent from every refs map', (t) => { }); test('cites is a Citation ref on records that can create cites', (t) => { - for (const entry of effortGraphContent()) { + for (const entry of proofContent()) { if ( entry.collection === 'Effort' || entry.collection === 'Blob' || diff --git a/packages/effort-graph/src/__tests__/read.test.ts b/packages/proof/src/__tests__/read.test.ts similarity index 100% rename from packages/effort-graph/src/__tests__/read.test.ts rename to packages/proof/src/__tests__/read.test.ts diff --git a/packages/effort-graph/src/__tests__/schemas.test.ts b/packages/proof/src/__tests__/schemas.test.ts similarity index 90% rename from packages/effort-graph/src/__tests__/schemas.test.ts rename to packages/proof/src/__tests__/schemas.test.ts index 1f3a94e5..95f6e9cd 100644 --- a/packages/effort-graph/src/__tests__/schemas.test.ts +++ b/packages/proof/src/__tests__/schemas.test.ts @@ -1,7 +1,7 @@ import test from 'ava'; import { parse as parseMarkdown } from '@flatbread/transformer-markdown'; import { - EffortGraphMutationSchema, + ProofMutationSchema, EffortFrontmatterSchema, IssueFrontmatterSchema, RiskFrontmatterSchema, @@ -92,39 +92,36 @@ test('each of the 15 mutation schemas accepts a valid input', (t) => { const types = Object.keys(validMutations); t.is(types.length, 15); for (const type of types) { - t.notThrows( - () => EffortGraphMutationSchema.parse(validMutations[type]), - type - ); + t.notThrows(() => ProofMutationSchema.parse(validMutations[type]), type); } }); test('union rejects an unknown discriminant', (t) => { - t.throws(() => EffortGraphMutationSchema.parse({ type: 'DeleteEverything' })); + t.throws(() => ProofMutationSchema.parse({ type: 'DeleteEverything' })); }); test('rejects bad enum values', (t) => { t.throws(() => - EffortGraphMutationSchema.parse({ + ProofMutationSchema.parse({ type: 'SetEffortStatus', effortId: eff, status: 'archived', }) ); t.throws(() => - EffortGraphMutationSchema.parse({ + ProofMutationSchema.parse({ ...validMutations.WriteRisk, likelihood: 'certain', }) ); t.throws(() => - EffortGraphMutationSchema.parse({ + ProofMutationSchema.parse({ ...validMutations.SetRiskState, state: 'mitigated', }) ); t.throws(() => - EffortGraphMutationSchema.parse({ + ProofMutationSchema.parse({ ...validMutations.WriteConstraint, kind: 'squishy', }) @@ -133,19 +130,19 @@ test('rejects bad enum values', (t) => { test('rejects malformed ids', (t) => { t.throws(() => - EffortGraphMutationSchema.parse({ + ProofMutationSchema.parse({ type: 'AcceptDecision', decisionId: 'not-an-id', }) ); t.throws(() => - EffortGraphMutationSchema.parse({ + ProofMutationSchema.parse({ ...validMutations.WriteIssue, effort: 'eff-UPPER--0123456789abcdef', }) ); t.throws(() => - EffortGraphMutationSchema.parse({ + ProofMutationSchema.parse({ ...validMutations.ResolveIssue, resolvedBy: ['dec-short--abc'], }) @@ -154,7 +151,7 @@ test('rejects malformed ids', (t) => { test('WriteCitation allows URL body without blob; records cite Citation ids', (t) => { t.notThrows(() => - EffortGraphMutationSchema.parse({ + ProofMutationSchema.parse({ type: 'WriteCitation', effort: eff, title: 'External link', @@ -162,14 +159,14 @@ test('WriteCitation allows URL body without blob; records cite Citation ids', (t }) ); t.notThrows(() => - EffortGraphMutationSchema.parse({ + ProofMutationSchema.parse({ ...validMutations.WriteCitation, blob: `blb-payload--${suffix}`, role: 'context', }) ); t.notThrows(() => - EffortGraphMutationSchema.parse({ + ProofMutationSchema.parse({ ...validMutations.WriteFinding, cites: [`cit-paper--${suffix}`], }) @@ -177,7 +174,7 @@ test('WriteCitation allows URL body without blob; records cite Citation ids', (t }); test('CreateEffort rejects cites', (t) => { - const result = EffortGraphMutationSchema.safeParse({ + const result = ProofMutationSchema.safeParse({ ...validMutations.CreateEffort, cites: [`cit-paper--${suffix}`], }); @@ -195,7 +192,7 @@ test('CreateEffort rejects cites', (t) => { test('WriteCitation and WriteBlob reject relation keys', (t) => { for (const type of ['WriteCitation', 'WriteBlob'] as const) { - const result = EffortGraphMutationSchema.safeParse({ + const result = ProofMutationSchema.safeParse({ ...validMutations[type], cites: [`cit-paper--${suffix}`], }); diff --git a/packages/effort-graph/src/__tests__/skills.test.ts b/packages/proof/src/__tests__/skills.test.ts similarity index 96% rename from packages/effort-graph/src/__tests__/skills.test.ts rename to packages/proof/src/__tests__/skills.test.ts index 171051f7..22a5c2e6 100644 --- a/packages/effort-graph/src/__tests__/skills.test.ts +++ b/packages/proof/src/__tests__/skills.test.ts @@ -6,7 +6,7 @@ import { promisify } from 'node:util'; import test from 'ava'; const run = promisify(execFile); -const script = resolve('packages/effort-graph/scripts/sync-skills.mjs'); +const script = resolve('packages/proof/scripts/sync-skills.mjs'); test('skill projection syncs, removes stale files, and checks without writing', async (t) => { const root = await mkdtemp(resolve(tmpdir(), 'flatbread-skills-')); diff --git a/packages/effort-graph/src/__tests__/snapshot.test.ts b/packages/proof/src/__tests__/snapshot.test.ts similarity index 88% rename from packages/effort-graph/src/__tests__/snapshot.test.ts rename to packages/proof/src/__tests__/snapshot.test.ts index 86037481..c14074d0 100644 --- a/packages/effort-graph/src/__tests__/snapshot.test.ts +++ b/packages/proof/src/__tests__/snapshot.test.ts @@ -2,12 +2,9 @@ import test from 'ava'; import { mkdir, mkdtemp, writeFile } from 'node:fs/promises'; import { join } from 'node:path'; import { tmpdir } from 'node:os'; -import { EffortGraphValidationError } from '../errors.js'; +import { ProofValidationError } from '../errors.js'; import { serializeDocument } from '../frontmatter.js'; -import { - buildEffortGraphSnapshot, - createEffortGraphSnapshot, -} from '../snapshot.js'; +import { buildProofSnapshot, createProofSnapshot } from '../snapshot.js'; const e = 'eff-one--0123456789abcdef'; const d = 'dec-one--0123456789abcdef'; @@ -50,7 +47,7 @@ test('1 build capture survives later disk mutation', async (t) => { }); await writeFile(join(root, 'efforts', `${e}.md`), eb); await writeFile(join(root, 'decisions', `${d}.md`), db); - const snapshot = await buildEffortGraphSnapshot(root); + const snapshot = await buildProofSnapshot(root); await writeFile( join(root, 'efforts', `${e}.md`), serializeDocument('new', { @@ -86,25 +83,25 @@ test('2 duplicate IDs fail deterministically', async (t) => { state: 'proposed', }) ); - await t.throwsAsync(buildEffortGraphSnapshot(root), { - instanceOf: EffortGraphValidationError, + await t.throwsAsync(buildProofSnapshot(root), { + instanceOf: ProofValidationError, message: `Duplicate id ${e} at ${join(root, 'decisions/b.md')}`, }); }); test('3 missing and empty collection directories contribute no records', async (t) => { const root = await mkdtemp(join(tmpdir(), 'snap-')); - const a = await buildEffortGraphSnapshot(root); + const a = await buildProofSnapshot(root); t.false(a.hasId(e)); t.deepEqual(a.recordsByKind('effort'), []); await mkdir(join(root, 'efforts')); - const b = await buildEffortGraphSnapshot(root); + const b = await buildProofSnapshot(root); t.deepEqual(b.recordsByEffort(e), []); t.is(b.getRecord(e), undefined); }); test('4 byEffort filtering is exact', (t) => { - const s = createEffortGraphSnapshot([ + const s = createProofSnapshot([ input(e, 'effort'), input(e2, 'effort'), input(d, 'decision', e), @@ -115,7 +112,7 @@ test('4 byEffort filtering is exact', (t) => { ); }); test('5 byKind filtering is exact', (t) => { - const s = createEffortGraphSnapshot([ + const s = createProofSnapshot([ input(e, 'effort'), input(e2, 'effort'), input(d, 'decision', e), @@ -126,7 +123,7 @@ test('5 byKind filtering is exact', (t) => { ); }); test('6 sibling filtering is exact', (t) => { - const s = createEffortGraphSnapshot([ + const s = createProofSnapshot([ input(e, 'effort'), input(d, 'decision', e), { @@ -153,7 +150,7 @@ test('6 sibling filtering is exact', (t) => { test('7 constructor protects snapshot data', (t) => { const fm = { ...input(d, 'decision', e).frontmatter }; const bytes = Buffer.from('raw'); - const s = createEffortGraphSnapshot([ + const s = createProofSnapshot([ { ...input(d, 'decision', e), frontmatter: fm, rawBytes: bytes }, ]); fm.title = 'mutated'; diff --git a/packages/effort-graph/src/__tests__/writer.test.ts b/packages/proof/src/__tests__/writer.test.ts similarity index 92% rename from packages/effort-graph/src/__tests__/writer.test.ts rename to packages/proof/src/__tests__/writer.test.ts index 63a7870b..00408be2 100644 --- a/packages/effort-graph/src/__tests__/writer.test.ts +++ b/packages/proof/src/__tests__/writer.test.ts @@ -3,17 +3,17 @@ import { mkdir, mkdtemp, readFile } from 'node:fs/promises'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import matter from 'gray-matter'; -import { createEffortGraphWriter } from '../writer.js'; -import { EffortGraphValidationError } from '../errors.js'; -import type { EffortGraphWriter, MutationResult } from '../types.js'; -import type { EffortGraphMutation } from '../schemas.js'; +import { createProofWriter } from '../writer.js'; +import { ProofValidationError } from '../errors.js'; +import type { ProofWriter, MutationResult } from '../types.js'; +import type { ProofMutation } from '../schemas.js'; async function makeWriter(): Promise<{ root: string; - writer: EffortGraphWriter; + writer: ProofWriter; }> { const root = await mkdtemp(join(tmpdir(), 'eg-writer-')); - return { root, writer: createEffortGraphWriter({ rootDir: root }) }; + return { root, writer: createProofWriter({ rootDir: root }) }; } async function readFrontmatter(root: string, relativePath: string) { @@ -33,9 +33,9 @@ test('CreateEffort rejects cites through the writer', async (t) => { title: 'E', body: '', cites: ['cit-paper--0123456789abcdef'], - } as unknown as EffortGraphMutation), + } as unknown as ProofMutation), { - instanceOf: EffortGraphValidationError, + instanceOf: ProofValidationError, message: 'CreateEffort does not accept cites; create the Effort before its Citations.', } @@ -54,9 +54,9 @@ test('WriteCitation and WriteBlob reject cites through the writer', async (t) => title: 'Paper', body: 'https://example.com/paper', cites: ['cit-other--0123456789abcdef'], - } as unknown as EffortGraphMutation), + } as unknown as ProofMutation), { - instanceOf: EffortGraphValidationError, + instanceOf: ProofValidationError, message: /WriteCitation does not accept cites/, } ); @@ -67,9 +67,9 @@ test('WriteCitation and WriteBlob reject cites through the writer', async (t) => title: 'Payload', body: '# longform research\n', cites: ['cit-paper--0123456789abcdef'], - } as unknown as EffortGraphMutation), + } as unknown as ProofMutation), { - instanceOf: EffortGraphValidationError, + instanceOf: ProofValidationError, message: /WriteBlob does not accept cites/, } ); @@ -125,7 +125,7 @@ test('Supersede sets a Decision target state to superseded, exactly 2 files', as // Already-superseded target rejects a second superseder. await t.throwsAsync( writer.mutate({ type: 'Supersede', supersederId: b, targetId: a }), - { instanceOf: EffortGraphValidationError } + { instanceOf: ProofValidationError } ); }); @@ -167,7 +167,7 @@ test('Invalidate changes only edge fields on the target', async (t) => { findingId: finding, targetId: decision, }), - { instanceOf: EffortGraphValidationError } + { instanceOf: ProofValidationError } ); // A non-Finding source is rejected. await t.throwsAsync( @@ -176,7 +176,7 @@ test('Invalidate changes only edge fields on the target', async (t) => { findingId: decision, targetId: finding, }), - { instanceOf: EffortGraphValidationError } + { instanceOf: ProofValidationError } ); }); @@ -222,7 +222,7 @@ test('ResolveIssue rejects non-open issues and cross-effort sources', async (t) resolution: 'resolved', resolvedBy: [foreignFinding], }), - { instanceOf: EffortGraphValidationError } + { instanceOf: ProofValidationError } ); const resolved = await writer.mutate({ type: 'ResolveIssue', @@ -239,7 +239,7 @@ test('ResolveIssue rejects non-open issues and cross-effort sources', async (t) resolution: 'wontfix', resolvedBy: [localFinding], }), - { instanceOf: EffortGraphValidationError } + { instanceOf: ProofValidationError } ); }); @@ -295,7 +295,7 @@ test('AcceptDecision rejects proposed siblings and leaves others untouched', asy // Accepting a non-proposed decision is rejected. await t.throwsAsync( writer.mutate({ type: 'AcceptDecision', decisionId: winner }), - { instanceOf: EffortGraphValidationError } + { instanceOf: ProofValidationError } ); }); @@ -319,7 +319,7 @@ test('MitigateRisk requires an accepted Decision in the same Effort', async (t) ); await t.throwsAsync( writer.mutate({ type: 'MitigateRisk', riskId: risk, decisionId: decision }), - { instanceOf: EffortGraphValidationError } + { instanceOf: ProofValidationError } ); await writer.mutate({ type: 'AcceptDecision', decisionId: decision }); const result = await writer.mutate({ @@ -356,7 +356,7 @@ test('SetRiskState realized requires at least one Finding in evidence', async (t state: 'realized', evidence: [decision], }), - { instanceOf: EffortGraphValidationError } + { instanceOf: ProofValidationError } ); const finding = soleId( await writer.mutate({ @@ -446,7 +446,7 @@ test('WriteFinding rejects cites from another effort', async (t) => { cites: [foreignCitation], }), { - instanceOf: EffortGraphValidationError, + instanceOf: ProofValidationError, message: new RegExp( `cites target ${foreignCitation} belongs to a different effort` ), @@ -479,7 +479,7 @@ test('WriteCitation rejects a Blob from another effort', async (t) => { blob: foreignBlob, }), { - instanceOf: EffortGraphValidationError, + instanceOf: ProofValidationError, message: new RegExp( `Citation\\.blob ${foreignBlob} belongs to a different effort` ), @@ -517,7 +517,7 @@ test('generation tokens increment across successive mutations', async (t) => { test('writer uses one injected snapshot source', async (t) => { const root = await mkdtemp(join(tmpdir(), 'eg-snapshot-writer-')); const id = 'eff-active--0123456789abcdef'; - const snapshot = (await import('../snapshot.js')).createEffortGraphSnapshot([ + const snapshot = (await import('../snapshot.js')).createProofSnapshot([ { id, kind: 'effort', @@ -533,7 +533,7 @@ test('writer uses one injected snapshot source', async (t) => { }, ]); let count = 0; - const writer = createEffortGraphWriter({ + const writer = createProofWriter({ rootDir: root, index: { async buildSnapshot() { @@ -555,7 +555,7 @@ test('writer uses one injected snapshot source', async (t) => { test('snapshot before-image drives journal-compatible end-to-end output', async (t) => { const root = await mkdtemp(join(tmpdir(), 'eg-snapshot-before-')); const id = 'eff-captured--0123456789abcdef'; - const captured = (await import('../snapshot.js')).createEffortGraphSnapshot([ + const captured = (await import('../snapshot.js')).createProofSnapshot([ { id, kind: 'effort', @@ -570,7 +570,7 @@ test('snapshot before-image drives journal-compatible end-to-end output', async rawBytes: Buffer.from('captured raw bytes'), }, ]); - const writer = createEffortGraphWriter({ + const writer = createProofWriter({ rootDir: root, index: { async buildSnapshot() { diff --git a/packages/effort-graph/src/decision-lifecycle.ts b/packages/proof/src/decision-lifecycle.ts similarity index 70% rename from packages/effort-graph/src/decision-lifecycle.ts rename to packages/proof/src/decision-lifecycle.ts index 1771909e..25406eb8 100644 --- a/packages/effort-graph/src/decision-lifecycle.ts +++ b/packages/proof/src/decision-lifecycle.ts @@ -1,11 +1,8 @@ -import { EffortGraphValidationError } from './errors.js'; -import type { - EffortGraphSnapshot, - EffortGraphSnapshotArtifact, -} from './snapshot.js'; +import { ProofValidationError } from './errors.js'; +import type { ProofSnapshot, ProofSnapshotArtifact } from './snapshot.js'; export interface DecisionLifecycleChange { - readonly record: EffortGraphSnapshotArtifact; + readonly record: ProofSnapshotArtifact; readonly nextFrontmatter: Readonly>; } export interface AcceptDecisionLifecycleInput { @@ -13,16 +10,14 @@ export interface AcceptDecisionLifecycleInput { readonly rejectSiblings: boolean; } export function acceptDecisionLifecycle( - snapshot: EffortGraphSnapshot, + snapshot: ProofSnapshot, input: AcceptDecisionLifecycleInput ): readonly DecisionLifecycleChange[] { const target = snapshot.getRecord(input.decisionId); if (!target) - throw new EffortGraphValidationError( - `Unknown artifact ${input.decisionId}` - ); + throw new ProofValidationError(`Unknown artifact ${input.decisionId}`); if (target.kind !== 'decision' || target.frontmatter.state !== 'proposed') - throw new EffortGraphValidationError('Decision is not proposed'); + throw new ProofValidationError('Decision is not proposed'); const changes: DecisionLifecycleChange[] = [ { record: target, @@ -45,14 +40,13 @@ export function acceptDecisionLifecycle( return changes; } export function supersedeDecisionLifecycle( - snapshot: EffortGraphSnapshot, + snapshot: ProofSnapshot, decisionId: string ): DecisionLifecycleChange { const target = snapshot.getRecord(decisionId); - if (!target) - throw new EffortGraphValidationError(`Unknown artifact ${decisionId}`); + if (!target) throw new ProofValidationError(`Unknown artifact ${decisionId}`); if (target.kind !== 'decision') - throw new EffortGraphValidationError('Not a Decision'); + throw new ProofValidationError('Not a Decision'); return { record: target, nextFrontmatter: { ...target.frontmatter, state: 'superseded' }, diff --git a/packages/effort-graph/src/digest.ts b/packages/proof/src/digest.ts similarity index 99% rename from packages/effort-graph/src/digest.ts rename to packages/proof/src/digest.ts index 5b7a76eb..5495ed29 100644 --- a/packages/effort-graph/src/digest.ts +++ b/packages/proof/src/digest.ts @@ -157,7 +157,7 @@ function renderRecordBody( return [ '> Blob body omitted from bounded digests.', `Source path: \`${record.path || '(unknown)'}\`.`, - 'Use `effort get ` to read the payload.', + 'Use `proof get ` to read the payload.', ].join(' '); } if (bodyMode === 'full') return normalizeBody(record.body_excerpt); @@ -272,7 +272,7 @@ export async function renderDigest(input: DigestInput): Promise { let markdown = [ yamlHeader(input, reasons.length === 0 && !input.hasMore, reasons), ...(input.anomaly ? [`> anomaly: ${input.anomaly}`, ''] : []), - '# Effort Graph read', + '# Proof read', '## Index', ...visible.map((record) => `- [\`${record.id}\`](#${record.id})`), '## Records', @@ -305,7 +305,7 @@ export async function renderDigest(input: DigestInput): Promise { const header = [ yamlHeader(input, false, reasons), ...(anomaly ? [`> anomaly: ${anomaly}`, ''] : []), - '# Effort Graph read', + '# Proof read', '## Index', ...visible.map((record) => `- [\`${record.id}\`](#${record.id})`), '## Records', diff --git a/packages/effort-graph/src/errors.ts b/packages/proof/src/errors.ts similarity index 52% rename from packages/effort-graph/src/errors.ts rename to packages/proof/src/errors.ts index a810d07f..53fb5664 100644 --- a/packages/effort-graph/src/errors.ts +++ b/packages/proof/src/errors.ts @@ -3,59 +3,59 @@ import type { GenerationToken, } from './types.js'; -export class EffortGraphError extends Error { +export class ProofError extends Error { constructor(message: string, readonly code: string) { super(message); this.name = new.target.name; } } -export class EffortGraphLockedError extends EffortGraphError { +export class ProofLockedError extends ProofError { readonly retryAfterMs: number; - constructor(retryAfterMs = 1000, message = 'Effort graph is locked') { - super(message, 'EFFORT_GRAPH_LOCKED'); + constructor(retryAfterMs = 1000, message = 'Proof is locked') { + super(message, 'PROOF_LOCKED'); this.retryAfterMs = retryAfterMs; } } -export class EffortGraphValidationError extends EffortGraphError { +export class ProofValidationError extends ProofError { constructor(message: string) { - super(message, 'EFFORT_GRAPH_VALIDATION'); + super(message, 'PROOF_VALIDATION'); } } -export class EffortGraphReindexFailedError extends EffortGraphError { +export class ProofReindexFailedError extends ProofError { constructor(message: string, readonly originalError?: unknown) { - super(message, 'EFFORT_GRAPH_REINDEX_FAILED'); + super(message, 'PROOF_REINDEX_FAILED'); } } -export class EffortGraphCorruptJournalError extends EffortGraphError { +export class ProofCorruptJournalError extends ProofError { constructor(message: string) { - super(message, 'EFFORT_GRAPH_CORRUPT_JOURNAL'); + super(message, 'PROOF_CORRUPT_JOURNAL'); } } -export class EffortGraphLiveSchemaRejectedError extends EffortGraphError { +export class ProofLiveSchemaRejectedError extends ProofError { constructor( readonly publication: CommittedGenerationPublication, readonly originalError: Error ) { super( `Live schema rejected generation ${publication.targetGeneration}: ${originalError.message}`, - 'EFFORT_GRAPH_LIVE_SCHEMA_REJECTED' + 'PROOF_LIVE_SCHEMA_REJECTED' ); } } -export class EffortGraphGenerationWaitTimeoutError extends EffortGraphError { +export class ProofGenerationWaitTimeoutError extends ProofError { constructor(readonly token: GenerationToken, readonly timeoutMs: number) { super( `Timed out waiting for committed generation ${token} after ${timeoutMs}ms`, - 'EFFORT_GRAPH_GENERATION_WAIT_TIMEOUT' + 'PROOF_GENERATION_WAIT_TIMEOUT' ); } } -export class EffortGraphBarrierTimeoutError extends EffortGraphError { +export class ProofBarrierTimeoutError extends ProofError { constructor(readonly paths: readonly string[], readonly maxWaitMs: number) { super( `Timed out waiting for journal readability after ${maxWaitMs}ms`, - 'EFFORT_GRAPH_BARRIER_TIMEOUT' + 'PROOF_BARRIER_TIMEOUT' ); } } diff --git a/packages/effort-graph/src/frontmatter.ts b/packages/proof/src/frontmatter.ts similarity index 100% rename from packages/effort-graph/src/frontmatter.ts rename to packages/proof/src/frontmatter.ts diff --git a/packages/effort-graph/src/ids.ts b/packages/proof/src/ids.ts similarity index 100% rename from packages/effort-graph/src/ids.ts rename to packages/proof/src/ids.ts diff --git a/packages/effort-graph/src/index-store.ts b/packages/proof/src/index-store.ts similarity index 54% rename from packages/effort-graph/src/index-store.ts rename to packages/proof/src/index-store.ts index 2c283c80..52535383 100644 --- a/packages/effort-graph/src/index-store.ts +++ b/packages/proof/src/index-store.ts @@ -1,15 +1,9 @@ import { PREFIX_KIND } from './ids.js'; -import { buildEffortGraphSnapshot } from './snapshot.js'; -import type { - EffortGraphIndex, - IndexedArtifact, - PrimitiveKind, -} from './types.js'; -export function createFilesystemEffortGraphIndex( - rootDir: string -): EffortGraphIndex { +import { buildProofSnapshot } from './snapshot.js'; +import type { ProofIndex, IndexedArtifact, PrimitiveKind } from './types.js'; +export function createFilesystemProofIndex(rootDir: string): ProofIndex { const convert = ( - r: import('./snapshot.js').EffortGraphSnapshotArtifact + r: import('./snapshot.js').ProofSnapshotArtifact ): IndexedArtifact => ({ id: r.id, kind: r.kind, @@ -19,26 +13,26 @@ export function createFilesystemEffortGraphIndex( }); return { async getRecord(id) { - const r = (await buildEffortGraphSnapshot(rootDir)).getRecord(id); + const r = (await buildProofSnapshot(rootDir)).getRecord(id); return r && convert(r); }, async recordsByEffort(effortId) { - return (await buildEffortGraphSnapshot(rootDir)) + return (await buildProofSnapshot(rootDir)) .recordsByEffort(effortId) .map(convert); }, async recordsByKind(kind) { - return (await buildEffortGraphSnapshot(rootDir)) + return (await buildProofSnapshot(rootDir)) .recordsByKind(kind) .map(convert); }, async siblingDecisions(effortId, o = {}) { - return (await buildEffortGraphSnapshot(rootDir)) + return (await buildProofSnapshot(rootDir)) .siblingDecisions(effortId, o) .map(convert); }, async hasId(id) { - return (await buildEffortGraphSnapshot(rootDir)).hasId(id); + return (await buildProofSnapshot(rootDir)).hasId(id); }, }; } diff --git a/packages/effort-graph/src/index.ts b/packages/proof/src/index.ts similarity index 88% rename from packages/effort-graph/src/index.ts rename to packages/proof/src/index.ts index 9e97bced..d1cd3583 100644 --- a/packages/effort-graph/src/index.ts +++ b/packages/proof/src/index.ts @@ -15,9 +15,9 @@ export * from './journalBarrier.js'; export * from './digest.js'; export { READ_RELATIONS, - EffortGraphConsistencyError, - EffortGraphInvalidCursorError, - EffortGraphReadValidationError, + ProofConsistencyError, + ProofInvalidCursorError, + ProofReadValidationError, canonicalizeReadQuery, parseGenerationToken, pruneReadCache, diff --git a/packages/effort-graph/src/journal.ts b/packages/proof/src/journal.ts similarity index 94% rename from packages/effort-graph/src/journal.ts rename to packages/proof/src/journal.ts index b284aa90..4901fdc1 100644 --- a/packages/effort-graph/src/journal.ts +++ b/packages/proof/src/journal.ts @@ -11,9 +11,9 @@ import { import { dirname, join } from 'node:path'; import { createHash, randomUUID } from 'node:crypto'; import { - EffortGraphCorruptJournalError, - EffortGraphLockedError, - EffortGraphReindexFailedError, + ProofCorruptJournalError, + ProofLockedError, + ProofReindexFailedError, } from './errors.js'; import type { PlannedWrite, @@ -100,7 +100,7 @@ export async function recoverJournal( try { intent = JSON.parse(await readFile(intentPath, 'utf8')); } catch { - throw new EffortGraphCorruptJournalError(`Cannot parse ${intentPath}`); + throw new ProofCorruptJournalError(`Cannot parse ${intentPath}`); } transactionId = intent.transactionId; const committed = await readFile(join(td, 'committed')) @@ -146,7 +146,7 @@ export async function recoverJournal( touchedIds: intent.touchedIds, }); } catch (e) { - throw new EffortGraphReindexFailedError('Recovery reindex failed', e); + throw new ProofReindexFailedError('Recovery reindex failed', e); } await publishGeneration(root, intent.targetGeneration); await writeFileDurable(join(td, 'published'), ''); @@ -198,7 +198,7 @@ export async function commitJournal( a.relativePath.localeCompare(b.relativePath) )) { if (!(await verifyLock())) - throw new EffortGraphLockedError(0, 'Writer lock lost mid-transaction'); + throw new ProofLockedError(0, 'Writer lock lost mid-transaction'); const target = join(root, w.relativePath); await mkdir(dirname(target), { recursive: true }); const tmp = join(root, w.relativePath.replace(/\.md$/, `.tmp-${token}.md`)); @@ -217,7 +217,7 @@ export async function commitJournal( touchedIds: writes.map((w) => w.id), }); } catch (e) { - throw new EffortGraphReindexFailedError('Reindex failed', e); + throw new ProofReindexFailedError('Reindex failed', e); } await publishGeneration(root, generation); await writeFileDurable(join(td, 'published'), ''); diff --git a/packages/effort-graph/src/journalBarrier.ts b/packages/proof/src/journalBarrier.ts similarity index 85% rename from packages/effort-graph/src/journalBarrier.ts rename to packages/proof/src/journalBarrier.ts index 791b71af..0fb28de6 100644 --- a/packages/effort-graph/src/journalBarrier.ts +++ b/packages/proof/src/journalBarrier.ts @@ -2,9 +2,9 @@ import { access, readFile, readdir } from 'node:fs/promises'; import { relative, resolve, join, sep } from 'node:path'; import type { ReindexBarrier } from '@flatbread/core'; import { - EffortGraphBarrierTimeoutError, - EffortGraphCorruptJournalError, - EffortGraphValidationError, + ProofBarrierTimeoutError, + ProofCorruptJournalError, + ProofValidationError, } from './errors.js'; export interface JournalReindexBarrierOptions { @@ -35,7 +35,7 @@ async function blockingWrites(rootDir: string): Promise { try { intent = JSON.parse(intentText); } catch { - throw new EffortGraphCorruptJournalError(`Cannot parse ${intentPath}`); + throw new ProofCorruptJournalError(`Cannot parse ${intentPath}`); } let committed = false; try { @@ -44,20 +44,18 @@ async function blockingWrites(rootDir: string): Promise { } catch {} if (committed) continue; if (!Array.isArray(intent.writes)) { - throw new EffortGraphCorruptJournalError( - `Invalid writes in ${intentPath}` - ); + throw new ProofCorruptJournalError(`Invalid writes in ${intentPath}`); } for (const write of intent.writes) { if (typeof write.relativePath !== 'string') { - throw new EffortGraphCorruptJournalError( + throw new ProofCorruptJournalError( `Invalid relativePath in ${intentPath}` ); } const absolute = resolve(rootDir, write.relativePath); const outside = relative(rootDir, absolute); if (outside === '..' || outside.startsWith(`..${sep}`)) { - throw new EffortGraphValidationError( + throw new ProofValidationError( `Journal path escapes root directory: ${write.relativePath}` ); } @@ -90,7 +88,7 @@ export function createJournalReindexBarrier( ) return; if (Date.now() - started >= maxWaitMs) - throw new EffortGraphBarrierTimeoutError(requestedPaths, maxWaitMs); + throw new ProofBarrierTimeoutError(requestedPaths, maxWaitMs); await new Promise((resolveSleep) => setTimeout(resolveSleep, pollIntervalMs) ); diff --git a/packages/effort-graph/src/live.ts b/packages/proof/src/live.ts similarity index 84% rename from packages/effort-graph/src/live.ts rename to packages/proof/src/live.ts index 0ff3613b..e2c12d4a 100644 --- a/packages/effort-graph/src/live.ts +++ b/packages/proof/src/live.ts @@ -2,33 +2,33 @@ import { readFile } from 'node:fs/promises'; import { relative, resolve, sep, join } from 'node:path'; import type { LiveSchemaReloader, SchemaSnapshot } from '@flatbread/core'; import { - EffortGraphGenerationWaitTimeoutError, - EffortGraphLiveSchemaRejectedError, - EffortGraphValidationError, + ProofGenerationWaitTimeoutError, + ProofLiveSchemaRejectedError, + ProofValidationError, } from './errors.js'; -import { createEffortGraphWriter } from './writer.js'; +import { createProofWriter } from './writer.js'; import type { CommittedGenerationPublication, CommittedGenerationPublisher, - EffortGraphWriter, - EffortGraphWriterOptions, + ProofWriter, + ProofWriterOptions, GenerationToken, } from './types.js'; export interface WaitForCommittedGenerationOptions { timeoutMs?: number; } -export interface EffortGraphLiveBridge { +export interface ProofLiveBridge { readonly rootDir: string; - readonly writer: EffortGraphWriter; + readonly writer: ProofWriter; readonly publisher: CommittedGenerationPublisher; waitForCommittedGeneration( token: GenerationToken, options?: WaitForCommittedGenerationOptions ): Promise; } -export interface CreateEffortGraphLiveBridgeOptions - extends Omit { +export interface CreateProofLiveBridgeOptions + extends Omit { reloader: LiveSchemaReloader; pollIntervalMs?: number; } @@ -46,16 +46,16 @@ async function generationOnDisk(rootDir: string): Promise { function tokenNumber(token: string): number { if (!/^[1-9]\d*$/.test(token)) { - throw new EffortGraphValidationError( + throw new ProofValidationError( `Generation token must be a positive integer: ${token}` ); } return Number(token); } -export async function createEffortGraphLiveBridge( - options: CreateEffortGraphLiveBridgeOptions -): Promise { +export async function createProofLiveBridge( + options: CreateProofLiveBridgeOptions +): Promise { const pollIntervalMs = options.pollIntervalMs ?? 25; const liveGenerations = new Map(); // Tokens at or below this mark were already published when the bridge was @@ -68,7 +68,7 @@ export async function createEffortGraphLiveBridge( const absolute = resolve(options.rootDir, path.replaceAll('\\', sep)); const outside = relative(options.rootDir, absolute); if (outside === '..' || outside.startsWith(`..${sep}`)) { - throw new EffortGraphValidationError( + throw new ProofValidationError( `Publication path escapes root directory: ${path}` ); } @@ -79,7 +79,7 @@ export async function createEffortGraphLiveBridge( source: 'writer', }); if (result.status === 'rejected') { - throw new EffortGraphLiveSchemaRejectedError(publication, result.error); + throw new ProofLiveSchemaRejectedError(publication, result.error); } liveGenerations.set( Number(publication.targetGeneration), @@ -88,7 +88,7 @@ export async function createEffortGraphLiveBridge( }, }; - const writer = createEffortGraphWriter({ + const writer = createProofWriter({ rootDir: options.rootDir, index: options.index, clock: options.clock, @@ -110,7 +110,7 @@ export async function createEffortGraphLiveBridge( const remaining = deadline === undefined ? pollIntervalMs : deadline - Date.now(); if (remaining <= 0) - throw new EffortGraphGenerationWaitTimeoutError( + throw new ProofGenerationWaitTimeoutError( token, waitOptions.timeoutMs! ); diff --git a/packages/effort-graph/src/lock.ts b/packages/proof/src/lock.ts similarity index 94% rename from packages/effort-graph/src/lock.ts rename to packages/proof/src/lock.ts index 39f91f20..19221379 100644 --- a/packages/effort-graph/src/lock.ts +++ b/packages/proof/src/lock.ts @@ -2,7 +2,7 @@ import { hostname } from 'node:os'; import { open, readFile, rename, unlink } from 'node:fs/promises'; import { join } from 'node:path'; import { randomUUID } from 'node:crypto'; -import { EffortGraphLockedError } from './errors.js'; +import { ProofLockedError } from './errors.js'; import type { WriterLockOptions } from './types.js'; export interface WriterLock { token: string; @@ -50,7 +50,7 @@ export async function acquireWriterLock( return acquireWriterLock(root, options); } } catch {} - throw new EffortGraphLockedError(leaseMs); + throw new ProofLockedError(leaseMs); } const verify = async () => { try { diff --git a/packages/effort-graph/src/planner.ts b/packages/proof/src/planner.ts similarity index 81% rename from packages/effort-graph/src/planner.ts rename to packages/proof/src/planner.ts index 0027abc8..d37b9f24 100644 --- a/packages/effort-graph/src/planner.ts +++ b/packages/proof/src/planner.ts @@ -1,5 +1,5 @@ import { join } from 'node:path'; -import { EffortGraphValidationError } from './errors.js'; +import { ProofValidationError } from './errors.js'; import { serializeDocument } from './frontmatter.js'; import { generateArtifactId, @@ -10,9 +10,9 @@ import { acceptDecisionLifecycle, supersedeDecisionLifecycle, } from './decision-lifecycle.js'; -import type { EffortGraphSnapshot } from './snapshot.js'; +import type { ProofSnapshot } from './snapshot.js'; import type { PlannedWrite, PrimitiveKind } from './types.js'; -import type { EffortGraphMutation } from './schemas.js'; +import type { ProofMutation } from './schemas.js'; const kinds: Record = { WriteIssue: 'issue', @@ -45,7 +45,7 @@ function assertNoCitationBlobEdges( ): void { const present = CITATION_BLOB_FORBIDDEN_KEYS.filter((key) => key in input); if (present.length) - throw new EffortGraphValidationError( + throw new ProofValidationError( `${type} does not accept ${present.join( ', ' )}; relation fields are only valid on Issue, Finding, Decision, Constraint, or Risk records.` @@ -53,28 +53,26 @@ function assertNoCitationBlobEdges( } function assertCites( - get: ( - id: string - ) => NonNullable>, + get: (id: string) => NonNullable>, effortId: string, cites: string[] | undefined ): void { for (const citeId of cites ?? []) { const target = get(citeId); if (target.kind !== 'citation') - throw new EffortGraphValidationError( + throw new ProofValidationError( `cites must target a Citation, got ${target.kind} (${citeId})` ); if (target.frontmatter.effort !== effortId) - throw new EffortGraphValidationError( + throw new ProofValidationError( `cites target ${citeId} belongs to a different effort` ); } } export function planMutation( - input: EffortGraphMutation, - snapshot: EffortGraphSnapshot, + input: ProofMutation, + snapshot: ProofSnapshot, root: string, now: Date, randomBytes?: (length: number) => Uint8Array @@ -82,7 +80,7 @@ export function planMutation( const writes = new Map(); const get = (id: string) => { const r = snapshot.getRecord(id); - if (!r) throw new EffortGraphValidationError(`Unknown artifact ${id}`); + if (!r) throw new ProofValidationError(`Unknown artifact ${id}`); return r; }; const add = ( @@ -96,9 +94,7 @@ export function planMutation( const beforeBytes = operation === 'update' ? snapshot.getRawBytes(id) : undefined; if (operation === 'update' && !beforeBytes) - throw new EffortGraphValidationError( - `Missing snapshot bytes for update ${id}` - ); + throw new ProofValidationError(`Missing snapshot bytes for update ${id}`); writes.set(path, { id, kind, @@ -111,22 +107,20 @@ export function planMutation( }; if (input.type === 'CreateEffort') { if ('cites' in input) - throw new EffortGraphValidationError( + throw new ProofValidationError( 'CreateEffort does not accept cites; create the Effort before its Citations.' ); const id = input.id ?? generateArtifactId('effort', input.title, randomBytes); if (!validateArtifactId(id, 'effort') || snapshot.hasId(id)) - throw new EffortGraphValidationError(`Invalid or duplicate id ${id}`); + throw new ProofValidationError(`Invalid or duplicate id ${id}`); if ( input.slug && snapshot .recordsByKind('effort') .some((r) => r.frontmatter.slug === input.slug) ) - throw new EffortGraphValidationError( - `Duplicate effort slug ${input.slug}` - ); + throw new ProofValidationError(`Duplicate effort slug ${input.slug}`); add( id, 'effort', @@ -150,11 +144,10 @@ export function planMutation( } if (input.type === 'SetEffortStatus') { const r = get(input.effortId); - if (r.kind !== 'effort') - throw new EffortGraphValidationError('Not an effort'); + if (r.kind !== 'effort') throw new ProofValidationError('Not an effort'); const old = String(r.frontmatter.status); if (old === input.status || old === 'completed' || old === 'abandoned') - throw new EffortGraphValidationError('Illegal effort transition'); + throw new ProofValidationError('Illegal effort transition'); add(r.id, r.kind, { ...r.frontmatter, status: input.status }, r.body); return [...writes.values()]; } @@ -173,18 +166,18 @@ export function planMutation( assertNoCitationBlobEdges(input.type, raw); const id = raw.id ?? generateArtifactId(kind, raw.title, randomBytes); if (!validateArtifactId(id, kind) || snapshot.hasId(id)) - throw new EffortGraphValidationError('Invalid or duplicate id'); + throw new ProofValidationError('Invalid or duplicate id'); const effort = get(raw.effort); if (effort.kind !== 'effort') - throw new EffortGraphValidationError('Invalid effort'); + throw new ProofValidationError('Invalid effort'); if (kind === 'citation' && raw.blob !== undefined) { const blob = get(raw.blob); if (blob.kind !== 'blob') - throw new EffortGraphValidationError( + throw new ProofValidationError( `Citation.blob must target a Blob, got ${blob.kind}` ); if (blob.frontmatter.effort !== raw.effort) - throw new EffortGraphValidationError( + throw new ProofValidationError( `Citation.blob ${raw.blob} belongs to a different effort` ); } @@ -210,19 +203,19 @@ export function planMutation( for (const targetId of (fm[edge] as string[] | undefined) ?? []) { const target = get(targetId); if (edge === 'supersedes' && target.kind !== kind) - throw new EffortGraphValidationError( + throw new ProofValidationError( 'Supersedes must target the same kind' ); if ( edge === 'supersedes' && (target.frontmatter.superseded_by as string[] | undefined)?.length ) - throw new EffortGraphValidationError('Target already superseded'); + throw new ProofValidationError('Target already superseded'); if ( edge === 'invalidates' && !['finding', 'decision'].includes(target.kind) ) - throw new EffortGraphValidationError( + throw new ProofValidationError( 'Invalidation target must be a Finding or Decision' ); const reverse = @@ -255,14 +248,14 @@ export function planMutation( (input.type === 'Supersede' && a.kind !== b.kind) || (a.frontmatter.effort !== b.frontmatter.effort && a.kind !== 'effort') ) - throw new EffortGraphValidationError('Invalid edge'); + throw new ProofValidationError('Invalid edge'); if (input.type === 'Invalidate') { if (a.kind !== 'finding') - throw new EffortGraphValidationError( + throw new ProofValidationError( `Invalidate requires a Finding source, got ${a.kind}` ); if (b.kind !== 'finding' && b.kind !== 'decision') - throw new EffortGraphValidationError( + throw new ProofValidationError( 'Invalidation target must be a Finding or Decision' ); } @@ -270,9 +263,9 @@ export function planMutation( input.type === 'Supersede' && (b.frontmatter[back] as unknown[] | undefined)?.length ) - throw new EffortGraphValidationError('Target already superseded'); + throw new ProofValidationError('Target already superseded'); if (((a.frontmatter[edge] as string[] | undefined) ?? []).includes(b.id)) - throw new EffortGraphValidationError('Duplicate edge'); + throw new ProofValidationError('Duplicate edge'); add( a.id, a.kind, @@ -300,10 +293,10 @@ export function planMutation( if (input.type === 'ResolveIssue') { const r = get(input.issueId); if (r.kind !== 'issue' || r.frontmatter.status !== 'open') - throw new EffortGraphValidationError('Issue is not open'); + throw new ProofValidationError('Issue is not open'); for (const id of input.resolvedBy) if (get(id).frontmatter.effort !== r.frontmatter.effort) - throw new EffortGraphValidationError('Different effort'); + throw new ProofValidationError('Different effort'); add( r.id, r.kind, @@ -339,7 +332,7 @@ export function planMutation( d.frontmatter.state !== 'accepted' || r.frontmatter.effort !== d.frontmatter.effort ) - throw new EffortGraphValidationError('Cannot mitigate risk'); + throw new ProofValidationError('Cannot mitigate risk'); add( r.id, r.kind, @@ -351,16 +344,16 @@ export function planMutation( if (input.type === 'SetRiskState') { const r = get(input.riskId); if (r.kind !== 'risk' || r.frontmatter.state !== 'open') - throw new EffortGraphValidationError('Risk is not open'); + throw new ProofValidationError('Risk is not open'); const evidence = input.evidence.map(get); for (const x of evidence) if (x.frontmatter.effort !== r.frontmatter.effort) - throw new EffortGraphValidationError('Different effort'); + throw new ProofValidationError('Different effort'); if ( input.state === 'realized' && !evidence.some((x) => x.kind === 'finding') ) - throw new EffortGraphValidationError('Realized risk requires finding'); + throw new ProofValidationError('Realized risk requires finding'); add( r.id, r.kind, @@ -369,5 +362,5 @@ export function planMutation( ); return [...writes.values()]; } - throw new EffortGraphValidationError('Unsupported mutation'); + throw new ProofValidationError('Unsupported mutation'); } diff --git a/packages/effort-graph/src/preset.ts b/packages/proof/src/preset.ts similarity index 94% rename from packages/effort-graph/src/preset.ts rename to packages/proof/src/preset.ts index f702d61c..a5743c1c 100644 --- a/packages/effort-graph/src/preset.ts +++ b/packages/proof/src/preset.ts @@ -2,9 +2,7 @@ import type { ContentEntry } from '@flatbread/core'; const CITE_REFS = { cites: 'Citation' } as const; -export function effortGraphContent( - root = '.flatbread-efforts' -): ContentEntry[] { +export function proofContent(root = '.flatbread-proof'): ContentEntry[] { // Union refs intentionally stay out of Flatbread refs; they target multiple collections. // `cites` is homogeneous → Citation so core validates + GraphQL-resolves the edge. // Citation may optionally ref a Blob; a Citation body alone (e.g. a URL) is valid. @@ -92,7 +90,7 @@ function equalRefs( ); } -export function findEffortGraphContentRoot( +export function findProofContentRoot( content: readonly Pick[] ): string | undefined { const names = [ @@ -113,7 +111,7 @@ export function findEffortGraphContentRoot( ? effort.path.slice(0, -'/efforts'.length) : undefined; if (!root) return undefined; - const expected = effortGraphContent(root); + const expected = proofContent(root); if ( names.some( (name) => diff --git a/packages/effort-graph/src/read.ts b/packages/proof/src/read.ts similarity index 84% rename from packages/effort-graph/src/read.ts rename to packages/proof/src/read.ts index 7296f8d1..703cbb4b 100644 --- a/packages/effort-graph/src/read.ts +++ b/packages/proof/src/read.ts @@ -53,48 +53,48 @@ export type ReadQuery = export interface ConsistencyErrorShape { error: { code: - | 'EFFORT_GRAPH_GENERATION_WAIT_TIMEOUT' - | 'EFFORT_GRAPH_LIVE_SCHEMA_REJECTED' - | 'EFFORT_GRAPH_INVALID_GENERATION'; + | 'PROOF_GENERATION_WAIT_TIMEOUT' + | 'PROOF_LIVE_SCHEMA_REJECTED' + | 'PROOF_INVALID_GENERATION'; message: string; requested_generation: string; timeout_ms?: number; }; } -export class EffortGraphReadValidationError extends Error { +export class ProofReadValidationError extends Error { readonly shape: { error: { - code: 'EFFORT_GRAPH_INVALID_GENERATION' | 'EFFORT_GRAPH_INVALID_ARGUMENT'; + code: 'PROOF_INVALID_GENERATION' | 'PROOF_INVALID_ARGUMENT'; message: string; }; }; constructor( - code: 'EFFORT_GRAPH_INVALID_GENERATION' | 'EFFORT_GRAPH_INVALID_ARGUMENT', + code: 'PROOF_INVALID_GENERATION' | 'PROOF_INVALID_ARGUMENT', message: string ) { super(message); - this.name = 'EffortGraphReadValidationError'; + this.name = 'ProofReadValidationError'; this.shape = { error: { code, message } }; } } -export class EffortGraphInvalidCursorError extends Error { +export class ProofInvalidCursorError extends Error { readonly shape = { - error: { code: 'EFFORT_GRAPH_INVALID_CURSOR' as const, message: '' }, + error: { code: 'PROOF_INVALID_CURSOR' as const, message: '' }, }; constructor(message: string) { super(message); - this.name = 'EffortGraphInvalidCursorError'; + this.name = 'ProofInvalidCursorError'; this.shape.error.message = message; } } -export class EffortGraphConsistencyError extends Error { +export class ProofConsistencyError extends Error { readonly shape: ConsistencyErrorShape; constructor(shape: ConsistencyErrorShape) { super(shape.error.message); - this.name = 'EffortGraphConsistencyError'; + this.name = 'ProofConsistencyError'; this.shape = shape; } } @@ -132,13 +132,13 @@ async function servedGeneration( if (wanted !== undefined && current < wanted) { const shape: ConsistencyErrorShape = { error: { - code: 'EFFORT_GRAPH_GENERATION_WAIT_TIMEOUT', - message: `Durable Effort Graph generation ${wanted} was not observed (current: ${current})`, + code: 'PROOF_GENERATION_WAIT_TIMEOUT', + message: `Durable Proof generation ${wanted} was not observed (current: ${current})`, requested_generation: strict!.min_generation, timeout_ms: timeout, }, }; - throw new EffortGraphConsistencyError(shape); + throw new ProofConsistencyError(shape); } return String(current); } @@ -149,8 +149,8 @@ export function parseGenerationToken(value: unknown): number { !/^(0|[1-9]\d*)$/.test(value) || !Number.isSafeInteger(Number(value)) ) - throw new EffortGraphReadValidationError( - 'EFFORT_GRAPH_INVALID_GENERATION', + throw new ProofReadValidationError( + 'PROOF_INVALID_GENERATION', 'strict-min-generation must be a canonical non-negative safe integer string' ); return Number(value); diff --git a/packages/effort-graph/src/schemas.ts b/packages/proof/src/schemas.ts similarity index 97% rename from packages/effort-graph/src/schemas.ts rename to packages/proof/src/schemas.ts index 6062cc19..048a19e7 100644 --- a/packages/effort-graph/src/schemas.ts +++ b/packages/proof/src/schemas.ts @@ -108,7 +108,7 @@ export const SetRiskStateSchema = z.object({ state: z.enum(['realized', 'accepted']), evidence: id.array().min(1), }); -export const EffortGraphMutationSchema = z.discriminatedUnion('type', [ +export const ProofMutationSchema = z.discriminatedUnion('type', [ CreateEffortSchema, SetEffortStatusSchema, WriteIssueSchema, @@ -125,7 +125,7 @@ export const EffortGraphMutationSchema = z.discriminatedUnion('type', [ MitigateRiskSchema, SetRiskStateSchema, ]); -export type EffortGraphMutation = z.input; +export type ProofMutation = z.input; export const EffortFrontmatterSchema = z .object({ id, diff --git a/packages/effort-graph/src/snapshot.ts b/packages/proof/src/snapshot.ts similarity index 68% rename from packages/effort-graph/src/snapshot.ts rename to packages/proof/src/snapshot.ts index ec470861..c84647ac 100644 --- a/packages/effort-graph/src/snapshot.ts +++ b/packages/proof/src/snapshot.ts @@ -1,47 +1,47 @@ import { readdir, readFile } from 'node:fs/promises'; import { join, relative } from 'node:path'; -import { EffortGraphValidationError } from './errors.js'; +import { ProofValidationError } from './errors.js'; import { parseDocument } from './frontmatter.js'; import { KIND_DIRECTORY } from './ids.js'; import type { PrimitiveKind } from './types.js'; -export interface EffortGraphSnapshotArtifact { +export interface ProofSnapshotArtifact { readonly id: string; readonly kind: PrimitiveKind; readonly path: string; readonly frontmatter: Readonly>; readonly body: string; } -export interface EffortGraphSnapshotArtifactInput - extends Omit { +export interface ProofSnapshotArtifactInput + extends Omit { readonly frontmatter: Readonly>; readonly rawBytes: Buffer; } -export interface EffortGraphSnapshot { - getRecord(id: string): EffortGraphSnapshotArtifact | undefined; +export interface ProofSnapshot { + getRecord(id: string): ProofSnapshotArtifact | undefined; hasId(id: string): boolean; - recordsByEffort(effortId: string): readonly EffortGraphSnapshotArtifact[]; - recordsByKind(kind: PrimitiveKind): readonly EffortGraphSnapshotArtifact[]; + recordsByEffort(effortId: string): readonly ProofSnapshotArtifact[]; + recordsByKind(kind: PrimitiveKind): readonly ProofSnapshotArtifact[]; siblingDecisions( effortId: string, options?: Readonly<{ state?: string; excludeId?: string }> - ): readonly EffortGraphSnapshotArtifact[]; + ): readonly ProofSnapshotArtifact[]; getRawBytes(id: string): Buffer | undefined; } -export interface EffortGraphSnapshotSource { - buildSnapshot(rootDir: string): Promise; +export interface ProofSnapshotSource { + buildSnapshot(rootDir: string): Promise; } -export function createEffortGraphSnapshot( - artifacts: readonly EffortGraphSnapshotArtifactInput[] -): EffortGraphSnapshot { - const byId = new Map(); +export function createProofSnapshot( + artifacts: readonly ProofSnapshotArtifactInput[] +): ProofSnapshot { + const byId = new Map(); const raw = new Map(); - const byEffort = new Map(); - const byKind = new Map(); + const byEffort = new Map(); + const byKind = new Map(); for (const input of artifacts) { if (byId.has(input.id)) - throw new EffortGraphValidationError( + throw new ProofValidationError( `Duplicate id ${input.id} at ${input.path}` ); const record = Object.freeze({ @@ -63,7 +63,7 @@ export function createEffortGraphSnapshot( kindList.push(record); byKind.set(record.kind, kindList); } - const freezeLists = (map: Map) => { + const freezeLists = (map: Map) => { for (const list of map.values()) Object.freeze(list); }; freezeLists(byEffort); @@ -88,10 +88,10 @@ export function createEffortGraphSnapshot( }; } -export async function buildEffortGraphSnapshot( +export async function buildProofSnapshot( rootDir: string -): Promise { - const artifacts: EffortGraphSnapshotArtifactInput[] = []; +): Promise { + const artifacts: ProofSnapshotArtifactInput[] = []; for (const kind of Object.keys(KIND_DIRECTORY) as PrimitiveKind[]) { const dir = join(rootDir, KIND_DIRECTORY[kind]); let names: string[]; @@ -117,14 +117,14 @@ export async function buildEffortGraphSnapshot( const seen = new Set(); for (const artifact of artifacts) { if (seen.has(artifact.id)) - throw new EffortGraphValidationError( + throw new ProofValidationError( `Duplicate id ${artifact.id} at ${join(rootDir, artifact.path)}` ); seen.add(artifact.id); } - return createEffortGraphSnapshot(artifacts); + return createProofSnapshot(artifacts); } -export const filesystemEffortGraphSnapshotSource: EffortGraphSnapshotSource = { - buildSnapshot: buildEffortGraphSnapshot, +export const filesystemProofSnapshotSource: ProofSnapshotSource = { + buildSnapshot: buildProofSnapshot, }; diff --git a/packages/effort-graph/src/types.ts b/packages/proof/src/types.ts similarity index 88% rename from packages/effort-graph/src/types.ts rename to packages/proof/src/types.ts index 83d542b6..f7f48587 100644 --- a/packages/effort-graph/src/types.ts +++ b/packages/proof/src/types.ts @@ -42,7 +42,7 @@ export interface IndexedArtifact { frontmatter: Record; body: string; } -export interface EffortGraphIndex { +export interface ProofIndex { getRecord(id: string): Promise; recordsByEffort(effortId: string): Promise; recordsByKind(kind: PrimitiveKind): Promise; @@ -55,19 +55,17 @@ export interface EffortGraphIndex { export interface WriterLockOptions { leaseMs?: number; } -export interface EffortGraphWriterOptions { +export interface ProofWriterOptions { rootDir: string; - index?: import('./snapshot.js').EffortGraphSnapshotSource; + index?: import('./snapshot.js').ProofSnapshotSource; publisher?: CommittedGenerationPublisher; clock?: () => Date; randomBytes?: (length: number) => Uint8Array; lockOptions?: Partial; } -export interface EffortGraphWriter { +export interface ProofWriter { recover(): Promise; - mutate( - input: import('./schemas.js').EffortGraphMutation - ): Promise; + mutate(input: import('./schemas.js').ProofMutation): Promise; } export interface RecoveryResult { action: 'none' | 'rolled_back' | 'completed'; diff --git a/packages/effort-graph/src/writer.ts b/packages/proof/src/writer.ts similarity index 88% rename from packages/effort-graph/src/writer.ts rename to packages/proof/src/writer.ts index baf2be11..51f16d44 100644 --- a/packages/effort-graph/src/writer.ts +++ b/packages/proof/src/writer.ts @@ -3,18 +3,16 @@ import { join } from 'node:path'; import { acquireWriterLock } from './lock.js'; import { commitJournal, recoverJournal } from './journal.js'; import { planMutation } from './planner.js'; -import { filesystemEffortGraphSnapshotSource } from './snapshot.js'; +import { filesystemProofSnapshotSource } from './snapshot.js'; import { parseDocument } from './frontmatter.js'; import type { - EffortGraphWriter, - EffortGraphWriterOptions, + ProofWriter, + ProofWriterOptions, MutationResult, WrittenArtifact, } from './types.js'; -export function createEffortGraphWriter( - options: EffortGraphWriterOptions -): EffortGraphWriter { - const snapshotSource = options.index ?? filesystemEffortGraphSnapshotSource, +export function createProofWriter(options: ProofWriterOptions): ProofWriter { + const snapshotSource = options.index ?? filesystemProofSnapshotSource, publisher = options.publisher ?? { publish: async () => {} }, clock = options.clock ?? (() => new Date()); async function recover() { diff --git a/packages/effort-graph/tsconfig.json b/packages/proof/tsconfig.json similarity index 100% rename from packages/effort-graph/tsconfig.json rename to packages/proof/tsconfig.json diff --git a/packages/effort-graph/tsup.config.ts b/packages/proof/tsup.config.ts similarity index 100% rename from packages/effort-graph/tsup.config.ts rename to packages/proof/tsup.config.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e58403b4..4582c947 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -36,9 +36,9 @@ importers: '@cursor/sdk': specifier: ^1.0.9 version: 1.0.12 - '@flatbread/effort-graph': + '@flatbread/proof': specifier: workspace:* - version: link:packages/effort-graph + version: link:packages/proof '@nrwl/workspace': specifier: 14.4.3 version: 14.4.3(@swc/core@1.13.3)(eslint@7.32.0)(prettier@2.7.1)(ts-node@10.9.1(@swc/core@1.13.3)(@types/node@16.11.47)(typescript@4.7.4))(typescript@4.7.4) @@ -324,36 +324,11 @@ importers: specifier: 4.7.4 version: 4.7.4 - packages/effort-graph: - dependencies: - '@flatbread/core': - specifier: workspace:* - version: link:../core - gray-matter: - specifier: ^4.0.3 - version: 4.0.3 - zod: - specifier: ^3.24.1 - version: 3.25.76 - devDependencies: - '@flatbread/transformer-markdown': - specifier: workspace:* - version: link:../transformer-markdown - '@types/node': - specifier: 25.6.2 - version: 25.6.2 - tsup: - specifier: 8.5.1 - version: 8.5.1(@swc/core@1.13.3)(jiti@2.5.1)(postcss@8.5.14)(tsx@4.21.0)(typescript@6.0.3)(yaml@2.8.1) - typescript: - specifier: 6.0.3 - version: 6.0.3 - packages/explorer: dependencies: - '@flatbread/effort-graph': + '@flatbread/proof': specifier: workspace:* - version: link:../effort-graph + version: link:../proof devDependencies: '@react-three/drei': specifier: ^10.0.6 @@ -433,12 +408,12 @@ importers: '@flatbread/core': specifier: workspace:* version: link:../core - '@flatbread/effort-graph': - specifier: workspace:* - version: link:../effort-graph '@flatbread/explorer': specifier: workspace:* version: link:../explorer + '@flatbread/proof': + specifier: workspace:* + version: link:../proof '@flatbread/source-filesystem': specifier: workspace:* version: link:../source-filesystem @@ -504,6 +479,31 @@ importers: specifier: 5.3.4 version: 5.3.4 + packages/proof: + dependencies: + '@flatbread/core': + specifier: workspace:* + version: link:../core + gray-matter: + specifier: ^4.0.3 + version: 4.0.3 + zod: + specifier: ^3.24.1 + version: 3.25.76 + devDependencies: + '@flatbread/transformer-markdown': + specifier: workspace:* + version: link:../transformer-markdown + '@types/node': + specifier: 25.6.2 + version: 25.6.2 + tsup: + specifier: 8.5.1 + version: 8.5.1(@swc/core@1.13.3)(jiti@2.5.1)(postcss@8.5.14)(tsx@4.21.0)(typescript@6.0.3)(yaml@2.8.1) + typescript: + specifier: 6.0.3 + version: 6.0.3 + packages/resolver-svimg: devDependencies: '@flatbread/core': @@ -10957,7 +10957,7 @@ snapshots: '@jest/console@27.5.1': dependencies: '@jest/types': 27.5.1 - '@types/node': 22.19.18 + '@types/node': 20.19.10 chalk: 4.1.0 jest-message-util: 27.5.1 jest-util: 27.5.1 @@ -10967,14 +10967,14 @@ snapshots: dependencies: '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 22.19.18 + '@types/node': 20.19.10 jest-mock: 27.5.1 '@jest/fake-timers@27.5.1': dependencies: '@jest/types': 27.5.1 '@sinonjs/fake-timers': 8.1.0 - '@types/node': 22.19.18 + '@types/node': 20.19.10 jest-message-util: 27.5.1 jest-mock: 27.5.1 jest-util: 27.5.1 @@ -10992,7 +10992,7 @@ snapshots: '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 22.19.18 + '@types/node': 20.19.10 chalk: 4.1.0 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -11061,7 +11061,7 @@ snapshots: dependencies: '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 22.19.18 + '@types/node': 20.19.10 '@types/yargs': 16.0.9 chalk: 4.1.0 @@ -11834,7 +11834,7 @@ snapshots: '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 - '@types/node': 22.19.18 + '@types/node': 20.19.10 '@types/chai@5.2.3': dependencies: @@ -11843,7 +11843,7 @@ snapshots: '@types/connect@3.4.38': dependencies: - '@types/node': 22.19.18 + '@types/node': 20.19.10 '@types/cookie@0.6.0': {} @@ -11872,7 +11872,7 @@ snapshots: '@types/express-serve-static-core@4.19.6': dependencies: - '@types/node': 22.19.18 + '@types/node': 20.19.10 '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 '@types/send': 0.17.5 @@ -11891,7 +11891,7 @@ snapshots: '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 22.19.18 + '@types/node': 20.19.10 '@types/gradient-string@1.1.2': dependencies: @@ -11930,7 +11930,7 @@ snapshots: '@types/jsonfile@6.1.4': dependencies: - '@types/node': 22.19.18 + '@types/node': 20.19.10 '@types/lodash-es@4.17.6': dependencies: @@ -12000,7 +12000,7 @@ snapshots: '@types/resolve@1.17.1': dependencies: - '@types/node': 22.19.18 + '@types/node': 20.19.10 '@types/sade@1.7.4': dependencies: @@ -12013,12 +12013,12 @@ snapshots: '@types/send@0.17.5': dependencies: '@types/mime': 1.3.5 - '@types/node': 22.19.18 + '@types/node': 20.19.10 '@types/serve-static@1.15.8': dependencies: '@types/http-errors': 2.0.5 - '@types/node': 22.19.18 + '@types/node': 20.19.10 '@types/send': 0.17.5 '@types/stack-utils@2.0.3': {} @@ -12036,7 +12036,7 @@ snapshots: '@types/through@0.0.33': dependencies: - '@types/node': 22.19.18 + '@types/node': 20.19.10 '@types/tinycolor2@1.4.6': {} @@ -12048,7 +12048,7 @@ snapshots: '@types/ws@8.18.1': dependencies: - '@types/node': 22.19.18 + '@types/node': 20.19.10 '@types/yargs-parser@21.0.3': {} @@ -15271,7 +15271,7 @@ snapshots: '@jest/environment': 27.5.1 '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 22.19.18 + '@types/node': 20.19.10 chalk: 4.1.0 co: 4.6.0 dedent: 0.7.0 @@ -15348,7 +15348,7 @@ snapshots: '@jest/environment': 27.5.1 '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 22.19.18 + '@types/node': 20.19.10 jest-mock: 27.5.1 jest-util: 27.5.1 jsdom: 16.7.0 @@ -15363,7 +15363,7 @@ snapshots: '@jest/environment': 27.5.1 '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 22.19.18 + '@types/node': 20.19.10 jest-mock: 27.5.1 jest-util: 27.5.1 @@ -15373,7 +15373,7 @@ snapshots: dependencies: '@jest/types': 27.5.1 '@types/graceful-fs': 4.1.9 - '@types/node': 22.19.18 + '@types/node': 20.19.10 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -15392,7 +15392,7 @@ snapshots: '@jest/source-map': 27.5.1 '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 22.19.18 + '@types/node': 20.19.10 chalk: 4.1.0 co: 4.6.0 expect: 27.5.1 @@ -15435,7 +15435,7 @@ snapshots: jest-mock@27.5.1: dependencies: '@jest/types': 27.5.1 - '@types/node': 22.19.18 + '@types/node': 20.19.10 jest-pnp-resolver@1.2.3(jest-resolve@27.5.1): optionalDependencies: @@ -15463,7 +15463,7 @@ snapshots: '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 22.19.18 + '@types/node': 20.19.10 chalk: 4.1.0 emittery: 0.8.1 graceful-fs: 4.2.11 @@ -15514,7 +15514,7 @@ snapshots: jest-serializer@27.5.1: dependencies: - '@types/node': 22.19.18 + '@types/node': 20.19.10 graceful-fs: 4.2.11 jest-snapshot@27.5.1: @@ -15547,7 +15547,7 @@ snapshots: jest-util@27.5.1: dependencies: '@jest/types': 27.5.1 - '@types/node': 22.19.18 + '@types/node': 20.19.10 chalk: 4.1.0 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -15564,7 +15564,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 22.19.18 + '@types/node': 20.19.10 merge-stream: 2.0.0 supports-color: 8.1.1 diff --git a/scripts/bumpVersions.test.ts b/scripts/bumpVersions.test.ts index 026fabdb..1659b676 100644 --- a/scripts/bumpVersions.test.ts +++ b/scripts/bumpVersions.test.ts @@ -12,7 +12,7 @@ type TestPackage = WorkspaceBumpPackage & { const packages: TestPackage[] = [ { - name: '@flatbread/effort-graph', + name: '@flatbread/proof', changedSinceLastPublish: true, }, { @@ -27,7 +27,7 @@ const packages: TestPackage[] = [ { name: 'flatbread', dependencies: { - '@flatbread/effort-graph': 'workspace:*', + '@flatbread/proof': 'workspace:*', '@flatbread/codegen': 'workspace:^', }, devDependencies: { '@flatbread/utils': 'workspace:*' }, @@ -37,10 +37,8 @@ const packages: TestPackage[] = [ test('workspace dependent closure follows production workspace dependencies', (t) => { t.deepEqual( - [ - ...getWorkspaceDependentClosure(packages, ['@flatbread/effort-graph']), - ].sort(), - ['@flatbread/effort-graph', 'flatbread'] + [...getWorkspaceDependentClosure(packages, ['@flatbread/proof'])].sort(), + ['@flatbread/proof', 'flatbread'] ); t.deepEqual( [...getWorkspaceDependentClosure(packages, ['@flatbread/utils'])].sort(), @@ -54,7 +52,7 @@ test('changed package propagation includes transitive public dependents', (t) => .filter((pkg) => pkg.changedSinceLastPublish) .map((pkg) => pkg.name) .sort(), - ['@flatbread/codegen', '@flatbread/effort-graph', 'flatbread'] + ['@flatbread/codegen', '@flatbread/proof', 'flatbread'] ); }); @@ -62,15 +60,15 @@ test('selection validation reports omitted required dependents', (t) => { t.deepEqual( validateBumpSelection( packages, - ['@flatbread/effort-graph', '@flatbread/codegen', 'flatbread'], - ['@flatbread/effort-graph'] + ['@flatbread/proof', '@flatbread/codegen', 'flatbread'], + ['@flatbread/proof'] ), ['flatbread'] ); t.deepEqual( validateBumpSelection( packages, - ['@flatbread/effort-graph', '@flatbread/codegen', 'flatbread'], + ['@flatbread/proof', '@flatbread/codegen', 'flatbread'], ['flatbread'] ), [] diff --git a/scripts/bumpVersions.ts b/scripts/bumpVersions.ts index 6a334251..ee1d3dad 100644 --- a/scripts/bumpVersions.ts +++ b/scripts/bumpVersions.ts @@ -356,16 +356,16 @@ async function main(): Promise { const flatbreadManifest = JSON.parse( await fs.readFile('packages/flatbread/package.json', 'utf8') ); - const effortGraphManifest = JSON.parse( - await fs.readFile('packages/effort-graph/package.json', 'utf8') + const proofManifest = JSON.parse( + await fs.readFile('packages/proof/package.json', 'utf8') ); await fs.writeFile( - 'packages/effort-graph/skills/effort-graph/release.json', + 'packages/proof/skills/proof/release.json', `${JSON.stringify( { format: 1, flatbreadVersion: flatbreadManifest.version, - effortGraphVersion: effortGraphManifest.version, + proofVersion: proofManifest.version, gitTag: `v${flatbreadManifest.version}`, }, null, diff --git a/scripts/publish.test.ts b/scripts/publish.test.ts index f5792c28..331c64dd 100644 --- a/scripts/publish.test.ts +++ b/scripts/publish.test.ts @@ -11,7 +11,7 @@ test('publish ordering is a stable topological sort', (t) => { name: 'flatbread', dirName: 'flatbread', dependencies: { - '@flatbread/effort-graph': 'workspace:*', + '@flatbread/proof': 'workspace:*', '@flatbread/codegen': 'workspace:*', }, }, @@ -21,7 +21,7 @@ test('publish ordering is a stable topological sort', (t) => { dependencies: { '@flatbread/utils': 'workspace:*' }, }, { name: '@flatbread/utils', dirName: 'utils' }, - { name: '@flatbread/effort-graph', dirName: 'effort-graph' }, + { name: '@flatbread/proof', dirName: 'proof' }, { name: '@flatbread/config', dirName: 'config' }, ]); @@ -29,7 +29,7 @@ test('publish ordering is a stable topological sort', (t) => { sorted.map((pkg) => pkg.name), [ '@flatbread/config', - '@flatbread/effort-graph', + '@flatbread/proof', '@flatbread/utils', '@flatbread/codegen', 'flatbread', diff --git a/tsconfig.json b/tsconfig.json index f5820c64..bf99c47b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,7 +17,7 @@ "@flatbread/resolver-svimg": ["./packages/resolver-svimg/src/index.ts"], "@flatbread/utils": ["./packages/utils/src/index.ts"], "@flatbread/explorer": ["./packages/explorer/src/node/index.ts"], - "@flatbread/effort-graph": ["./packages/effort-graph/src/index.ts"], + "@flatbread/proof": ["./packages/proof/src/index.ts"], "@flatbread/source-filesystem": [ "./packages/source-filesystem/src/index.ts" ],