@davidorex/pi-context 0.26.0 → 0.28.1

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.
Files changed (123) hide show
  1. package/CHANGELOG.md +71 -15
  2. package/README.md +71 -18
  3. package/dist/block-api.d.ts +165 -18
  4. package/dist/block-api.d.ts.map +1 -1
  5. package/dist/block-api.js +800 -57
  6. package/dist/block-api.js.map +1 -1
  7. package/dist/citation-rot-scanner.d.ts +80 -0
  8. package/dist/citation-rot-scanner.d.ts.map +1 -0
  9. package/dist/citation-rot-scanner.js +421 -0
  10. package/dist/citation-rot-scanner.js.map +1 -0
  11. package/dist/content-hash.d.ts +25 -0
  12. package/dist/content-hash.d.ts.map +1 -0
  13. package/dist/content-hash.js +62 -0
  14. package/dist/content-hash.js.map +1 -0
  15. package/dist/context-dir.d.ts +126 -1
  16. package/dist/context-dir.d.ts.map +1 -1
  17. package/dist/context-dir.js +208 -4
  18. package/dist/context-dir.js.map +1 -1
  19. package/dist/context-registry.d.ts +122 -0
  20. package/dist/context-registry.d.ts.map +1 -0
  21. package/dist/context-registry.js +189 -0
  22. package/dist/context-registry.js.map +1 -0
  23. package/dist/context-sdk.d.ts +179 -12
  24. package/dist/context-sdk.d.ts.map +1 -1
  25. package/dist/context-sdk.js +536 -101
  26. package/dist/context-sdk.js.map +1 -1
  27. package/dist/context.d.ts +222 -4
  28. package/dist/context.d.ts.map +1 -1
  29. package/dist/context.js +244 -56
  30. package/dist/context.js.map +1 -1
  31. package/dist/git-env.d.ts +2 -0
  32. package/dist/git-env.d.ts.map +1 -0
  33. package/dist/git-env.js +29 -0
  34. package/dist/git-env.js.map +1 -0
  35. package/dist/index.d.ts +124 -2
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +440 -1125
  38. package/dist/index.js.map +1 -1
  39. package/dist/lens-view.d.ts.map +1 -1
  40. package/dist/lens-view.js +5 -3
  41. package/dist/lens-view.js.map +1 -1
  42. package/dist/migration-registry-loader.d.ts +121 -0
  43. package/dist/migration-registry-loader.d.ts.map +1 -0
  44. package/dist/migration-registry-loader.js +309 -0
  45. package/dist/migration-registry-loader.js.map +1 -0
  46. package/dist/migrations-store.d.ts +141 -0
  47. package/dist/migrations-store.d.ts.map +1 -0
  48. package/dist/migrations-store.js +206 -0
  49. package/dist/migrations-store.js.map +1 -0
  50. package/dist/object-store.d.ts +26 -0
  51. package/dist/object-store.d.ts.map +1 -0
  52. package/dist/object-store.js +104 -0
  53. package/dist/object-store.js.map +1 -0
  54. package/dist/ops-registry.d.ts +44 -0
  55. package/dist/ops-registry.d.ts.map +1 -0
  56. package/dist/ops-registry.js +1223 -0
  57. package/dist/ops-registry.js.map +1 -0
  58. package/dist/orientation.d.ts +16 -0
  59. package/dist/orientation.d.ts.map +1 -0
  60. package/dist/orientation.js +49 -0
  61. package/dist/orientation.js.map +1 -0
  62. package/dist/promote-item.d.ts +28 -0
  63. package/dist/promote-item.d.ts.map +1 -0
  64. package/dist/promote-item.js +257 -0
  65. package/dist/promote-item.js.map +1 -0
  66. package/dist/read-element.d.ts +129 -0
  67. package/dist/read-element.d.ts.map +1 -0
  68. package/dist/read-element.js +296 -0
  69. package/dist/read-element.js.map +1 -0
  70. package/dist/rename-canonical-id.d.ts.map +1 -1
  71. package/dist/rename-canonical-id.js +22 -13
  72. package/dist/rename-canonical-id.js.map +1 -1
  73. package/dist/roadmap-plan.d.ts.map +1 -1
  74. package/dist/roadmap-plan.js +23 -13
  75. package/dist/roadmap-plan.js.map +1 -1
  76. package/dist/schema-validator.d.ts +1 -0
  77. package/dist/schema-validator.d.ts.map +1 -1
  78. package/dist/schema-validator.js +7 -3
  79. package/dist/schema-validator.js.map +1 -1
  80. package/dist/schema-write.d.ts +78 -4
  81. package/dist/schema-write.d.ts.map +1 -1
  82. package/dist/schema-write.js +297 -34
  83. package/dist/schema-write.js.map +1 -1
  84. package/dist/status-vocab.d.ts +1 -0
  85. package/dist/status-vocab.d.ts.map +1 -1
  86. package/dist/status-vocab.js +4 -0
  87. package/dist/status-vocab.js.map +1 -1
  88. package/dist/truncate.d.ts +34 -0
  89. package/dist/truncate.d.ts.map +1 -0
  90. package/dist/truncate.js +85 -0
  91. package/dist/truncate.js.map +1 -0
  92. package/dist/write-schema-migration-tool.d.ts +46 -0
  93. package/dist/write-schema-migration-tool.d.ts.map +1 -0
  94. package/dist/write-schema-migration-tool.js +115 -0
  95. package/dist/write-schema-migration-tool.js.map +1 -0
  96. package/package.json +35 -2
  97. package/samples/blocks/work-orders.json +3 -0
  98. package/samples/conception.json +22 -3
  99. package/samples/migrations.json +133 -0
  100. package/samples/schemas/context-contracts.schema.json +19 -4
  101. package/samples/schemas/conventions.schema.json +68 -12
  102. package/samples/schemas/decisions.schema.json +125 -28
  103. package/samples/schemas/features.schema.json +140 -26
  104. package/samples/schemas/framework-gaps.schema.json +171 -26
  105. package/samples/schemas/issues.schema.json +86 -13
  106. package/samples/schemas/layer-plans.schema.json +195 -35
  107. package/samples/schemas/phase.schema.json +18 -3
  108. package/samples/schemas/rationale.schema.json +37 -7
  109. package/samples/schemas/requirements.schema.json +77 -10
  110. package/samples/schemas/research.schema.json +169 -36
  111. package/samples/schemas/spec-reviews.schema.json +88 -18
  112. package/samples/schemas/story.schema.json +18 -3
  113. package/samples/schemas/tasks.schema.json +66 -10
  114. package/samples/schemas/verification.schema.json +70 -12
  115. package/samples/schemas/work-orders.schema.json +195 -0
  116. package/schemas/bootstrap.schema.json +18 -6
  117. package/schemas/config.schema.json +58 -26
  118. package/schemas/context-registry.schema.json +46 -0
  119. package/schemas/migrations.schema.json +123 -0
  120. package/schemas/relations.schema.json +41 -10
  121. package/skill-narrative.md +42 -21
  122. package/skills/pi-context/SKILL.md +159 -65
  123. package/skills/pi-context/references/bundled-resources.md +7 -2
