@davidorex/pi-context 0.26.0 → 0.28.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/CHANGELOG.md +69 -15
- package/README.md +71 -18
- package/dist/block-api.d.ts +165 -18
- package/dist/block-api.d.ts.map +1 -1
- package/dist/block-api.js +800 -57
- package/dist/block-api.js.map +1 -1
- package/dist/citation-rot-scanner.d.ts +80 -0
- package/dist/citation-rot-scanner.d.ts.map +1 -0
- package/dist/citation-rot-scanner.js +421 -0
- package/dist/citation-rot-scanner.js.map +1 -0
- package/dist/content-hash.d.ts +25 -0
- package/dist/content-hash.d.ts.map +1 -0
- package/dist/content-hash.js +62 -0
- package/dist/content-hash.js.map +1 -0
- package/dist/context-dir.d.ts +126 -1
- package/dist/context-dir.d.ts.map +1 -1
- package/dist/context-dir.js +208 -4
- package/dist/context-dir.js.map +1 -1
- package/dist/context-registry.d.ts +122 -0
- package/dist/context-registry.d.ts.map +1 -0
- package/dist/context-registry.js +189 -0
- package/dist/context-registry.js.map +1 -0
- package/dist/context-sdk.d.ts +179 -12
- package/dist/context-sdk.d.ts.map +1 -1
- package/dist/context-sdk.js +536 -101
- package/dist/context-sdk.js.map +1 -1
- package/dist/context.d.ts +222 -4
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +244 -56
- package/dist/context.js.map +1 -1
- package/dist/git-env.d.ts +2 -0
- package/dist/git-env.d.ts.map +1 -0
- package/dist/git-env.js +29 -0
- package/dist/git-env.js.map +1 -0
- package/dist/index.d.ts +124 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +440 -1125
- package/dist/index.js.map +1 -1
- package/dist/lens-view.d.ts.map +1 -1
- package/dist/lens-view.js +5 -3
- package/dist/lens-view.js.map +1 -1
- package/dist/migration-registry-loader.d.ts +121 -0
- package/dist/migration-registry-loader.d.ts.map +1 -0
- package/dist/migration-registry-loader.js +309 -0
- package/dist/migration-registry-loader.js.map +1 -0
- package/dist/migrations-store.d.ts +141 -0
- package/dist/migrations-store.d.ts.map +1 -0
- package/dist/migrations-store.js +206 -0
- package/dist/migrations-store.js.map +1 -0
- package/dist/object-store.d.ts +26 -0
- package/dist/object-store.d.ts.map +1 -0
- package/dist/object-store.js +104 -0
- package/dist/object-store.js.map +1 -0
- package/dist/ops-registry.d.ts +44 -0
- package/dist/ops-registry.d.ts.map +1 -0
- package/dist/ops-registry.js +1223 -0
- package/dist/ops-registry.js.map +1 -0
- package/dist/orientation.d.ts +16 -0
- package/dist/orientation.d.ts.map +1 -0
- package/dist/orientation.js +49 -0
- package/dist/orientation.js.map +1 -0
- package/dist/promote-item.d.ts +28 -0
- package/dist/promote-item.d.ts.map +1 -0
- package/dist/promote-item.js +257 -0
- package/dist/promote-item.js.map +1 -0
- package/dist/read-element.d.ts +129 -0
- package/dist/read-element.d.ts.map +1 -0
- package/dist/read-element.js +296 -0
- package/dist/read-element.js.map +1 -0
- package/dist/rename-canonical-id.d.ts.map +1 -1
- package/dist/rename-canonical-id.js +22 -13
- package/dist/rename-canonical-id.js.map +1 -1
- package/dist/roadmap-plan.d.ts.map +1 -1
- package/dist/roadmap-plan.js +23 -13
- package/dist/roadmap-plan.js.map +1 -1
- package/dist/schema-validator.d.ts +1 -0
- package/dist/schema-validator.d.ts.map +1 -1
- package/dist/schema-validator.js +7 -3
- package/dist/schema-validator.js.map +1 -1
- package/dist/schema-write.d.ts +78 -4
- package/dist/schema-write.d.ts.map +1 -1
- package/dist/schema-write.js +297 -34
- package/dist/schema-write.js.map +1 -1
- package/dist/status-vocab.d.ts +1 -0
- package/dist/status-vocab.d.ts.map +1 -1
- package/dist/status-vocab.js +4 -0
- package/dist/status-vocab.js.map +1 -1
- package/dist/truncate.d.ts +34 -0
- package/dist/truncate.d.ts.map +1 -0
- package/dist/truncate.js +85 -0
- package/dist/truncate.js.map +1 -0
- package/dist/write-schema-migration-tool.d.ts +46 -0
- package/dist/write-schema-migration-tool.d.ts.map +1 -0
- package/dist/write-schema-migration-tool.js +115 -0
- package/dist/write-schema-migration-tool.js.map +1 -0
- package/package.json +35 -2
- package/samples/blocks/work-orders.json +3 -0
- package/samples/conception.json +22 -3
- package/samples/migrations.json +133 -0
- package/samples/schemas/context-contracts.schema.json +19 -4
- package/samples/schemas/conventions.schema.json +68 -12
- package/samples/schemas/decisions.schema.json +125 -28
- package/samples/schemas/features.schema.json +140 -26
- package/samples/schemas/framework-gaps.schema.json +171 -26
- package/samples/schemas/issues.schema.json +86 -13
- package/samples/schemas/layer-plans.schema.json +195 -35
- package/samples/schemas/phase.schema.json +18 -3
- package/samples/schemas/rationale.schema.json +37 -7
- package/samples/schemas/requirements.schema.json +77 -10
- package/samples/schemas/research.schema.json +169 -36
- package/samples/schemas/spec-reviews.schema.json +88 -18
- package/samples/schemas/story.schema.json +18 -3
- package/samples/schemas/tasks.schema.json +66 -10
- package/samples/schemas/verification.schema.json +70 -12
- package/samples/schemas/work-orders.schema.json +195 -0
- package/schemas/bootstrap.schema.json +18 -6
- package/schemas/config.schema.json +58 -26
- package/schemas/context-registry.schema.json +46 -0
- package/schemas/migrations.schema.json +123 -0
- package/schemas/relations.schema.json +41 -10
- package/skill-narrative.md +42 -21
- package/skills/pi-context/SKILL.md +159 -65
- package/skills/pi-context/references/bundled-resources.md +7 -2
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* migrations-store — substrate-managed read / write surface for
|
|
3
|
+
* `<resolveContextDir(cwd)>/migrations.json`.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors the config / relations precedent in context.ts: load + AJV-validate
|
|
6
|
+
* via `validateFromFile` against the bundled migrations.schema.json; whole-file
|
|
7
|
+
* writes delegate to block-api's atomic `writeTypedFile` (tmp + rename) so a
|
|
8
|
+
* failed write leaves the prior file byte-identical.
|
|
9
|
+
*
|
|
10
|
+
* Three op-correct mutation helpers — append / replace / remove — wrap a
|
|
11
|
+
* load → JSON deep-clone → mutate → write pattern. Identity of a MigrationDecl
|
|
12
|
+
* is the (schemaName, fromVersion) pair, mirroring the registry's
|
|
13
|
+
* one-outgoing-edge-per-(schemaName, fromVersion) discipline from
|
|
14
|
+
* `schema-migrations.ts`:
|
|
15
|
+
* - appendMigrationDecl requires the (schemaName, fromVersion) pair to be
|
|
16
|
+
* ABSENT; collision throws with a descriptive message so an unintended
|
|
17
|
+
* double-declaration surfaces at the write site rather than as silent
|
|
18
|
+
* registry duplicate-registration at load time.
|
|
19
|
+
* - replaceMigrationDecl requires the pair to be PRESENT; a missing target
|
|
20
|
+
* throws (use append to introduce a new declaration).
|
|
21
|
+
* - removeMigrationDecl requires the pair to be PRESENT; a missing target
|
|
22
|
+
* throws.
|
|
23
|
+
*
|
|
24
|
+
* After each successful mutation the helper invokes
|
|
25
|
+
* `invalidateMigrationRegistry(cwd)` (migration-registry-loader.ts) so the
|
|
26
|
+
* next `getProjectMigrationRegistry(cwd)` consumer reads the fresh
|
|
27
|
+
* declarations without process restart. The store↔loader edge is mutually
|
|
28
|
+
* cyclic (loader reads from store; store writes invalidate loader cache);
|
|
29
|
+
* ESM tolerates the cycle because both imports are function-level uses, not
|
|
30
|
+
* top-level evaluations.
|
|
31
|
+
*
|
|
32
|
+
* MigrationDecl + TransformSpec + TransformOp types mirror the on-disk schema
|
|
33
|
+
* shape one-for-one. They live here (rather than schema-migrations.ts) because
|
|
34
|
+
* schema-migrations.ts is the in-memory registry abstraction (knows nothing of
|
|
35
|
+
* persistence); the persisted-shape vocabulary belongs at the substrate-store
|
|
36
|
+
* boundary.
|
|
37
|
+
*/
|
|
38
|
+
import fs from "node:fs";
|
|
39
|
+
import path from "node:path";
|
|
40
|
+
import { fileURLToPath } from "node:url";
|
|
41
|
+
import { writeTypedFile } from "./block-api.js";
|
|
42
|
+
import { migrationsPath, migrationsPathForDir, resolveContextDir } from "./context-dir.js";
|
|
43
|
+
import { invalidateMigrationRegistry, invalidateMigrationRegistryForDir } from "./migration-registry-loader.js";
|
|
44
|
+
import { validateFromFile } from "./schema-validator.js";
|
|
45
|
+
/**
|
|
46
|
+
* Resolve the bundled migrations schema file. Mirrors the private
|
|
47
|
+
* `bundledSchemaPath` helper in context.ts — schemas live one directory up
|
|
48
|
+
* from both `src/` (under tsx --test) and `dist/` (after tsc).
|
|
49
|
+
*/
|
|
50
|
+
function bundledMigrationsSchemaPath() {
|
|
51
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
52
|
+
return path.resolve(here, "..", "schemas", "migrations.schema.json");
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Current schema_version emitted into newly-created migrations.json files.
|
|
56
|
+
* Tracks the `version` field of migrations.schema.json itself.
|
|
57
|
+
*/
|
|
58
|
+
export const MIGRATIONS_FILE_VERSION = "1.0.0";
|
|
59
|
+
/**
|
|
60
|
+
* Load + AJV-validate migrations.json. Returns null when the file is absent
|
|
61
|
+
* (pre-write state is a normal condition, NOT an error — empty/missing yields
|
|
62
|
+
* an empty registry in the loader). Throws on read / parse / schema failure.
|
|
63
|
+
*/
|
|
64
|
+
export function loadMigrationsFileForDir(substrateDir) {
|
|
65
|
+
const p = migrationsPathForDir(substrateDir);
|
|
66
|
+
if (!fs.existsSync(p))
|
|
67
|
+
return null;
|
|
68
|
+
let raw;
|
|
69
|
+
try {
|
|
70
|
+
raw = fs.readFileSync(p, "utf-8");
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
throw new Error(`loadMigrationsFile: failed to read ${p}: ${err instanceof Error ? err.message : String(err)}`);
|
|
74
|
+
}
|
|
75
|
+
let data;
|
|
76
|
+
try {
|
|
77
|
+
data = JSON.parse(raw);
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
throw new Error(`loadMigrationsFile: invalid JSON in ${p}: ${err instanceof Error ? err.message : String(err)}`);
|
|
81
|
+
}
|
|
82
|
+
validateFromFile(bundledMigrationsSchemaPath(), data, `migrations.json (${p})`);
|
|
83
|
+
return data;
|
|
84
|
+
}
|
|
85
|
+
export function loadMigrationsFile(cwd) {
|
|
86
|
+
return loadMigrationsFileForDir(resolveContextDir(cwd));
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Atomic, AJV-validated whole-file write of migrations.json. Delegates to
|
|
90
|
+
* block-api's writeTypedFile against the bundled migrations schema. `ctx` is
|
|
91
|
+
* accepted for call-site parity with the rest of the substrate write surface;
|
|
92
|
+
* the migrations schema declares no envelope author fields so stamping is a
|
|
93
|
+
* structural no-op today (the loader-cache invalidation upstream of this call
|
|
94
|
+
* is the side-effect that matters for read-after-write parity).
|
|
95
|
+
*/
|
|
96
|
+
export function writeMigrationsFile(cwd, file, ctx) {
|
|
97
|
+
writeMigrationsFileForDir(resolveContextDir(cwd), file, ctx);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Dir-targeted twin of {@link writeMigrationsFile} (Cycle-1 `*ForDir` pattern).
|
|
101
|
+
* Atomic, AJV-validated whole-file write of `<substrateDir>/migrations.json`
|
|
102
|
+
* against the bundled migrations schema — takes the ALREADY-RESOLVED substrate
|
|
103
|
+
* dir directly (no `.pi-context.json` pointer resolution). The cwd form is a
|
|
104
|
+
* thin wrapper resolving the active dir; behaviour is byte-identical when called
|
|
105
|
+
* via cwd. Same attestation-parity no-op semantics as the cwd form (the
|
|
106
|
+
* migrations schema declares no envelope author fields). Does NOT invalidate any
|
|
107
|
+
* loader cache — the cache-invalidation side-effect lives on the
|
|
108
|
+
* appendMigrationDecl mutation helpers, not the raw whole-file write.
|
|
109
|
+
*/
|
|
110
|
+
export function writeMigrationsFileForDir(substrateDir, file, ctx) {
|
|
111
|
+
writeTypedFile(migrationsPathForDir(substrateDir), bundledMigrationsSchemaPath(), file, ctx, "migrations.json");
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Compose an initial empty migrations file shape — used by the append helper
|
|
115
|
+
* when the on-disk file is absent. Centralised so the `schema_version` token
|
|
116
|
+
* is sourced from one place.
|
|
117
|
+
*/
|
|
118
|
+
function emptyMigrationsFile() {
|
|
119
|
+
return { schema_version: MIGRATIONS_FILE_VERSION, migrations: [] };
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Deep-clone via JSON round-trip. Sufficient for MigrationDecl shapes (no
|
|
123
|
+
* Date / Map / undefined values per the schema). Matches the amend-config
|
|
124
|
+
* load-clone-mutate-write precedent.
|
|
125
|
+
*/
|
|
126
|
+
function clone(value) {
|
|
127
|
+
return JSON.parse(JSON.stringify(value));
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Locate the index of a (schemaName, fromVersion) MigrationDecl within the
|
|
131
|
+
* file's `migrations[]` array; returns -1 when absent. Centralised so the
|
|
132
|
+
* three op-correct helpers cannot drift on identity-matching semantics.
|
|
133
|
+
*/
|
|
134
|
+
function findMigrationIndex(file, schemaName, fromVersion) {
|
|
135
|
+
return file.migrations.findIndex((m) => m.schemaName === schemaName && m.fromVersion === fromVersion);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Append a new MigrationDecl to the substrate. Op-correctness: the
|
|
139
|
+
* (schemaName, fromVersion) pair must be ABSENT on-disk; collision throws.
|
|
140
|
+
* Invalidates the loader cache for `cwd` after a successful write so the
|
|
141
|
+
* next registry consumer reads the fresh declaration.
|
|
142
|
+
*/
|
|
143
|
+
export function appendMigrationDecl(cwd, decl, ctx) {
|
|
144
|
+
appendMigrationDeclForDir(resolveContextDir(cwd), decl, ctx);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Dir-targeted twin of {@link appendMigrationDecl} (Cycle-1 `*ForDir` pattern).
|
|
148
|
+
* Append a new MigrationDecl to the substrate at `substrateDir`. Op-correctness:
|
|
149
|
+
* the (schemaName, fromVersion) pair must be ABSENT on-disk; collision throws.
|
|
150
|
+
* Invalidates the loader cache for `substrateDir` after a successful write so
|
|
151
|
+
* the next registry consumer reads the fresh declaration. The cwd form is a thin
|
|
152
|
+
* wrapper resolving the active dir; behaviour is byte-identical when called via
|
|
153
|
+
* cwd (resolveContextDir(cwd) → invalidateMigrationRegistry(cwd) routes through
|
|
154
|
+
* invalidateMigrationRegistryForDir on the same dir).
|
|
155
|
+
*/
|
|
156
|
+
export function appendMigrationDeclForDir(substrateDir, decl, ctx) {
|
|
157
|
+
const current = loadMigrationsFileForDir(substrateDir) ?? emptyMigrationsFile();
|
|
158
|
+
const idx = findMigrationIndex(current, decl.schemaName, decl.fromVersion);
|
|
159
|
+
if (idx >= 0) {
|
|
160
|
+
throw new Error(`appendMigrationDecl: collision — migration for schema '${decl.schemaName}' fromVersion '${decl.fromVersion}' already exists; use replaceMigrationDecl to overwrite`);
|
|
161
|
+
}
|
|
162
|
+
const next = clone(current);
|
|
163
|
+
next.migrations.push(decl);
|
|
164
|
+
writeMigrationsFileForDir(substrateDir, next, ctx);
|
|
165
|
+
invalidateMigrationRegistryForDir(substrateDir);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Replace an existing MigrationDecl identified by (schemaName, fromVersion).
|
|
169
|
+
* Op-correctness: target must be PRESENT; missing target throws. The whole
|
|
170
|
+
* decl is replaced (no per-field merge). Invalidates the loader cache after a
|
|
171
|
+
* successful write.
|
|
172
|
+
*/
|
|
173
|
+
export function replaceMigrationDecl(cwd, decl, ctx) {
|
|
174
|
+
const current = loadMigrationsFile(cwd);
|
|
175
|
+
if (current === null) {
|
|
176
|
+
throw new Error(`replaceMigrationDecl: migrations.json absent at ${migrationsPath(cwd)}; use appendMigrationDecl to create`);
|
|
177
|
+
}
|
|
178
|
+
const idx = findMigrationIndex(current, decl.schemaName, decl.fromVersion);
|
|
179
|
+
if (idx < 0) {
|
|
180
|
+
throw new Error(`replaceMigrationDecl: target missing — no migration declared for schema '${decl.schemaName}' fromVersion '${decl.fromVersion}'; use appendMigrationDecl to introduce`);
|
|
181
|
+
}
|
|
182
|
+
const next = clone(current);
|
|
183
|
+
next.migrations[idx] = decl;
|
|
184
|
+
writeMigrationsFile(cwd, next, ctx);
|
|
185
|
+
invalidateMigrationRegistry(cwd);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Remove an existing MigrationDecl identified by (schemaName, fromVersion).
|
|
189
|
+
* Op-correctness: target must be PRESENT; missing target throws. Invalidates
|
|
190
|
+
* the loader cache after a successful write.
|
|
191
|
+
*/
|
|
192
|
+
export function removeMigrationDecl(cwd, schemaName, fromVersion, ctx) {
|
|
193
|
+
const current = loadMigrationsFile(cwd);
|
|
194
|
+
if (current === null) {
|
|
195
|
+
throw new Error(`removeMigrationDecl: migrations.json absent at ${migrationsPath(cwd)}; nothing to remove`);
|
|
196
|
+
}
|
|
197
|
+
const idx = findMigrationIndex(current, schemaName, fromVersion);
|
|
198
|
+
if (idx < 0) {
|
|
199
|
+
throw new Error(`removeMigrationDecl: target missing — no migration declared for schema '${schemaName}' fromVersion '${fromVersion}'`);
|
|
200
|
+
}
|
|
201
|
+
const next = clone(current);
|
|
202
|
+
next.migrations.splice(idx, 1);
|
|
203
|
+
writeMigrationsFile(cwd, next, ctx);
|
|
204
|
+
invalidateMigrationRegistry(cwd);
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=migrations-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrations-store.js","sourceRoot":"","sources":["../src/migrations-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True when an object with `contentHash` already exists in the store.
|
|
3
|
+
* Asserts hash shape first (a malformed hash can never be present, but the
|
|
4
|
+
* guard keeps the surface uniform and rejects path-escape attempts at the
|
|
5
|
+
* boundary).
|
|
6
|
+
*/
|
|
7
|
+
export declare function hasObject(substrateDir: string, contentHash: string): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Write `content` under `contentHash` if not already present.
|
|
10
|
+
*
|
|
11
|
+
* Idempotent: returns early when `hasObject` is true (content-addressed — the
|
|
12
|
+
* same hash implies the same bytes, so a re-put would rewrite identical
|
|
13
|
+
* content). On a fresh write, creates `<substrateDir>/objects/` if needed and
|
|
14
|
+
* writes `JSON.stringify(content, null, 2)` via atomic tmp+rename.
|
|
15
|
+
*
|
|
16
|
+
* `content` is expected to be the canonical content projection the caller
|
|
17
|
+
* hashed to obtain `contentHash`; this module does not re-derive or verify the
|
|
18
|
+
* hash (no dependency on content-hash.ts).
|
|
19
|
+
*/
|
|
20
|
+
export declare function putObject(substrateDir: string, contentHash: string, content: Record<string, unknown>): void;
|
|
21
|
+
/**
|
|
22
|
+
* Parsed content stored under `contentHash`, or `null` when no such object
|
|
23
|
+
* exists. Asserts hash shape first.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getObject(substrateDir: string, contentHash: string): Record<string, unknown> | null;
|
|
26
|
+
//# sourceMappingURL=object-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"object-store.d.ts","sourceRoot":"","sources":["../src/object-store.ts"],"names":[],"mappings":"AAoDA;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAG5E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAqB3G;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAOnG"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content-addressed object store (Cycle 2, Phase B). A durable, append-only
|
|
3
|
+
* store keyed by a content hash: each distinct content projection is written
|
|
4
|
+
* once to `<substrateDir>/objects/<contentHash>.json` holding its JSON. This is
|
|
5
|
+
* the durable Merkle store that makes the OID/refname split actually
|
|
6
|
+
* content-addressed and gives later cycles real pinning + integrity.
|
|
7
|
+
*
|
|
8
|
+
* Dir-explicit (no pointer resolution), so it is independently testable and
|
|
9
|
+
* usable across substrate dirs. It takes a `contentHash` parameter rather than
|
|
10
|
+
* computing one — the caller supplies the hash from `computeContentHash` — so
|
|
11
|
+
* this module has ZERO dependency on `content-hash.ts`.
|
|
12
|
+
*
|
|
13
|
+
* No file lock: a write is keyed by its own content hash, so two writers of the
|
|
14
|
+
* same content produce byte-identical files at the same path (collision-free,
|
|
15
|
+
* idempotent). Atomic tmp+rename guards against a torn read of a partial file.
|
|
16
|
+
*
|
|
17
|
+
* `objects/` is tracked in git (it is the integrity store; gitignoring it would
|
|
18
|
+
* lose pinning). No `.gitignore` change accompanies this module.
|
|
19
|
+
*
|
|
20
|
+
* Dormant this cycle: nothing in any write path calls `putObject` yet (Cycle 3
|
|
21
|
+
* wiring / Cycle 10 backfill). Infrastructure module — not re-exported from
|
|
22
|
+
* `index.ts`.
|
|
23
|
+
*/
|
|
24
|
+
import fs from "node:fs";
|
|
25
|
+
import path from "node:path";
|
|
26
|
+
/** Lowercase 64-char hex (a SHA-256 digest). */
|
|
27
|
+
const CONTENT_HASH_PATTERN = /^[0-9a-f]{64}$/;
|
|
28
|
+
/**
|
|
29
|
+
* Guard the hash before it becomes a path segment. A content hash is a fixed
|
|
30
|
+
* lowercase-hex SHA-256 digest; anything else (wrong length, uppercase, path
|
|
31
|
+
* separators, `..`) is rejected so a malformed value cannot escape the
|
|
32
|
+
* `objects/` directory or name a non-canonical file. Analogous to
|
|
33
|
+
* `assertSubstrateName` for block names.
|
|
34
|
+
*/
|
|
35
|
+
function assertContentHash(contentHash) {
|
|
36
|
+
if (!CONTENT_HASH_PATTERN.test(contentHash)) {
|
|
37
|
+
throw new Error(`object-store: invalid contentHash ${JSON.stringify(contentHash)} — expected lowercase 64-char hex (SHA-256)`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function objectsDirFor(substrateDir) {
|
|
41
|
+
return path.join(substrateDir, "objects");
|
|
42
|
+
}
|
|
43
|
+
function objectPathFor(substrateDir, contentHash) {
|
|
44
|
+
return path.join(objectsDirFor(substrateDir), `${contentHash}.json`);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* True when an object with `contentHash` already exists in the store.
|
|
48
|
+
* Asserts hash shape first (a malformed hash can never be present, but the
|
|
49
|
+
* guard keeps the surface uniform and rejects path-escape attempts at the
|
|
50
|
+
* boundary).
|
|
51
|
+
*/
|
|
52
|
+
export function hasObject(substrateDir, contentHash) {
|
|
53
|
+
assertContentHash(contentHash);
|
|
54
|
+
return fs.existsSync(objectPathFor(substrateDir, contentHash));
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Write `content` under `contentHash` if not already present.
|
|
58
|
+
*
|
|
59
|
+
* Idempotent: returns early when `hasObject` is true (content-addressed — the
|
|
60
|
+
* same hash implies the same bytes, so a re-put would rewrite identical
|
|
61
|
+
* content). On a fresh write, creates `<substrateDir>/objects/` if needed and
|
|
62
|
+
* writes `JSON.stringify(content, null, 2)` via atomic tmp+rename.
|
|
63
|
+
*
|
|
64
|
+
* `content` is expected to be the canonical content projection the caller
|
|
65
|
+
* hashed to obtain `contentHash`; this module does not re-derive or verify the
|
|
66
|
+
* hash (no dependency on content-hash.ts).
|
|
67
|
+
*/
|
|
68
|
+
export function putObject(substrateDir, contentHash, content) {
|
|
69
|
+
assertContentHash(contentHash);
|
|
70
|
+
if (hasObject(substrateDir, contentHash)) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const objectsDir = objectsDirFor(substrateDir);
|
|
74
|
+
fs.mkdirSync(objectsDir, { recursive: true });
|
|
75
|
+
const filePath = objectPathFor(substrateDir, contentHash);
|
|
76
|
+
const tmpPath = `${filePath}.object-store-${process.pid}.tmp`;
|
|
77
|
+
try {
|
|
78
|
+
fs.writeFileSync(tmpPath, JSON.stringify(content, null, 2), "utf-8");
|
|
79
|
+
fs.renameSync(tmpPath, filePath);
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
try {
|
|
83
|
+
fs.unlinkSync(tmpPath);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
/* ignore cleanup failure */
|
|
87
|
+
}
|
|
88
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
89
|
+
throw new Error(`object-store: failed to write object ${contentHash}: ${msg}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Parsed content stored under `contentHash`, or `null` when no such object
|
|
94
|
+
* exists. Asserts hash shape first.
|
|
95
|
+
*/
|
|
96
|
+
export function getObject(substrateDir, contentHash) {
|
|
97
|
+
assertContentHash(contentHash);
|
|
98
|
+
const filePath = objectPathFor(substrateDir, contentHash);
|
|
99
|
+
if (!fs.existsSync(filePath)) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
return JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=object-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"object-store.js","sourceRoot":"","sources":["../src/object-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,gDAAgD;AAChD,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AAE9C;;;;;;GAMG;AACH,SAAS,iBAAiB,CAAC,WAAmB;IAC7C,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CACd,qCAAqC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,6CAA6C,CAC7G,CAAC;IACH,CAAC;AACF,CAAC;AAED,SAAS,aAAa,CAAC,YAAoB;IAC1C,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,aAAa,CAAC,YAAoB,EAAE,WAAmB;IAC/D,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,EAAE,GAAG,WAAW,OAAO,CAAC,CAAC;AACtE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,YAAoB,EAAE,WAAmB;IAClE,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC/B,OAAO,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,CAAC;AAChE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,SAAS,CAAC,YAAoB,EAAE,WAAmB,EAAE,OAAgC;IACpG,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC/B,IAAI,SAAS,CAAC,YAAY,EAAE,WAAW,CAAC,EAAE,CAAC;QAC1C,OAAO;IACR,CAAC;IACD,MAAM,UAAU,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;IAC/C,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,aAAa,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,GAAG,QAAQ,iBAAiB,OAAO,CAAC,GAAG,MAAM,CAAC;IAC9D,IAAI,CAAC;QACJ,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACrE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,IAAI,CAAC;YACJ,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;QAAC,MAAM,CAAC;YACR,4BAA4B;QAC7B,CAAC;QACD,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,MAAM,IAAI,KAAK,CAAC,wCAAwC,WAAW,KAAK,GAAG,EAAE,CAAC,CAAC;IAChF,CAAC;AACF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,YAAoB,EAAE,WAAmB;IAClE,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC/B,MAAM,QAAQ,GAAG,aAAa,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IAC1D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC;IACb,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAA4B,CAAC;AAClF,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { type TSchema } from "typebox";
|
|
3
|
+
/**
|
|
4
|
+
* One substrate operation. `run(cwd, params)` returns the text payload that
|
|
5
|
+
* registerAll places at `content[0].text`; everything else (param coercion,
|
|
6
|
+
* library calls, early returns, throws) lives in run verbatim. `parameters` is
|
|
7
|
+
* the typebox Type.Object schema published as the tool's parameter schema.
|
|
8
|
+
*
|
|
9
|
+
* `surface` partitions ops for the downstream CLI ("use" = read/write substrate
|
|
10
|
+
* ops; "process" reserved for lifecycle/dispatch ops). `authGated` flags ops
|
|
11
|
+
* the CLI should treat as requiring credentialed confirmation; it is carried
|
|
12
|
+
* for that consumer and is not the enforcement point (the pi-agent-dispatch
|
|
13
|
+
* auth-gate remains canonical).
|
|
14
|
+
*/
|
|
15
|
+
export interface OpDefinition<P = any> {
|
|
16
|
+
name: string;
|
|
17
|
+
label: string;
|
|
18
|
+
description: string;
|
|
19
|
+
promptSnippet?: string;
|
|
20
|
+
parameters: TSchema;
|
|
21
|
+
run(cwd: string, params: P): string | Promise<string>;
|
|
22
|
+
authGated?: boolean;
|
|
23
|
+
surface: "use" | "process";
|
|
24
|
+
}
|
|
25
|
+
export declare const ops: OpDefinition[];
|
|
26
|
+
/**
|
|
27
|
+
* The pi-context-owned set of tool names that require human-authorization at
|
|
28
|
+
* the pi-agent-dispatch tool_call gate. Derived from the registry's authGated
|
|
29
|
+
* flags rather than hand-maintained, so a single source — the OpDefinition's
|
|
30
|
+
* authGated field — names both the CLI's credentialed-confirmation hint and the
|
|
31
|
+
* gate's aggregated allowlist. pi-agent-dispatch imports this via the `./ops`
|
|
32
|
+
* subpath and folds it into AUTH_REQUIRED_TOOLS alongside the other packages'
|
|
33
|
+
* owned sets. The gate at the pi-agent-dispatch layer remains the enforcement
|
|
34
|
+
* point; this list is the source of pi-context's contribution to it.
|
|
35
|
+
*/
|
|
36
|
+
export declare const gatedTools: string[];
|
|
37
|
+
/**
|
|
38
|
+
* Register every op in `ops` as a pi tool. Each tool's execute body is the
|
|
39
|
+
* uniform wrapper around the op's run(): coerce params, await run, place the
|
|
40
|
+
* returned string at content[0].text. Behavior-identical to the prior inline
|
|
41
|
+
* registrations.
|
|
42
|
+
*/
|
|
43
|
+
export declare function registerAll(pi: ExtensionAPI): void;
|
|
44
|
+
//# sourceMappingURL=ops-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ops-registry.d.ts","sourceRoot":"","sources":["../src/ops-registry.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAGX,YAAY,EAEZ,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,KAAK,OAAO,EAAQ,MAAM,SAAS,CAAC;AA4D7C;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,GAAG;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACtD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,KAAK,GAAG,SAAS,CAAC;CAC3B;AA6BD,eAAO,MAAM,GAAG,EAAE,YAAY,EAqzC7B,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,EAAsD,CAAC;AAYtF;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAuBlD"}
|