@davidorex/pi-context 0.32.0 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -557,6 +557,86 @@ export declare function resolveConflict(cwd: string, name: string, schema?: unkn
557
557
  wroteSchema: boolean;
558
558
  baseAdvancedTo: string;
559
559
  };
560
+ /**
561
+ * `context-reconcile` result (FEAT-011 — FGAP-116). `deltas` lists every
562
+ * rollup-kind item whose STORED status diverges from its DERIVED membership-
563
+ * rollup status (from → stored value, to → derived value, per the declaring
564
+ * derived-status invariant). Under `dryRun` the deltas are the exact set a
565
+ * live run would apply and nothing is written (`applied` 0); a live run
566
+ * applies exactly that set through the standard validated write path and
567
+ * reports `applied`. Scope v1 is derived-status deltas ONLY: the op never
568
+ * writes an authored-status kind (feature/gap/issue/task buckets are human
569
+ * judgment) and never touches prose — those classes are flagged for review by
570
+ * validate, not auto-repaired.
571
+ */
572
+ export interface ReconcileResult {
573
+ error?: string;
574
+ dryRun: boolean;
575
+ deltas: Array<{
576
+ id: string;
577
+ block: string;
578
+ from: string;
579
+ to: string;
580
+ invariant: string;
581
+ }>;
582
+ applied: number;
583
+ /**
584
+ * Declared-baseline staleness sweep (FEAT-011 criterion 6 — TASK-089):
585
+ * every stale_conditions-bearing item whose status buckets complete and
586
+ * whose typed condition fired or whose content pin drifted, transitioned
587
+ * to `stale`. Under dryRun the exact set a live run would apply; a live
588
+ * run applies it through the standard validated write path. Flag-only
589
+ * anchor-drift items (no transition shape) are validate's, not here.
590
+ */
591
+ stalenessTransitions: Array<{
592
+ id: string;
593
+ block: string;
594
+ from: string;
595
+ to: string;
596
+ reasons: string[];
597
+ }>;
598
+ stalenessApplied: number;
599
+ /** Ceremony-entry identity establishment (DEC-0020), live runs only. */
600
+ substrateIdEstablished?: string;
601
+ }
602
+ /**
603
+ * `/context reconcile` engine (FEAT-011 — the repair half of the derived-status
604
+ * invariant class). Computes every stored-vs-derived status delta for the
605
+ * kinds the config's derived-status invariants declare (paired with their
606
+ * `state_derivation.rollups` entries), using the SAME shared completeness
607
+ * helper the state derivation and the invariant class use
608
+ * (`derivedRollupComplete`) — the preview, the detector, and the repair
609
+ * cannot disagree. A live run converges each delta through `updateItemInBlock`
610
+ * (identity-stamped, AJV-validated, envelope-stamped, attested to the invoking
611
+ * writer via `ctx`): a converge-write is not authoring — the written value IS
612
+ * the derivation (the schema_version stamp argument). Ceremony discipline:
613
+ * seeds the catalog config decls at entry, and a LIVE run establishes
614
+ * substrate identity when absent (it reaches identity-stamping writes;
615
+ * DEC-0020). Deltas are deduplicated per (block, id) across invariants.
616
+ */
617
+ export declare function reconcileContext(cwd: string, { dryRun }?: {
618
+ dryRun?: boolean;
619
+ }, ctx?: DispatchContext): ReconcileResult;
620
+ /**
621
+ * Converge-on-write hook (FEAT-011 criterion 2 — FGAP-116's last mechanism,
622
+ * the schema_version template applied to rollup-kind stored status). Invoked
623
+ * AFTER a sanctioned mutating op's write lands (the op's own lock is already
624
+ * released — sequential lock acquisition, no nesting): recomputes the
625
+ * derived-status delta set with the SAME core the reconcile ceremony uses and
626
+ * stamps every affected rollup item's stored status through the standard
627
+ * validated write path — a converge-stamp is not authoring; the written value
628
+ * IS the derivation. Config-driven opt-in: a substrate with no
629
+ * `derived-status` invariant (or no `state_derivation.rollups`) computes an
630
+ * empty set and performs no writes, so non-declaring and legacy substrates
631
+ * are byte-identical to before. BEST-EFFORT by design: it never establishes
632
+ * identity (a convergence side-effect minting a substrate_id would be a lazy
633
+ * mint, DEC-0012) and never fails the caller's already-landed write — an
634
+ * apply failure leaves the divergence for the `derived-status` invariant to
635
+ * detect and `context-reconcile` (the ceremony with the establishment +
636
+ * error surface) to repair. Returns the converged set, or null when there was
637
+ * nothing to converge or the hook could not run.
638
+ */
639
+ export declare function convergeDerivedStatusAfterWrite(cwd: string, ctx?: DispatchContext): ReconcileResult["deltas"] | null;
560
640
  /**
561
641
  * Blocked-resolution commit op (TASK-051 — FGAP-080) — the resolution half of
562
642
  * the blocked-resync loop `update` opens. After `update` REFUSES a catalog-ahead
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAA2B,MAAM,iCAAiC,CAAC;AAI7F,OAAO,EASN,KAAK,iBAAiB,EAItB,MAAM,cAAc,CAAC;AAetB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAuB7D,OAAO,EAAe,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AA6KrE;;;;;;;;;;;;;;GAcG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;IAClD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBACf,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;CAU/C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CA0DrG;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB;;;;;;;;;;;;;;OAcG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,sBAAsB;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,oBAAoB,GAAG,mBAAmB,GAAG,cAAc,CAAC;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACpC;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAwOD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAS1G;AAkQD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,gCAAgC,CAC/C,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,GACf;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,sBAAsB,EAAE,CAAA;CAAE,CA2DnG;AA6UD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,aAAa,CA8NhG;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EACF,SAAS,GACT,eAAe,GACf,kBAAkB,GAClB,eAAe,GACf,aAAa,GACb,iBAAiB,GACjB,mBAAmB,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAAA;KAAE,CAAC;CACvF;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IACjC,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACvE;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAmH1D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAkCnE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,WAAW,YAAY;IAC5B,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,MAAM,EAAE,OAAO,CAAC;IAChB,qFAAqF;IACrF,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,qFAAqF;IACrF,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8FAA8F;IAC9F,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;;;;;;;;;OASG;IACH,aAAa,EAAE,aAAa,EAAE,CAAC;IAC/B,4FAA4F;IAC5F,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;;;;OAIG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB;;;;OAIG;IACH,SAAS,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,cAAc,EAAE,CAAA;KAAE,CAAC,CAAC;IAChE,gGAAgG;IAChG,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IACpE,sDAAsD;IACtD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB;;;;;;;;OAQG;IACH,iBAAiB,EAAE,iBAAiB,CAAC;IACrC;;;;;;;;OAQG;IACH,oBAAoB,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1E;;;;;;;;;;;;;;;;OAgBG;IACH,kBAAkB,CAAC,EAAE;QACpB,OAAO,EAAE;YACR,QAAQ,EAAE,MAAM,EAAE,CAAC;YACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;YACnB,MAAM,EAAE,MAAM,EAAE,CAAC;YACjB,iBAAiB,EAAE,iBAAiB,CAAC;YACrC,oBAAoB,EAAE,KAAK,CAAC;gBAAE,MAAM,EAAE,MAAM,CAAC;gBAAC,IAAI,EAAE,MAAM,CAAC;gBAAC,EAAE,EAAE,MAAM,CAAA;aAAE,CAAC,CAAC;SAC1E,CAAC;QACF,UAAU,EAAE;YACX,OAAO,EAAE,MAAM,EAAE,CAAC;YAClB,OAAO,EAAE,MAAM,EAAE,CAAC;YAClB,SAAS,EAAE,MAAM,EAAE,CAAC;SACpB,CAAC;QACF,OAAO,EAAE,MAAM,CAAC;KAChB,CAAC;IACF;;;;;;OAMG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,MAAc,EAAE,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,YAAY,CA8ZtG;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACpC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,MAAM,GACb,MAAM,GAAG,IAAI,CAiBf;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAY3E;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,eAAe,CAC9B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,OAAO,EAChB,GAAG,CAAC,EAAE,eAAe,GACnB;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CA+CtE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,cAAc,CAC7B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,GAAG,CAAC,EAAE,eAAe,GAEnB;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,sBAAsB,EAAE,CAAC;IAAC,sBAAsB,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5G;IACA,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,IAAI,CAAC;IACf,oBAAoB,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1E,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,sBAAsB,CAAC,EAAE,MAAM,CAAC;CAC/B,CA2MH;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,YAAY,CAAC,WAAW,CAAC,GAAG,MAAM,CAoB5E;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,aAAa,CAAC,aAAa,EAAE,aAAa,EAAE,GAAG,MAAM,CAsDpE;AAqID;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAyCjH;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CAiB7F;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAgClG;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC,CAqCtF;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAyC7F;AAsFD,QAAA,MAAM,SAAS,GAAI,IAAI,YAAY,SAwRlC,CAAC;AAEF,eAAe,SAAS,CAAC;AAQzB,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAChH,OAAO,EACN,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,qBAAqB,EACrB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,EACnB,aAAa,GACb,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAErG,OAAO,EACN,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,YAAY,EACZ,oBAAoB,EACpB,eAAe,EACf,UAAU,EACV,UAAU,EACV,gBAAgB,GAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACjG,OAAO,EACN,WAAW,EACX,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,aAAa,EACb,uBAAuB,EACvB,iBAAiB,EACjB,KAAK,OAAO,EACZ,QAAQ,EACR,eAAe,GACf,MAAM,mBAAmB,CAAC;AAK3B,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -6,12 +6,12 @@ import { execSync } from "node:child_process";
6
6
  import fs from "node:fs";
7
7
  import path from "node:path";
8
8
  import { fileURLToPath } from "node:url";
9
- import { forEachBlockArray, readBlock, readBlockForDir, writeBlockForDir } from "./block-api.js";
9
+ import { forEachBlockArray, readBlock, readBlockForDir, updateItemInBlock, writeBlockForDir } from "./block-api.js";
10
10
  import { computeContentHash, computeFileContentHash } from "./content-hash.js";
11
- import { adoptConception, installedBlockDestPath, installedSchemaDestPath, loadConfig, loadContext, mergeCatalogRegistries, reconcileActiveSubstrateRegistration, writeConfig, writeSkeletonConfig, } from "./context.js";
11
+ import { adoptConception, installedBlockDestPath, installedSchemaDestPath, loadConfig, loadContext, loadRelations, mergeCatalogRegistries, reconcileActiveSubstrateRegistration, writeConfig, writeSkeletonConfig, } from "./context.js";
12
12
  import { BootstrapNotFoundError, flipBootstrapPointer, migrationsPathForDir, mintSubstrateId, pendingBlockedPathForDir, resolveContextDir, SCHEMAS_DIR, schemasDir, tryResolveContextDir, writeBootstrapPointer, } from "./context-dir.js";
13
13
  import { registerSubstrate } from "./context-registry.js";
14
- import { contextState, findAppendableBlocks, validateContext } from "./context-sdk.js";
14
+ import { buildIdIndex, contextState, derivedRollupComplete, evaluateStalenessCandidates, findAppendableBlocks, validateContext, } from "./context-sdk.js";
15
15
  import { cleanGitEnv } from "./git-env.js";
16
16
  import { buildCurationSuggestions, loadLensView, renderLensView } from "./lens-view.js";
17
17
  import { buildFreshRegistryWithChain, getProjectMigrationRegistryForDir, invalidateMigrationRegistryForDir, } from "./migration-registry-loader.js";
@@ -20,11 +20,13 @@ import { getObject, putObject } from "./object-store.js";
20
20
  import { registerAll } from "./ops-registry.js";
21
21
  import { buildOrientationBlock, skillsDir } from "./orientation.js";
22
22
  import { loadPendingBlockedForDir, reconcilePendingBlockedForDir, } from "./pending-blocked-store.js";
23
+ import { discoverArrayKey } from "./read-element.js";
23
24
  import { loadRoadmap, renderRoadmap, validateRoadmap } from "./roadmap-plan.js";
24
25
  import { mergeSchema } from "./schema-merge.js";
25
26
  import { runMigrations } from "./schema-migrations.js";
26
27
  import { ValidationError, validate, validateBlockWithMigrationForDir } from "./schema-validator.js";
27
28
  import { writeSchemaCheckedForDir } from "./schema-write.js";
29
+ import { resolveStateDerivation, resolveStatusVocabulary as resolveStatusVocab } from "./status-vocab.js";
28
30
  import { checkForUpdates } from "./update-check.js";
29
31
  // ── Command handlers ────────────────────────────────────────────────────────
30
32
  /**
@@ -2159,6 +2161,186 @@ export function resolveConflict(cwd, name, schema, ctx) {
2159
2161
  }
2160
2162
  return { schemaName: name, wroteSchema, baseAdvancedTo: catalogHash };
2161
2163
  }
2164
+ /**
2165
+ * `/context reconcile` engine (FEAT-011 — the repair half of the derived-status
2166
+ * invariant class). Computes every stored-vs-derived status delta for the
2167
+ * kinds the config's derived-status invariants declare (paired with their
2168
+ * `state_derivation.rollups` entries), using the SAME shared completeness
2169
+ * helper the state derivation and the invariant class use
2170
+ * (`derivedRollupComplete`) — the preview, the detector, and the repair
2171
+ * cannot disagree. A live run converges each delta through `updateItemInBlock`
2172
+ * (identity-stamped, AJV-validated, envelope-stamped, attested to the invoking
2173
+ * writer via `ctx`): a converge-write is not authoring — the written value IS
2174
+ * the derivation (the schema_version stamp argument). Ceremony discipline:
2175
+ * seeds the catalog config decls at entry, and a LIVE run establishes
2176
+ * substrate identity when absent (it reaches identity-stamping writes;
2177
+ * DEC-0020). Deltas are deduplicated per (block, id) across invariants.
2178
+ */
2179
+ export function reconcileContext(cwd, { dryRun = false } = {}, ctx) {
2180
+ const result = { dryRun, deltas: [], applied: 0, stalenessTransitions: [], stalenessApplied: 0 };
2181
+ const destRoot = tryResolveContextDir(cwd);
2182
+ if (destRoot === null) {
2183
+ result.error =
2184
+ "No .pi-context.json bootstrap pointer found. Run /context init <substrate-dir> first to bootstrap the substrate.";
2185
+ return result;
2186
+ }
2187
+ seedCatalogConfigMigrationDecls(destRoot);
2188
+ if (!dryRun) {
2189
+ const establishedId = establishSubstrateIdentityAtEntry(cwd, destRoot);
2190
+ if (establishedId)
2191
+ result.substrateIdEstablished = establishedId;
2192
+ }
2193
+ const config = loadConfig(cwd);
2194
+ if (!config) {
2195
+ result.error = "No config.json found in substrate dir — run /context init <substrate-dir> first.";
2196
+ return result;
2197
+ }
2198
+ result.deltas = computeDerivedStatusDeltas(cwd, config);
2199
+ result.stalenessTransitions = computeStalenessTransitions(cwd);
2200
+ if (dryRun)
2201
+ return result;
2202
+ result.applied = applyDerivedStatusDeltas(cwd, config, result.deltas, ctx);
2203
+ result.stalenessApplied = applyStalenessTransitions(cwd, config, result.stalenessTransitions, ctx);
2204
+ return result;
2205
+ }
2206
+ /**
2207
+ * The transition slice of the declared-baseline staleness sweep: candidates
2208
+ * from the SAME evaluateStalenessCandidates helper validate flags with,
2209
+ * restricted to the transition-eligible kind, each becoming a stored-status
2210
+ * delta to `stale`. Flag-only anchor-drift candidates never transition.
2211
+ */
2212
+ function computeStalenessTransitions(cwd) {
2213
+ const index = buildIdIndex(cwd);
2214
+ return evaluateStalenessCandidates(cwd, index)
2215
+ .filter((c) => c.kind === "staleness-candidate")
2216
+ .map((c) => ({
2217
+ id: c.id,
2218
+ block: c.block,
2219
+ from: String(index.byRefname.get(c.id)?.item.status ?? ""),
2220
+ to: "stale",
2221
+ reasons: c.reasons,
2222
+ }));
2223
+ }
2224
+ /** Apply the complete-to-stale transitions through the standard validated write path. */
2225
+ function applyStalenessTransitions(cwd, config, transitions, ctx) {
2226
+ let applied = 0;
2227
+ for (const t of transitions) {
2228
+ const arrayKey = config.block_kinds?.find((bk) => bk.canonical_id === t.block)?.array_key ??
2229
+ (() => {
2230
+ const data = readBlock(cwd, t.block);
2231
+ const discovered = discoverArrayKey(data);
2232
+ if (discovered === null) {
2233
+ throw new Error(`context-reconcile: no array key discoverable for block '${t.block}'`);
2234
+ }
2235
+ return discovered;
2236
+ })();
2237
+ updateItemInBlock(cwd, t.block, arrayKey, (item) => String(item.id) === t.id, { status: t.to }, ctx);
2238
+ applied += 1;
2239
+ }
2240
+ return applied;
2241
+ }
2242
+ /**
2243
+ * Read-only core of the derived-status repair: the stored-vs-derived delta set
2244
+ * for every kind a `derived-status` invariant declares (paired with its
2245
+ * `state_derivation.rollups` entry), deduplicated per (block, id). Shared by
2246
+ * `reconcileContext` and the post-write convergence hook so the ceremony and
2247
+ * the hook compute the identical set.
2248
+ */
2249
+ function computeDerivedStatusDeltas(cwd, config) {
2250
+ const deltas = [];
2251
+ const sd = resolveStateDerivation(cwd);
2252
+ const declared = (config.invariants ?? []).filter((inv) => inv.class === "derived-status");
2253
+ if (sd === null || declared.length === 0)
2254
+ return deltas;
2255
+ const index = buildIdIndex(cwd);
2256
+ const edges = loadRelations(cwd);
2257
+ const vocab = resolveStatusVocab(cwd);
2258
+ const bucketOf = (item) => vocab[String(item.status)] ?? "unknown";
2259
+ const rollupByKind = new Map(sd.rollups.map((r) => [r.kind, r]));
2260
+ const roleDir = new Map();
2261
+ for (const rt of config.relation_types ?? []) {
2262
+ if (rt.role_direction !== undefined)
2263
+ roleDir.set(rt.canonical_id, rt.role_direction);
2264
+ }
2265
+ const seen = new Set();
2266
+ for (const inv of declared) {
2267
+ const entry = rollupByKind.get(inv.block);
2268
+ if (entry === undefined)
2269
+ continue; // inert declaration — nothing to derive against
2270
+ for (const loc of index.byRefname.values()) {
2271
+ if (loc.block !== inv.block)
2272
+ continue;
2273
+ const key = `${inv.block} ${loc.id}`;
2274
+ if (seen.has(key))
2275
+ continue;
2276
+ const derived = derivedRollupComplete(index, edges, roleDir, rollupByKind, bucketOf, loc.id)
2277
+ ? entry.complete_status
2278
+ : entry.incomplete_status;
2279
+ const stored = String(loc.item.status);
2280
+ if (stored === derived)
2281
+ continue;
2282
+ seen.add(key);
2283
+ deltas.push({ id: loc.id, block: inv.block, from: stored, to: derived, invariant: inv.id });
2284
+ }
2285
+ }
2286
+ return deltas;
2287
+ }
2288
+ /** Apply a computed delta set through the standard validated write path. */
2289
+ function applyDerivedStatusDeltas(cwd, config, deltas, ctx) {
2290
+ let applied = 0;
2291
+ for (const delta of deltas) {
2292
+ const arrayKey = config.block_kinds?.find((bk) => bk.canonical_id === delta.block)?.array_key ??
2293
+ (() => {
2294
+ const data = readBlock(cwd, delta.block);
2295
+ const discovered = discoverArrayKey(data);
2296
+ if (discovered === null) {
2297
+ throw new Error(`context-reconcile: no array key discoverable for block '${delta.block}'`);
2298
+ }
2299
+ return discovered;
2300
+ })();
2301
+ updateItemInBlock(cwd, delta.block, arrayKey, (item) => String(item.id) === delta.id, { status: delta.to }, ctx);
2302
+ applied += 1;
2303
+ }
2304
+ return applied;
2305
+ }
2306
+ /**
2307
+ * Converge-on-write hook (FEAT-011 criterion 2 — FGAP-116's last mechanism,
2308
+ * the schema_version template applied to rollup-kind stored status). Invoked
2309
+ * AFTER a sanctioned mutating op's write lands (the op's own lock is already
2310
+ * released — sequential lock acquisition, no nesting): recomputes the
2311
+ * derived-status delta set with the SAME core the reconcile ceremony uses and
2312
+ * stamps every affected rollup item's stored status through the standard
2313
+ * validated write path — a converge-stamp is not authoring; the written value
2314
+ * IS the derivation. Config-driven opt-in: a substrate with no
2315
+ * `derived-status` invariant (or no `state_derivation.rollups`) computes an
2316
+ * empty set and performs no writes, so non-declaring and legacy substrates
2317
+ * are byte-identical to before. BEST-EFFORT by design: it never establishes
2318
+ * identity (a convergence side-effect minting a substrate_id would be a lazy
2319
+ * mint, DEC-0012) and never fails the caller's already-landed write — an
2320
+ * apply failure leaves the divergence for the `derived-status` invariant to
2321
+ * detect and `context-reconcile` (the ceremony with the establishment +
2322
+ * error surface) to repair. Returns the converged set, or null when there was
2323
+ * nothing to converge or the hook could not run.
2324
+ */
2325
+ export function convergeDerivedStatusAfterWrite(cwd, ctx) {
2326
+ try {
2327
+ const config = loadConfig(cwd);
2328
+ if (!config)
2329
+ return null;
2330
+ const deltas = computeDerivedStatusDeltas(cwd, config);
2331
+ if (deltas.length === 0)
2332
+ return null;
2333
+ applyDerivedStatusDeltas(cwd, config, deltas, ctx);
2334
+ return deltas;
2335
+ }
2336
+ catch {
2337
+ // Best-effort: the caller's write already landed; a convergence failure
2338
+ // (pre-identity stamping guard, unreadable sibling block) leaves the
2339
+ // divergence detectable by the derived-status invariant and repairable by
2340
+ // context-reconcile — never a failure of the triggering write.
2341
+ return null;
2342
+ }
2343
+ }
2162
2344
  /**
2163
2345
  * Blocked-resolution commit op (TASK-051 — FGAP-080) — the resolution half of
2164
2346
  * the blocked-resync loop `update` opens. After `update` REFUSES a catalog-ahead