@@ -48,6 +48,27 @@ export declare function resolveContextDir(cwd: string): string;
48
48
  * boundaries under tsx/dist dual-load).
49
49
  */
50
50
  export declare function tryResolveContextDir(cwd: string): string | null;
51
+ /**
52
+ * Optional pointer-history fields stamped onto the bootstrap pointer by
53
+ * `flipBootstrapPointer` (the /context switch family's mutation surface).
54
+ * Pre-fresh-init pointers carry NONE of these; switched pointers carry ALL
55
+ * three. The bootstrap schema declares each as optional so existing v1.0.0
56
+ * pointers remain valid against v1.1.0 — missing optional fields resolve to
57
+ * undefined in-process.
58
+ *
59
+ * `previous_contextDir` is the contextDir value the pointer held IMMEDIATELY
60
+ * BEFORE the most-recent flip; consumed by `/context switch -` to flip back.
61
+ *
62
+ * `switched_at` is the ISO 8601 timestamp of the most-recent flip.
63
+ *
64
+ * `switched_by` is the verified terminal-operator identity stamped by auth-gate
65
+ * on confirm; forensic attribution for the flip.
66
+ */
67
+ export interface BootstrapPointerExtras {
68
+ previous_contextDir?: string;
69
+ switched_at?: string;
70
+ switched_by?: string;
71
+ }
51
72
  /**
52
73
  * Atomically write a `.pi-context.json` bootstrap pointer at `<cwd>/.pi-context.json`.
53
74
  * `contextDir` is a required parameter chosen by the caller per DEC-0015 —
@@ -60,8 +81,48 @@ export declare function tryResolveContextDir(cwd: string): string | null;
60
81
  * `bootstrapCache` entry for this cwd so the next `resolveContextDir(cwd)`
61
82
  * call reads fresh data even if mtime granularity (1s on some filesystems)
62
83
  * would otherwise mask the change.
84
+ *
85
+ * Backwards-compatible signature evolution: the optional `extras` parameter
86
+ * carries the v1.1.0 pointer-history fields. When `extras` is omitted (default,
87
+ * existing call sites) the writer behaves identically to its v1.0.0 form —
88
+ * pointer carries only `{contextDir, version, created_at}` and `version` stays
89
+ * at "1.0.0". When `extras` is provided, the pointer-history fields are
90
+ * merged in and `version` bumps to "1.1.0" so the on-disk pointer self-declares
91
+ * the format it carries. `created_at` is FRESH on every call (this primitive
92
+ * does not preserve created_at across writes — see `flipBootstrapPointer` for
93
+ * the preservation contract).
63
94
  */
64
- export declare function writeBootstrapPointer(cwd: string, contextDir: string): void;
95
+ export declare function writeBootstrapPointer(cwd: string, contextDir: string, extras?: BootstrapPointerExtras): void;
96
+ /**
97
+ * Flip the bootstrap pointer to a new contextDir while preserving the original
98
+ * `created_at` timestamp and stamping pointer-history fields (previous_contextDir,
99
+ * switched_at, switched_by). The mutation surface for `/context switch` family
100
+ * + `context-switch` Pi tool.
101
+ *
102
+ * Behavior:
103
+ * 1. Reads the existing pointer (throws BootstrapNotFoundError when absent —
104
+ * flipping a pointer that does not exist is a programming error; callers
105
+ * bootstrapping a fresh substrate use `writeBootstrapPointer` directly).
106
+ * 2. Constructs the new pointer:
107
+ * - contextDir: `newContextDir` (the flip target)
108
+ * - version: "1.1.0" (pointer-history-bearing)
109
+ * - created_at: PRESERVED from the existing pointer (or stamped fresh when
110
+ * the existing pointer lacks created_at, which only happens for hand-
111
+ * authored pointers that omit the field)
112
+ * - previous_contextDir: the existing pointer's contextDir (so subsequent
113
+ * `/context switch -` can flip back)
114
+ * - switched_at: current ISO 8601 timestamp
115
+ * - switched_by: caller-supplied `writerIdentity` (auth-gate-verified
116
+ * terminal-operator identity at the Pi tool boundary)
117
+ * 3. AJV-validates against the URN-registered bootstrap schema.
118
+ * 4. Atomic tmp + rename write.
119
+ * 5. Invalidates `bootstrapCache` for the cwd.
120
+ *
121
+ * Does NOT validate that `newContextDir` exists / has a config.json — that is
122
+ * the caller's read-side check (slash command handler + Pi tool body each
123
+ * perform target-dir-shape validation appropriate to their mode).
124
+ */
125
+ export declare function flipBootstrapPointer(cwd: string, newContextDir: string, writerIdentity: string): void;
65
126
  /**
66
127
  * Reject substrate names that are not bare path segments (FGAP-079 / DEC-0045).
67
128
  *
@@ -87,7 +148,71 @@ export declare function assertSubstrateName(name: string): void;
87
148
  * hardcoded.
88
149
  */
89
150
  export declare function schemasDir(cwd: string): string;
151
+ /**
152
+ * Dir-targeted form of `schemaPath`: build the schema path against an
153
+ * explicit substrate directory rather than resolving one from `cwd`.
154
+ * `assertSubstrateName` still guards the block name (path-injection guard
155
+ * preserved). Cross-substrate consumers (Cycle F resolver / Cycle H
156
+ * migration) target a non-active substrate by passing its directory here.
157
+ */
158
+ export declare function schemaPathForDir(substrateDir: string, blockName: string): string;
90
159
  export declare function schemaPath(cwd: string, blockName: string): string;
91
160
  export declare function agentsDir(cwd: string): string;
92
161
  export declare function contextTemplatesDir(cwd: string): string;
162
+ /**
163
+ * `<resolveContextDir(cwd)>/migrations.json` — substrate-managed file holding
164
+ * operator-authored schema version migration declarations. Singleton file per
165
+ * cwd (no per-name guard); see `migrations-store.ts` for read / write helpers
166
+ * and `migration-registry-loader.ts` for the loader that converts declarations
167
+ * into a populated MigrationRegistry. Mirrors the relationsPath / configPath
168
+ * shape: pointer-resolved, substrate-dir-relative, no fallback default.
169
+ */
170
+ /**
171
+ * Dir-targeted form of `migrationsPath`: build the `migrations.json` path
172
+ * against an explicit substrate directory rather than resolving one from
173
+ * `cwd`. Used by the ForDir migration-registry loader so a write into a
174
+ * non-active substrate validates/migrates against THAT substrate's
175
+ * declarations.
176
+ */
177
+ export declare function migrationsPathForDir(substrateDir: string): string;
178
+ export declare function migrationsPath(cwd: string): string;
179
+ /**
180
+ * `^sub-[0-9a-f]{16}$` — the substrate_id shape. A substrate_id is the per-
181
+ * substrate root identity that `mintOid` (block-api.ts) salts an item OID with,
182
+ * so two substrates minting an item with the same birth nonce still produce
183
+ * distinct OIDs. Single source of truth for the on-disk `config.substrate_id`
184
+ * regex (mirrored as a literal `pattern` in config.schema.json — the two must
185
+ * not drift).
186
+ */
187
+ export declare const SUBSTRATE_ID_PATTERN: RegExp;
188
+ /**
189
+ * Mint a fresh substrate_id: `"sub-" + sha256Hex(canonicalJson([Date.now(),
190
+ * randomUUID()])).slice(0, 16)`. The `[epoch-ms, uuid]` tuple makes the pre-
191
+ * image collision-free in practice (the uuid alone suffices; the timestamp is
192
+ * a readability/ordering aid in the pre-image only, never surfaced). The
193
+ * 16-hex-char slice keeps the id compact while leaving 64 bits of entropy —
194
+ * far beyond the substrate-count regime. Minted ONCE per substrate (at
195
+ * /context init in Cycle 4; established by hand for the active substrate +
196
+ * packaged samples this cycle) and then immutable on disk; never re-minted on
197
+ * an item write.
198
+ */
199
+ export declare function mintSubstrateId(): string;
200
+ /**
201
+ * Read the `substrate_id` from `<substrateDir>/config.json`. Throws loudly when
202
+ * the config is absent / unreadable / lacks a `substrate_id` — there is NO
203
+ * degraded fallback and NO lazy mint-on-read (locked decision 2): a substrate
204
+ * that participates in identity stamping must carry an explicit substrate_id,
205
+ * established when its identity-declaring schemas were established. The
206
+ * schema-gate on `prepareItemIdentityForWrite` (block-api.ts) and this throw
207
+ * align by construction — stamping only fires for substrates whose schemas
208
+ * declare the identity fields, which are exactly the substrates given a
209
+ * substrate_id — so the throw is a loud guard against a mis-provisioned
210
+ * substrate, not an expected runtime branch.
211
+ */
212
+ export declare function substrateIdForDir(substrateDir: string): string;
213
+ /**
214
+ * `substrateIdForDir(resolveContextDir(cwd))` — the cwd-resolved form for
215
+ * callers holding a working directory rather than an explicit substrate dir.
216
+ */
217
+ export declare function substrateIdFor(cwd: string): string;
93
218
  //# sourceMappingURL=context-dir.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context-dir.d.ts","sourceRoot":"","sources":["../src/context-dir.ts"],"names":[],"mappings":"AA+BA,mFAAmF;AACnF,eAAO,MAAM,WAAW,YAAY,CAAC;AAErC;;;;;;;GAOG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAChD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;gBACnB,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM;CAQ9C;AA6BD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAuCrD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAO/D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CA+B3E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAMtD;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAGjE;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEvD"}
1
+ {"version":3,"file":"context-dir.d.ts","sourceRoot":"","sources":["../src/context-dir.ts"],"names":[],"mappings":"AAiCA,mFAAmF;AACnF,eAAO,MAAM,WAAW,YAAY,CAAC;AAErC;;;;;;;GAOG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAChD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;gBACnB,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM;CAQ9C;AA6BD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAuCrD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAO/D;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,sBAAsB;IACtC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAuC5G;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CA2DrG;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAMtD;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAGhF;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAQjE;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;;GAOG;AACH;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAElD;AAID;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,QAAuB,CAAC;AAEzD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CA8B9D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAElD"}
@@ -25,8 +25,10 @@
25
25
  * workflow-executor.ts still import it as a bare segment); Phase 7 of
26
26
  * FGAP-026 closure cascades those sites and removes the export.
27
27
  */
28
+ import { randomUUID } from "node:crypto";
28
29
  import fs from "node:fs";
29
30
  import path from "node:path";
31
+ import { canonicalJson, sha256Hex } from "./content-hash.js";
30
32
  import { validate } from "./schema-validator.js";
31
33
  /** @deprecated Same status as the removed PROJECT_DIR — Phase 7 cascade target. */
32
34
  export const SCHEMAS_DIR = "schemas";
@@ -42,7 +44,7 @@ export class BootstrapNotFoundError extends Error {
42
44
  cwd;
43
45
  bootstrapPath;
44
46
  constructor(cwd, bootstrapPath) {
45
- super(`pi-context: no .pi-context.json bootstrap pointer at ${bootstrapPath}; run /context init to declare substrate dir per DEC-0015`);
47
+ super(`pi-context: no .pi-context.json bootstrap pointer at ${bootstrapPath}; run /context init <substrate-dir> to declare substrate dir per DEC-0015`);
46
48
  this.name = "BootstrapNotFoundError";
47
49
  this.cwd = cwd;
48
50
  this.bootstrapPath = bootstrapPath;
@@ -149,13 +151,31 @@ export function tryResolveContextDir(cwd) {
149
151
  * `bootstrapCache` entry for this cwd so the next `resolveContextDir(cwd)`
150
152
  * call reads fresh data even if mtime granularity (1s on some filesystems)
151
153
  * would otherwise mask the change.
154
+ *
155
+ * Backwards-compatible signature evolution: the optional `extras` parameter
156
+ * carries the v1.1.0 pointer-history fields. When `extras` is omitted (default,
157
+ * existing call sites) the writer behaves identically to its v1.0.0 form —
158
+ * pointer carries only `{contextDir, version, created_at}` and `version` stays
159
+ * at "1.0.0". When `extras` is provided, the pointer-history fields are
160
+ * merged in and `version` bumps to "1.1.0" so the on-disk pointer self-declares
161
+ * the format it carries. `created_at` is FRESH on every call (this primitive
162
+ * does not preserve created_at across writes — see `flipBootstrapPointer` for
163
+ * the preservation contract).
152
164
  */
153
- export function writeBootstrapPointer(cwd, contextDir) {
165
+ export function writeBootstrapPointer(cwd, contextDir, extras) {
166
+ const hasExtras = extras !== undefined &&
167
+ (extras.previous_contextDir !== undefined || extras.switched_at !== undefined || extras.switched_by !== undefined);
154
168
  const pointer = {
155
169
  contextDir,
156
- version: "1.0.0",
170
+ version: hasExtras ? "1.1.0" : "1.0.0",
157
171
  created_at: new Date().toISOString(),
158
172
  };
173
+ if (extras?.previous_contextDir !== undefined)
174
+ pointer.previous_contextDir = extras.previous_contextDir;
175
+ if (extras?.switched_at !== undefined)
176
+ pointer.switched_at = extras.switched_at;
177
+ if (extras?.switched_by !== undefined)
178
+ pointer.switched_by = extras.switched_by;
159
179
  // Validate before write — AJV via canonical `validate()` against
160
180
  // pre-registered bootstrap schema URN.
161
181
  validate(BOOTSTRAP_REF_SCHEMA, pointer, `bootstrap pointer (writeBootstrapPointer for ${cwd})`);
@@ -180,6 +200,85 @@ export function writeBootstrapPointer(cwd, contextDir) {
180
200
  // fresh pointer regardless of mtime-granularity edge cases.
181
201
  bootstrapCache.delete(path.resolve(cwd));
182
202
  }
203
+ /**
204
+ * Flip the bootstrap pointer to a new contextDir while preserving the original
205
+ * `created_at` timestamp and stamping pointer-history fields (previous_contextDir,
206
+ * switched_at, switched_by). The mutation surface for `/context switch` family
207
+ * + `context-switch` Pi tool.
208
+ *
209
+ * Behavior:
210
+ * 1. Reads the existing pointer (throws BootstrapNotFoundError when absent —
211
+ * flipping a pointer that does not exist is a programming error; callers
212
+ * bootstrapping a fresh substrate use `writeBootstrapPointer` directly).
213
+ * 2. Constructs the new pointer:
214
+ * - contextDir: `newContextDir` (the flip target)
215
+ * - version: "1.1.0" (pointer-history-bearing)
216
+ * - created_at: PRESERVED from the existing pointer (or stamped fresh when
217
+ * the existing pointer lacks created_at, which only happens for hand-
218
+ * authored pointers that omit the field)
219
+ * - previous_contextDir: the existing pointer's contextDir (so subsequent
220
+ * `/context switch -` can flip back)
221
+ * - switched_at: current ISO 8601 timestamp
222
+ * - switched_by: caller-supplied `writerIdentity` (auth-gate-verified
223
+ * terminal-operator identity at the Pi tool boundary)
224
+ * 3. AJV-validates against the URN-registered bootstrap schema.
225
+ * 4. Atomic tmp + rename write.
226
+ * 5. Invalidates `bootstrapCache` for the cwd.
227
+ *
228
+ * Does NOT validate that `newContextDir` exists / has a config.json — that is
229
+ * the caller's read-side check (slash command handler + Pi tool body each
230
+ * perform target-dir-shape validation appropriate to their mode).
231
+ */
232
+ export function flipBootstrapPointer(cwd, newContextDir, writerIdentity) {
233
+ const bootstrapPath = path.join(cwd, ".pi-context.json");
234
+ if (!fs.existsSync(bootstrapPath)) {
235
+ throw new BootstrapNotFoundError(cwd, bootstrapPath);
236
+ }
237
+ let existingRaw;
238
+ try {
239
+ existingRaw = fs.readFileSync(bootstrapPath, "utf-8");
240
+ }
241
+ catch (err) {
242
+ throw new Error(`flipBootstrapPointer: failed to read existing ${bootstrapPath}: ${err instanceof Error ? err.message : String(err)}`);
243
+ }
244
+ let existing;
245
+ try {
246
+ existing = JSON.parse(existingRaw);
247
+ }
248
+ catch (err) {
249
+ throw new Error(`flipBootstrapPointer: invalid JSON in existing ${bootstrapPath}: ${err instanceof Error ? err.message : String(err)}`);
250
+ }
251
+ const previousContextDir = existing.contextDir;
252
+ if (typeof previousContextDir !== "string") {
253
+ throw new Error(`flipBootstrapPointer: existing pointer at ${bootstrapPath} lacks a string contextDir; refuses to flip an unreadable pointer`);
254
+ }
255
+ const preservedCreatedAt = typeof existing.created_at === "string" ? existing.created_at : new Date().toISOString();
256
+ const pointer = {
257
+ contextDir: newContextDir,
258
+ version: "1.1.0",
259
+ created_at: preservedCreatedAt,
260
+ previous_contextDir: previousContextDir,
261
+ switched_at: new Date().toISOString(),
262
+ switched_by: writerIdentity,
263
+ };
264
+ validate(BOOTSTRAP_REF_SCHEMA, pointer, `bootstrap pointer (flipBootstrapPointer for ${cwd})`);
265
+ const tmpPath = `${bootstrapPath}.bootstrap-${process.pid}.tmp`;
266
+ try {
267
+ fs.writeFileSync(tmpPath, JSON.stringify(pointer, null, 2), "utf-8");
268
+ fs.renameSync(tmpPath, bootstrapPath);
269
+ }
270
+ catch (err) {
271
+ try {
272
+ fs.unlinkSync(tmpPath);
273
+ }
274
+ catch {
275
+ /* ignore cleanup failure */
276
+ }
277
+ const msg = err instanceof Error ? err.message : String(err);
278
+ throw new Error(`flipBootstrapPointer: failed to write ${bootstrapPath}: ${msg}`);
279
+ }
280
+ bootstrapCache.delete(path.resolve(cwd));
281
+ }
183
282
  /**
184
283
  * Reject substrate names that are not bare path segments (FGAP-079 / DEC-0045).
185
284
  *
@@ -211,9 +310,25 @@ export function assertSubstrateName(name) {
211
310
  export function schemasDir(cwd) {
212
311
  return path.join(resolveContextDir(cwd), SCHEMAS_DIR);
213
312
  }
313
+ /**
314
+ * Dir-targeted form of `schemaPath`: build the schema path against an
315
+ * explicit substrate directory rather than resolving one from `cwd`.
316
+ * `assertSubstrateName` still guards the block name (path-injection guard
317
+ * preserved). Cross-substrate consumers (Cycle F resolver / Cycle H
318
+ * migration) target a non-active substrate by passing its directory here.
319
+ */
320
+ export function schemaPathForDir(substrateDir, blockName) {
321
+ assertSubstrateName(blockName);
322
+ return path.join(substrateDir, SCHEMAS_DIR, `${blockName}.schema.json`);
323
+ }
214
324
  export function schemaPath(cwd, blockName) {
325
+ // Assert the name BEFORE resolving the substrate dir so the FGAP-079
326
+ // path-traversal guard fires ahead of BootstrapNotFoundError (a traversal
327
+ // name must reject even when no `.pi-context.json` pointer exists). The
328
+ // ForDir body asserts again — harmless double-assert; the boundary guard
329
+ // is the point.
215
330
  assertSubstrateName(blockName);
216
- return path.join(resolveContextDir(cwd), SCHEMAS_DIR, `${blockName}.schema.json`);
331
+ return schemaPathForDir(resolveContextDir(cwd), blockName);
217
332
  }
218
333
  export function agentsDir(cwd) {
219
334
  return path.join(resolveContextDir(cwd), "agents");
@@ -221,4 +336,93 @@ export function agentsDir(cwd) {
221
336
  export function contextTemplatesDir(cwd) {
222
337
  return path.join(resolveContextDir(cwd), "templates");
223
338
  }
339
+ /**
340
+ * `<resolveContextDir(cwd)>/migrations.json` — substrate-managed file holding
341
+ * operator-authored schema version migration declarations. Singleton file per
342
+ * cwd (no per-name guard); see `migrations-store.ts` for read / write helpers
343
+ * and `migration-registry-loader.ts` for the loader that converts declarations
344
+ * into a populated MigrationRegistry. Mirrors the relationsPath / configPath
345
+ * shape: pointer-resolved, substrate-dir-relative, no fallback default.
346
+ */
347
+ /**
348
+ * Dir-targeted form of `migrationsPath`: build the `migrations.json` path
349
+ * against an explicit substrate directory rather than resolving one from
350
+ * `cwd`. Used by the ForDir migration-registry loader so a write into a
351
+ * non-active substrate validates/migrates against THAT substrate's
352
+ * declarations.
353
+ */
354
+ export function migrationsPathForDir(substrateDir) {
355
+ return path.join(substrateDir, "migrations.json");
356
+ }
357
+ export function migrationsPath(cwd) {
358
+ return migrationsPathForDir(resolveContextDir(cwd));
359
+ }
360
+ // ── Substrate identity (content-addressed substrate identity, Cycle 3) ────────
361
+ /**
362
+ * `^sub-[0-9a-f]{16}$` — the substrate_id shape. A substrate_id is the per-
363
+ * substrate root identity that `mintOid` (block-api.ts) salts an item OID with,
364
+ * so two substrates minting an item with the same birth nonce still produce
365
+ * distinct OIDs. Single source of truth for the on-disk `config.substrate_id`
366
+ * regex (mirrored as a literal `pattern` in config.schema.json — the two must
367
+ * not drift).
368
+ */
369
+ export const SUBSTRATE_ID_PATTERN = /^sub-[0-9a-f]{16}$/;
370
+ /**
371
+ * Mint a fresh substrate_id: `"sub-" + sha256Hex(canonicalJson([Date.now(),
372
+ * randomUUID()])).slice(0, 16)`. The `[epoch-ms, uuid]` tuple makes the pre-
373
+ * image collision-free in practice (the uuid alone suffices; the timestamp is
374
+ * a readability/ordering aid in the pre-image only, never surfaced). The
375
+ * 16-hex-char slice keeps the id compact while leaving 64 bits of entropy —
376
+ * far beyond the substrate-count regime. Minted ONCE per substrate (at
377
+ * /context init in Cycle 4; established by hand for the active substrate +
378
+ * packaged samples this cycle) and then immutable on disk; never re-minted on
379
+ * an item write.
380
+ */
381
+ export function mintSubstrateId() {
382
+ return `sub-${sha256Hex(canonicalJson([Date.now(), randomUUID()])).slice(0, 16)}`;
383
+ }
384
+ /**
385
+ * Read the `substrate_id` from `<substrateDir>/config.json`. Throws loudly when
386
+ * the config is absent / unreadable / lacks a `substrate_id` — there is NO
387
+ * degraded fallback and NO lazy mint-on-read (locked decision 2): a substrate
388
+ * that participates in identity stamping must carry an explicit substrate_id,
389
+ * established when its identity-declaring schemas were established. The
390
+ * schema-gate on `prepareItemIdentityForWrite` (block-api.ts) and this throw
391
+ * align by construction — stamping only fires for substrates whose schemas
392
+ * declare the identity fields, which are exactly the substrates given a
393
+ * substrate_id — so the throw is a loud guard against a mis-provisioned
394
+ * substrate, not an expected runtime branch.
395
+ */
396
+ export function substrateIdForDir(substrateDir) {
397
+ const configPath = path.join(substrateDir, "config.json");
398
+ if (!fs.existsSync(configPath)) {
399
+ throw new Error(`substrateIdForDir: no config.json at ${configPath}; a substrate that stamps identity must carry an explicit substrate_id (no lazy mint on write)`);
400
+ }
401
+ let raw;
402
+ try {
403
+ raw = fs.readFileSync(configPath, "utf-8");
404
+ }
405
+ catch (err) {
406
+ throw new Error(`substrateIdForDir: failed to read ${configPath}: ${err instanceof Error ? err.message : String(err)}`);
407
+ }
408
+ let data;
409
+ try {
410
+ data = JSON.parse(raw);
411
+ }
412
+ catch (err) {
413
+ throw new Error(`substrateIdForDir: invalid JSON in ${configPath}: ${err instanceof Error ? err.message : String(err)}`);
414
+ }
415
+ const substrateId = data && typeof data === "object" ? data.substrate_id : undefined;
416
+ if (typeof substrateId !== "string" || !SUBSTRATE_ID_PATTERN.test(substrateId)) {
417
+ throw new Error(`substrateIdForDir: config.json at ${configPath} has no valid substrate_id (expected ^sub-[0-9a-f]{16}$, got ${JSON.stringify(substrateId)}); establish one before stamping identity`);
418
+ }
419
+ return substrateId;
420
+ }
421
+ /**
422
+ * `substrateIdForDir(resolveContextDir(cwd))` — the cwd-resolved form for
423
+ * callers holding a working directory rather than an explicit substrate dir.
424
+ */
425
+ export function substrateIdFor(cwd) {
426
+ return substrateIdForDir(resolveContextDir(cwd));
427
+ }
224
428
  //# sourceMappingURL=context-dir.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"context-dir.js","sourceRoot":"","sources":["../src/context-dir.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context-dir.js","sourceRoot":"","sources":["../src/context-dir.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * context-registry — project-root substrate registry read / write surface for
3
+ * `<cwd>/.pi-context-registry.json`.
4
+ *
5
+ * The registry is a PROJECT-ROOT file (tracked in git, like `.pi-context.json`),
6
+ * NOT substrate-relative: it enumerates EVERY known substrate by its immutable
7
+ * content-addressed `substrate_id` (`^sub-[0-9a-f]{16}$`), mapping each to its
8
+ * on-disk directory + alias list. This is the substrate-locator layer the
9
+ * Cycle-8 F2 resolver consumes to resolve a foreign `<substrate_id>:<oid>` /
10
+ * `<alias>:<refname>` locator to a directory, and the surface the Phase-H
11
+ * migration registers each legacy substrate into.
12
+ *
13
+ * Distinct from the `.pi-context.json` bootstrap pointer: the pointer names the
14
+ * single ACTIVE substrate dir; this registry enumerates all of them. The
15
+ * SoT-drift invariant in `validateContext` (context-sdk.ts) requires the active
16
+ * `config.substrate_id` to have an entry here whose `dir` resolves to the active
17
+ * substrate.
18
+ *
19
+ * Mirrors `migrations-store.ts` atomic discipline one-for-one:
20
+ * - `loadRegistry` reads + JSON-parses + AJV-validates via `validateFromFile`
21
+ * against the bundled `context-registry.schema.json`; returns null when the
22
+ * file is absent (a pre-write project with no registry is a normal state,
23
+ * NOT an error).
24
+ * - `writeRegistry` delegates whole-file writes to block-api's atomic
25
+ * `writeTypedFile` (tmp + rename + schema-validate), so a failed write
26
+ * leaves the prior file byte-identical and a malformed registry never lands.
27
+ * - `registerSubstrate` wraps a load-or-empty → JSON deep-clone → upsert →
28
+ * write pattern (idempotent: re-registering the same substrate_id with the
29
+ * same dir is a no-op rewrite; a changed dir/aliases overwrites the entry).
30
+ *
31
+ * A small per-cwd cache (keyed by absolute cwd, invalidated on mtime change and
32
+ * proactively on write) mirrors the migrations-store cache so read-after-write
33
+ * within a process is consistent without restart.
34
+ */
35
+ import type { DispatchContext } from "./dispatch-context.js";
36
+ /**
37
+ * Project-root path of the substrate registry. PROJECT-ROOT, not substrate-dir-
38
+ * relative (contrast `migrationsPath`, which resolves through the active
39
+ * substrate dir). The registry enumerates substrates above any single
40
+ * substrate, so it must live at a fixed root location independent of which
41
+ * substrate the bootstrap pointer currently names.
42
+ */
43
+ export declare function contextRegistryPath(cwd: string): string;
44
+ /**
45
+ * One registry entry — the directory + alias list for a substrate_id. Mirrors
46
+ * the `RegistryEntry` definition in context-registry.schema.json one-for-one.
47
+ * `dir` is resolved against the project root (`path.resolve(cwd, dir)`) when
48
+ * matched against the active substrate by the drift invariant.
49
+ */
50
+ export interface RegistryEntry {
51
+ dir: string;
52
+ aliases: string[];
53
+ }
54
+ /**
55
+ * On-disk registry shape. `substrates` is keyed by substrate_id
56
+ * (`^sub-[0-9a-f]{16}$`, enforced by the schema's `propertyNames`).
57
+ */
58
+ export interface RegistryFile {
59
+ version: string;
60
+ substrates: Record<string, RegistryEntry>;
61
+ }
62
+ /**
63
+ * Current `version` emitted into newly-created `.pi-context-registry.json`
64
+ * files. Tracks the `version` field of context-registry.schema.json itself.
65
+ */
66
+ export declare const REGISTRY_FILE_VERSION = "1.0.0";
67
+ /**
68
+ * Drop the cached registry for `cwd` so the next `loadRegistry(cwd)` re-reads
69
+ * from disk. Called internally by `writeRegistry`; exported for callers that
70
+ * mutate the file out-of-band (e.g. tests / the orchestrator seed).
71
+ */
72
+ export declare function invalidateRegistry(cwd: string): void;
73
+ /**
74
+ * Load + AJV-validate the project-root registry. Returns null when the file is
75
+ * absent (a project with no registry yet — a normal pre-write condition, NOT an
76
+ * error). Throws on read / parse / schema failure. Caches by absolute cwd keyed
77
+ * on file mtime.
78
+ */
79
+ export declare function loadRegistry(cwd: string): RegistryFile | null;
80
+ /**
81
+ * Atomic, AJV-validated whole-file write of `.pi-context-registry.json`.
82
+ * Delegates to block-api's `writeTypedFile` against the bundled registry schema
83
+ * (tmp + rename; a failed write leaves the prior file byte-identical). `ctx` is
84
+ * accepted for call-site parity with the rest of the substrate write surface;
85
+ * the registry schema declares no envelope author fields so stamping is a
86
+ * structural no-op today. Invalidates the per-cwd cache after the write so the
87
+ * next `loadRegistry(cwd)` reads the fresh file.
88
+ */
89
+ export declare function writeRegistry(cwd: string, file: RegistryFile, ctx?: DispatchContext): void;
90
+ /**
91
+ * Upsert a substrate's registry entry. Load-or-empty → clone → set
92
+ * `substrates[substrate_id] = { dir, aliases }` → atomic write. Idempotent:
93
+ * re-registering the same substrate_id with the same dir + aliases produces a
94
+ * byte-identical file; a changed dir (e.g. a renamed substrate directory) or a
95
+ * changed alias list overwrites the prior entry in place. `aliases` defaults to
96
+ * `[]` when omitted (Cycle 4 registers with empty aliases; the Phase-H
97
+ * migration populates the legacy `project:` alias).
98
+ *
99
+ * Does NOT validate that `substrate_id` matches `^sub-[0-9a-f]{16}$` here — the
100
+ * schema's `propertyNames` pattern enforces that at the write boundary (an
101
+ * out-of-shape key fails `writeTypedFile`'s AJV validation, leaving the prior
102
+ * file intact).
103
+ */
104
+ export declare function registerSubstrate(cwd: string, substrate_id: string, dir: string, aliases?: string[], ctx?: DispatchContext): void;
105
+ /**
106
+ * Resolve a substrate_id to its registered directory string (as stored — i.e.
107
+ * project-root-relative, the caller resolves against cwd when an absolute path
108
+ * is needed). Returns null on miss (substrate_id not registered, or no registry
109
+ * file at all) — never throws on a clean miss, mirroring the F2 resolver's
110
+ * expectation of a null-or-hit lookup.
111
+ */
112
+ export declare function resolveSubstrateDir(cwd: string, substrate_id: string): string | null;
113
+ /**
114
+ * Resolve an alias to the substrate_id that declares it. Scans every entry's
115
+ * `aliases[]` for an exact string match and returns the owning substrate_id.
116
+ * Returns null on miss (alias unregistered, or no registry file) — never throws
117
+ * on a clean miss. First-match wins if (by misconfiguration) two substrates
118
+ * claim the same alias; the registry does not enforce alias uniqueness this
119
+ * cycle.
120
+ */
121
+ export declare function resolveAlias(cwd: string, alias: string): string | null;
122
+ //# sourceMappingURL=context-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-registry.d.ts","sourceRoot":"","sources":["../src/context-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAMH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAa7D;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CAC1C;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,UAAU,CAAC;AAgB7C;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEpD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CA2B7D;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,CAAC,EAAE,eAAe,GAAG,IAAI,CAG1F;AAoBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAChC,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EACpB,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,MAAM,EAAO,EACtB,GAAG,CAAC,EAAE,eAAe,GACnB,IAAI,CAKN;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKpF;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOtE"}