@davidorex/pi-context 0.26.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 +23 -0
- package/README.md +195 -0
- package/dist/block-api.d.ts +328 -0
- package/dist/block-api.d.ts.map +1 -0
- package/dist/block-api.js +1167 -0
- package/dist/block-api.js.map +1 -0
- package/dist/block-validation.d.ts +33 -0
- package/dist/block-validation.d.ts.map +1 -0
- package/dist/block-validation.js +213 -0
- package/dist/block-validation.js.map +1 -0
- package/dist/context-dir.d.ts +93 -0
- package/dist/context-dir.d.ts.map +1 -0
- package/dist/context-dir.js +224 -0
- package/dist/context-dir.js.map +1 -0
- package/dist/context-sdk.d.ts +428 -0
- package/dist/context-sdk.d.ts.map +1 -0
- package/dist/context-sdk.js +1327 -0
- package/dist/context-sdk.js.map +1 -0
- package/dist/context.d.ts +497 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +1060 -0
- package/dist/context.js.map +1 -0
- package/dist/dispatch-context.d.ts +112 -0
- package/dist/dispatch-context.d.ts.map +1 -0
- package/dist/dispatch-context.js +119 -0
- package/dist/dispatch-context.js.map +1 -0
- package/dist/execution-context.d.ts +138 -0
- package/dist/execution-context.d.ts.map +1 -0
- package/dist/execution-context.js +151 -0
- package/dist/execution-context.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1655 -0
- package/dist/index.js.map +1 -0
- package/dist/lens-validator.d.ts +50 -0
- package/dist/lens-validator.d.ts.map +1 -0
- package/dist/lens-validator.js +46 -0
- package/dist/lens-validator.js.map +1 -0
- package/dist/lens-view.d.ts +75 -0
- package/dist/lens-view.d.ts.map +1 -0
- package/dist/lens-view.js +253 -0
- package/dist/lens-view.js.map +1 -0
- package/dist/rename-canonical-id.d.ts +64 -0
- package/dist/rename-canonical-id.d.ts.map +1 -0
- package/dist/rename-canonical-id.js +378 -0
- package/dist/rename-canonical-id.js.map +1 -0
- package/dist/roadmap-plan.d.ts +186 -0
- package/dist/roadmap-plan.d.ts.map +1 -0
- package/dist/roadmap-plan.js +534 -0
- package/dist/roadmap-plan.js.map +1 -0
- package/dist/samples-catalog.d.ts +48 -0
- package/dist/samples-catalog.d.ts.map +1 -0
- package/dist/samples-catalog.js +128 -0
- package/dist/samples-catalog.js.map +1 -0
- package/dist/schema-migrations.d.ts +82 -0
- package/dist/schema-migrations.d.ts.map +1 -0
- package/dist/schema-migrations.js +106 -0
- package/dist/schema-migrations.js.map +1 -0
- package/dist/schema-validator.d.ts +76 -0
- package/dist/schema-validator.d.ts.map +1 -0
- package/dist/schema-validator.js +219 -0
- package/dist/schema-validator.js.map +1 -0
- package/dist/schema-write.d.ts +122 -0
- package/dist/schema-write.d.ts.map +1 -0
- package/dist/schema-write.js +210 -0
- package/dist/schema-write.js.map +1 -0
- package/dist/status-vocab.d.ts +60 -0
- package/dist/status-vocab.d.ts.map +1 -0
- package/dist/status-vocab.js +109 -0
- package/dist/status-vocab.js.map +1 -0
- package/dist/test-helpers.d.ts +12 -0
- package/dist/test-helpers.d.ts.map +1 -0
- package/dist/test-helpers.js +28 -0
- package/dist/test-helpers.js.map +1 -0
- package/dist/topo.d.ts +19 -0
- package/dist/topo.d.ts.map +1 -0
- package/dist/topo.js +99 -0
- package/dist/topo.js.map +1 -0
- package/dist/update-check.d.ts +6 -0
- package/dist/update-check.d.ts.map +1 -0
- package/dist/update-check.js +82 -0
- package/dist/update-check.js.map +1 -0
- package/package.json +115 -0
- package/samples/blocks/context-contracts.json +3 -0
- package/samples/blocks/conventions.json +3 -0
- package/samples/blocks/decisions.json +3 -0
- package/samples/blocks/features.json +3 -0
- package/samples/blocks/framework-gaps.json +3 -0
- package/samples/blocks/issues.json +3 -0
- package/samples/blocks/layer-plans.json +3 -0
- package/samples/blocks/phase.json +3 -0
- package/samples/blocks/rationale.json +3 -0
- package/samples/blocks/requirements.json +3 -0
- package/samples/blocks/research.json +3 -0
- package/samples/blocks/spec-reviews.json +3 -0
- package/samples/blocks/story.json +3 -0
- package/samples/blocks/tasks.json +3 -0
- package/samples/blocks/verification.json +3 -0
- package/samples/conception.json +467 -0
- package/samples/schemas/context-contracts.schema.json +89 -0
- package/samples/schemas/conventions.schema.json +34 -0
- package/samples/schemas/decisions.schema.json +87 -0
- package/samples/schemas/features.schema.json +53 -0
- package/samples/schemas/framework-gaps.schema.json +64 -0
- package/samples/schemas/issues.schema.json +39 -0
- package/samples/schemas/layer-plans.schema.json +92 -0
- package/samples/schemas/phase.schema.json +118 -0
- package/samples/schemas/rationale.schema.json +24 -0
- package/samples/schemas/requirements.schema.json +34 -0
- package/samples/schemas/research.schema.json +134 -0
- package/samples/schemas/spec-reviews.schema.json +62 -0
- package/samples/schemas/story.schema.json +73 -0
- package/samples/schemas/tasks.schema.json +34 -0
- package/samples/schemas/verification.schema.json +37 -0
- package/schemas/bootstrap.schema.json +24 -0
- package/schemas/config.schema.json +193 -0
- package/schemas/layer.schema.json +9 -0
- package/schemas/priority.schema.json +9 -0
- package/schemas/relations.schema.json +31 -0
- package/schemas/severity.schema.json +9 -0
- package/schemas/source.schema.json +9 -0
- package/schemas/status.schema.json +9 -0
- package/schemas/verification-method.schema.json +9 -0
- package/skill-narrative.md +130 -0
- package/skills/pi-context/SKILL.md +684 -0
- package/skills/pi-context/references/bundled-resources.md +47 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical schema-write surface — read / write / mutate the JSON Schemas
|
|
3
|
+
* that live alongside project blocks under `<contextDir>/schemas/`.
|
|
4
|
+
*
|
|
5
|
+
* Closes structurally:
|
|
6
|
+
* - FGAP-011 (canonical schema-write surface): every schema mutation that
|
|
7
|
+
* would otherwise reach `.project/schemas/*.schema.json` via direct fs
|
|
8
|
+
* edits now has a single typed entry point. Direct fs writes remain
|
|
9
|
+
* possible but are now a parallel ungated path that should be retired
|
|
10
|
+
* in any future schema mutation per the F-006-bypass-pattern discipline.
|
|
11
|
+
*
|
|
12
|
+
* Contract:
|
|
13
|
+
* - All schemas pass through AJV draft-07 meta-schema validation before
|
|
14
|
+
* they touch disk. Malformed schemas throw `ValidationError` with the
|
|
15
|
+
* meta-violation details; the file is not created or modified.
|
|
16
|
+
* - Atomic on-disk semantics — writes go to a `<file>.schema-write-<pid>.tmp`
|
|
17
|
+
* sibling and are renamed into place. A failed write leaves the prior
|
|
18
|
+
* schema byte-identical.
|
|
19
|
+
* - Schema files land at `<resolveContextDir(cwd)>/schemas/<schemaName>.schema.json`,
|
|
20
|
+
* routed through `schemaPath` (context-dir) so write resolution is identical
|
|
21
|
+
* to read resolution — pointer-canonical, `config.root` is NOT a path input
|
|
22
|
+
* (FGAP-079 / DEC-0045). Previously based on a config.root-honoring
|
|
23
|
+
* path-builder, which diverged from the pointer-canonical read side.
|
|
24
|
+
*
|
|
25
|
+
* Out-of-scope for step 3:
|
|
26
|
+
* - Schema $id + version + $ref + migration registry (FGAP-006, step 4)
|
|
27
|
+
* - Schema diff / change-log tooling
|
|
28
|
+
* - Cross-package opinionated mutators (e.g. add-author-fields shorthand)
|
|
29
|
+
*/
|
|
30
|
+
import type { DispatchContext } from "./dispatch-context.js";
|
|
31
|
+
import { ValidationError } from "./schema-validator.js";
|
|
32
|
+
/**
|
|
33
|
+
* Read a schema from `<contextDir>/schemas/<schemaName>.schema.json` and
|
|
34
|
+
* return the parsed object. Returns `null` when the file does not exist —
|
|
35
|
+
* absence is a normal pre-write state, not an error. Throws when the file
|
|
36
|
+
* exists but is unreadable or contains invalid JSON.
|
|
37
|
+
*
|
|
38
|
+
* Note: this reader does NOT meta-validate. Callers that need a guarantee
|
|
39
|
+
* the file holds a valid schema should pipe the result through
|
|
40
|
+
* `validateSchemaAgainstMeta` themselves; `updateSchema` already does.
|
|
41
|
+
*/
|
|
42
|
+
export declare function readSchema(cwd: string, schemaName: string): object | null;
|
|
43
|
+
/**
|
|
44
|
+
* Atomically write `schema` to `<contextDir>/schemas/<schemaName>.schema.json`
|
|
45
|
+
* after validating it against the JSON Schema draft-07 meta-schema.
|
|
46
|
+
*
|
|
47
|
+
* Failure modes:
|
|
48
|
+
* - Malformed schema → `ValidationError` (file not created or modified).
|
|
49
|
+
* - Filesystem failure during write → `Error` with file context; tmp file
|
|
50
|
+
* cleanup is best-effort, prior schema (if any) is left byte-identical
|
|
51
|
+
* because the rename never happened.
|
|
52
|
+
*
|
|
53
|
+
* Overwrites any existing schema at the target path; callers that need
|
|
54
|
+
* mutate-in-place semantics should use `updateSchema`.
|
|
55
|
+
*/
|
|
56
|
+
export declare function writeSchema(cwd: string, schemaName: string, schema: object): void;
|
|
57
|
+
/**
|
|
58
|
+
* Op-correct create-or-replace of a whole schema body, layered over
|
|
59
|
+
* `writeSchema` (FGAP-077 — the Pi-tool / CLI-facing schema-write op).
|
|
60
|
+
*
|
|
61
|
+
* Where `writeSchema` is an unconditional create-or-overwrite, this surface
|
|
62
|
+
* adds an explicit operation discriminator so a caller's intent (create a NEW
|
|
63
|
+
* schema vs. replace an EXISTING one) is enforced rather than silently
|
|
64
|
+
* coerced:
|
|
65
|
+
* - `operation: "create"` requires the schema to be ABSENT — a collision
|
|
66
|
+
* with an existing schema throws (use `replace` to overwrite).
|
|
67
|
+
* - `operation: "replace"` requires the schema to be PRESENT — a missing
|
|
68
|
+
* target throws (use `create` to initialize).
|
|
69
|
+
* - any other operation string throws before any disk read.
|
|
70
|
+
*
|
|
71
|
+
* The presence check reuses `readSchema` (returns `null` when absent) and the
|
|
72
|
+
* single private `schemaWritePath` helper so there is one path source. The
|
|
73
|
+
* actual write delegates to `writeSchema`, which meta-validates against the
|
|
74
|
+
* draft-07 meta-schema and writes atomically (tmp + rename); this surface adds
|
|
75
|
+
* no second validation or write path.
|
|
76
|
+
*
|
|
77
|
+
* Migration boundary (DECIDED, FGAP-077): this op writes the schema JSON and
|
|
78
|
+
* meta-validates the schema body. It does NOT migrate existing block items
|
|
79
|
+
* forward when a `replace` changes the schema's `version`. A breaking
|
|
80
|
+
* evolution is handled at READ time by `validateBlockWithMigration`, which
|
|
81
|
+
* throws a version mismatch until a code-level `MigrationFn` is registered via
|
|
82
|
+
* `createRegistry().register(...)` — and there is no Pi-tool surface for
|
|
83
|
+
* registering a `MigrationFn`. This surface does not (and must not) emit an
|
|
84
|
+
* "items exist at old version" warning: that would require reading block files
|
|
85
|
+
* to assess data-layer impact from inside the schema-write layer, inverting
|
|
86
|
+
* the read-time / write-time layering.
|
|
87
|
+
*
|
|
88
|
+
* `ctx` is accepted and IGNORED: schema files carry no author-attestation
|
|
89
|
+
* fields, so there is nothing to stamp. The parameter is present for call-site
|
|
90
|
+
* parity with the attestation-aware block-write / config-write surfaces
|
|
91
|
+
* (mirrors `amendConfigEntry`'s ctx-forwarding parameter, which forwards to
|
|
92
|
+
* `writeConfig`; here there is no author-bearing target to forward to).
|
|
93
|
+
*
|
|
94
|
+
* `opts.dryRun` runs the SAME meta-validator `writeSchema` uses against the
|
|
95
|
+
* supplied body and returns `{ written: false }` without touching disk —
|
|
96
|
+
* keeping ONE validation path (no re-implemented validation for the preview).
|
|
97
|
+
*/
|
|
98
|
+
export declare function writeSchemaChecked(cwd: string, schemaName: string, schema: object, operation: "create" | "replace", ctx?: DispatchContext, opts?: {
|
|
99
|
+
dryRun?: boolean;
|
|
100
|
+
}): {
|
|
101
|
+
written: boolean;
|
|
102
|
+
operation: "create" | "replace";
|
|
103
|
+
schemaPath: string;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Read the current schema at `<contextDir>/schemas/<schemaName>.schema.json`,
|
|
107
|
+
* pass it to `mutator`, meta-validate the result, and atomically write it
|
|
108
|
+
* back. Throws if:
|
|
109
|
+
* - the schema does not exist (`Error` — caller must initialize first)
|
|
110
|
+
* - the on-disk schema parses as JSON but the mutator output fails meta
|
|
111
|
+
* validation (`ValidationError`)
|
|
112
|
+
* - the filesystem write fails (`Error`, prior schema unchanged)
|
|
113
|
+
*
|
|
114
|
+
* `mutator` receives a deep-readable reference to the parsed schema; it is
|
|
115
|
+
* the caller's responsibility to return a fresh object rather than mutate
|
|
116
|
+
* in place — callers that mutate in place still work because the result is
|
|
117
|
+
* what writeSchema sees, but the convention is "mutator returns the new
|
|
118
|
+
* schema" so the call site reads as a transform.
|
|
119
|
+
*/
|
|
120
|
+
export declare function updateSchema(cwd: string, schemaName: string, mutator: (current: object) => object): void;
|
|
121
|
+
export { ValidationError };
|
|
122
|
+
//# sourceMappingURL=schema-write.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-write.d.ts","sourceRoot":"","sources":["../src/schema-write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAA6B,MAAM,uBAAuB,CAAC;AAgBnF;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgBzE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAuBjF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,kBAAkB,CACjC,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,QAAQ,GAAG,SAAS,EAC/B,GAAG,CAAC,EAAE,eAAe,EACrB,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GACzB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,QAAQ,GAAG,SAAS,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAgC3E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAoBxG;AAID,OAAO,EAAE,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical schema-write surface — read / write / mutate the JSON Schemas
|
|
3
|
+
* that live alongside project blocks under `<contextDir>/schemas/`.
|
|
4
|
+
*
|
|
5
|
+
* Closes structurally:
|
|
6
|
+
* - FGAP-011 (canonical schema-write surface): every schema mutation that
|
|
7
|
+
* would otherwise reach `.project/schemas/*.schema.json` via direct fs
|
|
8
|
+
* edits now has a single typed entry point. Direct fs writes remain
|
|
9
|
+
* possible but are now a parallel ungated path that should be retired
|
|
10
|
+
* in any future schema mutation per the F-006-bypass-pattern discipline.
|
|
11
|
+
*
|
|
12
|
+
* Contract:
|
|
13
|
+
* - All schemas pass through AJV draft-07 meta-schema validation before
|
|
14
|
+
* they touch disk. Malformed schemas throw `ValidationError` with the
|
|
15
|
+
* meta-violation details; the file is not created or modified.
|
|
16
|
+
* - Atomic on-disk semantics — writes go to a `<file>.schema-write-<pid>.tmp`
|
|
17
|
+
* sibling and are renamed into place. A failed write leaves the prior
|
|
18
|
+
* schema byte-identical.
|
|
19
|
+
* - Schema files land at `<resolveContextDir(cwd)>/schemas/<schemaName>.schema.json`,
|
|
20
|
+
* routed through `schemaPath` (context-dir) so write resolution is identical
|
|
21
|
+
* to read resolution — pointer-canonical, `config.root` is NOT a path input
|
|
22
|
+
* (FGAP-079 / DEC-0045). Previously based on a config.root-honoring
|
|
23
|
+
* path-builder, which diverged from the pointer-canonical read side.
|
|
24
|
+
*
|
|
25
|
+
* Out-of-scope for step 3:
|
|
26
|
+
* - Schema $id + version + $ref + migration registry (FGAP-006, step 4)
|
|
27
|
+
* - Schema diff / change-log tooling
|
|
28
|
+
* - Cross-package opinionated mutators (e.g. add-author-fields shorthand)
|
|
29
|
+
*/
|
|
30
|
+
import fs from "node:fs";
|
|
31
|
+
import path from "node:path";
|
|
32
|
+
import { schemaPath } from "./context-dir.js";
|
|
33
|
+
import { ValidationError, validateSchemaAgainstMeta } from "./schema-validator.js";
|
|
34
|
+
/**
|
|
35
|
+
* `<resolveContextDir(cwd)>/schemas/<schemaName>.schema.json` — canonical schema
|
|
36
|
+
* path, routed through `schemaPath` (context-dir) so write resolution is
|
|
37
|
+
* BYTE-IDENTICAL to read resolution (FGAP-079 / DEC-0045). Previously this was
|
|
38
|
+
* based on a config.root-honoring path-builder, which diverged from the
|
|
39
|
+
* pointer-canonical read side (`schemaPath` / `validateBlockWithMigration`) under
|
|
40
|
+
* a non-default `config.root` — schemas would be written where reads/validation
|
|
41
|
+
* could not find them. Delegating to `schemaPath` collapses the two paths to one
|
|
42
|
+
* source AND inherits its `assertSubstrateName` guard (path-traversal rejection).
|
|
43
|
+
*/
|
|
44
|
+
function schemaWritePath(cwd, schemaName) {
|
|
45
|
+
return schemaPath(cwd, schemaName);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Read a schema from `<contextDir>/schemas/<schemaName>.schema.json` and
|
|
49
|
+
* return the parsed object. Returns `null` when the file does not exist —
|
|
50
|
+
* absence is a normal pre-write state, not an error. Throws when the file
|
|
51
|
+
* exists but is unreadable or contains invalid JSON.
|
|
52
|
+
*
|
|
53
|
+
* Note: this reader does NOT meta-validate. Callers that need a guarantee
|
|
54
|
+
* the file holds a valid schema should pipe the result through
|
|
55
|
+
* `validateSchemaAgainstMeta` themselves; `updateSchema` already does.
|
|
56
|
+
*/
|
|
57
|
+
export function readSchema(cwd, schemaName) {
|
|
58
|
+
const p = schemaWritePath(cwd, schemaName);
|
|
59
|
+
if (!fs.existsSync(p))
|
|
60
|
+
return null;
|
|
61
|
+
let raw;
|
|
62
|
+
try {
|
|
63
|
+
raw = fs.readFileSync(p, "utf-8");
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
throw new Error(`readSchema: failed to read ${p}: ${err instanceof Error ? err.message : String(err)}`);
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
return JSON.parse(raw);
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
throw new Error(`readSchema: invalid JSON in ${p}: ${err instanceof Error ? err.message : String(err)}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Atomically write `schema` to `<contextDir>/schemas/<schemaName>.schema.json`
|
|
77
|
+
* after validating it against the JSON Schema draft-07 meta-schema.
|
|
78
|
+
*
|
|
79
|
+
* Failure modes:
|
|
80
|
+
* - Malformed schema → `ValidationError` (file not created or modified).
|
|
81
|
+
* - Filesystem failure during write → `Error` with file context; tmp file
|
|
82
|
+
* cleanup is best-effort, prior schema (if any) is left byte-identical
|
|
83
|
+
* because the rename never happened.
|
|
84
|
+
*
|
|
85
|
+
* Overwrites any existing schema at the target path; callers that need
|
|
86
|
+
* mutate-in-place semantics should use `updateSchema`.
|
|
87
|
+
*/
|
|
88
|
+
export function writeSchema(cwd, schemaName, schema) {
|
|
89
|
+
const p = schemaWritePath(cwd, schemaName);
|
|
90
|
+
// (1) Meta-schema validation BEFORE any disk activity.
|
|
91
|
+
validateSchemaAgainstMeta(schema, `schema '${schemaName}'`);
|
|
92
|
+
// (2) Ensure the schemas/ directory exists.
|
|
93
|
+
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
94
|
+
// (3) Atomic write: tmp + rename.
|
|
95
|
+
const tmpPath = `${p}.schema-write-${process.pid}.tmp`;
|
|
96
|
+
try {
|
|
97
|
+
fs.writeFileSync(tmpPath, `${JSON.stringify(schema, null, 2)}\n`, "utf-8");
|
|
98
|
+
fs.renameSync(tmpPath, p);
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
try {
|
|
102
|
+
fs.unlinkSync(tmpPath);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
/* best-effort cleanup — surface the original error below */
|
|
106
|
+
}
|
|
107
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
108
|
+
throw new Error(`writeSchema: failed to write ${p}: ${msg}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Op-correct create-or-replace of a whole schema body, layered over
|
|
113
|
+
* `writeSchema` (FGAP-077 — the Pi-tool / CLI-facing schema-write op).
|
|
114
|
+
*
|
|
115
|
+
* Where `writeSchema` is an unconditional create-or-overwrite, this surface
|
|
116
|
+
* adds an explicit operation discriminator so a caller's intent (create a NEW
|
|
117
|
+
* schema vs. replace an EXISTING one) is enforced rather than silently
|
|
118
|
+
* coerced:
|
|
119
|
+
* - `operation: "create"` requires the schema to be ABSENT — a collision
|
|
120
|
+
* with an existing schema throws (use `replace` to overwrite).
|
|
121
|
+
* - `operation: "replace"` requires the schema to be PRESENT — a missing
|
|
122
|
+
* target throws (use `create` to initialize).
|
|
123
|
+
* - any other operation string throws before any disk read.
|
|
124
|
+
*
|
|
125
|
+
* The presence check reuses `readSchema` (returns `null` when absent) and the
|
|
126
|
+
* single private `schemaWritePath` helper so there is one path source. The
|
|
127
|
+
* actual write delegates to `writeSchema`, which meta-validates against the
|
|
128
|
+
* draft-07 meta-schema and writes atomically (tmp + rename); this surface adds
|
|
129
|
+
* no second validation or write path.
|
|
130
|
+
*
|
|
131
|
+
* Migration boundary (DECIDED, FGAP-077): this op writes the schema JSON and
|
|
132
|
+
* meta-validates the schema body. It does NOT migrate existing block items
|
|
133
|
+
* forward when a `replace` changes the schema's `version`. A breaking
|
|
134
|
+
* evolution is handled at READ time by `validateBlockWithMigration`, which
|
|
135
|
+
* throws a version mismatch until a code-level `MigrationFn` is registered via
|
|
136
|
+
* `createRegistry().register(...)` — and there is no Pi-tool surface for
|
|
137
|
+
* registering a `MigrationFn`. This surface does not (and must not) emit an
|
|
138
|
+
* "items exist at old version" warning: that would require reading block files
|
|
139
|
+
* to assess data-layer impact from inside the schema-write layer, inverting
|
|
140
|
+
* the read-time / write-time layering.
|
|
141
|
+
*
|
|
142
|
+
* `ctx` is accepted and IGNORED: schema files carry no author-attestation
|
|
143
|
+
* fields, so there is nothing to stamp. The parameter is present for call-site
|
|
144
|
+
* parity with the attestation-aware block-write / config-write surfaces
|
|
145
|
+
* (mirrors `amendConfigEntry`'s ctx-forwarding parameter, which forwards to
|
|
146
|
+
* `writeConfig`; here there is no author-bearing target to forward to).
|
|
147
|
+
*
|
|
148
|
+
* `opts.dryRun` runs the SAME meta-validator `writeSchema` uses against the
|
|
149
|
+
* supplied body and returns `{ written: false }` without touching disk —
|
|
150
|
+
* keeping ONE validation path (no re-implemented validation for the preview).
|
|
151
|
+
*/
|
|
152
|
+
export function writeSchemaChecked(cwd, schemaName, schema, operation, ctx, opts) {
|
|
153
|
+
void ctx; // accepted for call-site parity; schema files carry no author fields.
|
|
154
|
+
const target = schemaWritePath(cwd, schemaName);
|
|
155
|
+
// (1) Operation discriminator — reject unknown ops before any disk read.
|
|
156
|
+
if (operation !== "create" && operation !== "replace") {
|
|
157
|
+
throw new Error(`writeSchemaChecked: unknown operation '${operation}' — expected create | replace`);
|
|
158
|
+
}
|
|
159
|
+
// (2) Presence guard — readSchema returns null when the file is absent.
|
|
160
|
+
const existing = readSchema(cwd, schemaName);
|
|
161
|
+
if (operation === "create" && existing !== null) {
|
|
162
|
+
throw new Error(`writeSchemaChecked: create collision — schema '${schemaName}' already exists at ${target}; use operation 'replace' to overwrite`);
|
|
163
|
+
}
|
|
164
|
+
if (operation === "replace" && existing === null) {
|
|
165
|
+
throw new Error(`writeSchemaChecked: replace target missing — schema '${schemaName}' does not exist at ${target}; use operation 'create'`);
|
|
166
|
+
}
|
|
167
|
+
// (3) Dry-run: meta-validate via the SAME validator writeSchema uses, no write.
|
|
168
|
+
if (opts?.dryRun) {
|
|
169
|
+
validateSchemaAgainstMeta(schema, `schema '${schemaName}' (dry-run)`);
|
|
170
|
+
return { written: false, operation, schemaPath: target };
|
|
171
|
+
}
|
|
172
|
+
// (4) Commit: writeSchema re-meta-validates + writes atomically (tmp + rename).
|
|
173
|
+
writeSchema(cwd, schemaName, schema);
|
|
174
|
+
return { written: true, operation, schemaPath: target };
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Read the current schema at `<contextDir>/schemas/<schemaName>.schema.json`,
|
|
178
|
+
* pass it to `mutator`, meta-validate the result, and atomically write it
|
|
179
|
+
* back. Throws if:
|
|
180
|
+
* - the schema does not exist (`Error` — caller must initialize first)
|
|
181
|
+
* - the on-disk schema parses as JSON but the mutator output fails meta
|
|
182
|
+
* validation (`ValidationError`)
|
|
183
|
+
* - the filesystem write fails (`Error`, prior schema unchanged)
|
|
184
|
+
*
|
|
185
|
+
* `mutator` receives a deep-readable reference to the parsed schema; it is
|
|
186
|
+
* the caller's responsibility to return a fresh object rather than mutate
|
|
187
|
+
* in place — callers that mutate in place still work because the result is
|
|
188
|
+
* what writeSchema sees, but the convention is "mutator returns the new
|
|
189
|
+
* schema" so the call site reads as a transform.
|
|
190
|
+
*/
|
|
191
|
+
export function updateSchema(cwd, schemaName, mutator) {
|
|
192
|
+
const current = readSchema(cwd, schemaName);
|
|
193
|
+
if (current === null) {
|
|
194
|
+
throw new Error(`updateSchema: schema '${schemaName}' does not exist at ${schemaWritePath(cwd, schemaName)}; use writeSchema to create it`);
|
|
195
|
+
}
|
|
196
|
+
const next = mutator(current);
|
|
197
|
+
// validateSchemaAgainstMeta will throw ValidationError on a malformed result;
|
|
198
|
+
// we deliberately let that propagate so the caller sees the meta details.
|
|
199
|
+
validateSchemaAgainstMeta(next, `schema '${schemaName}' (post-mutator)`);
|
|
200
|
+
// Reuse writeSchema for the atomic write — it re-validates, which is a
|
|
201
|
+
// belt-and-braces double-check rather than wasted work, since the second
|
|
202
|
+
// validation is fast on the same AJV instance and guarantees disk state
|
|
203
|
+
// matches a meta-valid schema even if a future refactor moves the
|
|
204
|
+
// pre-write check.
|
|
205
|
+
writeSchema(cwd, schemaName, next);
|
|
206
|
+
}
|
|
207
|
+
// Re-export ValidationError so consumers don't need a dual import to catch
|
|
208
|
+
// the only error subclass thrown from the meta-validation path.
|
|
209
|
+
export { ValidationError };
|
|
210
|
+
//# sourceMappingURL=schema-write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-write.js","sourceRoot":"","sources":["../src/schema-write.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status-vocabulary primitives — pure helpers mapping per-schema status enum
|
|
3
|
+
* values to a normalized StatusBucket, plus the config-override resolver.
|
|
4
|
+
*
|
|
5
|
+
* Extracted here (from roadmap-plan.ts) so both roadmap-plan AND context-sdk
|
|
6
|
+
* can consume the vocabulary without forming a module import cycle. This
|
|
7
|
+
* mirrors the topo.ts extraction precedent: context-sdk's currentState +
|
|
8
|
+
* validateContext (status-consistency invariants) and roadmap-plan's
|
|
9
|
+
* rollupPhaseStatus both bucket statuses; routing both through one
|
|
10
|
+
* substrate-light module (it imports only loadContext from
|
|
11
|
+
* context, which depends on neither roadmap-plan nor context-sdk)
|
|
12
|
+
* keeps the dependency graph acyclic.
|
|
13
|
+
*
|
|
14
|
+
* StatusBucket itself is declared in context.ts (the substrate type
|
|
15
|
+
* surface) and imported/re-exported here; it is NOT redeclared.
|
|
16
|
+
*/
|
|
17
|
+
import { type StatusBucket } from "./context.js";
|
|
18
|
+
export type { StatusBucket } from "./context.js";
|
|
19
|
+
/**
|
|
20
|
+
* Hardcoded baseline mapping from per-schema status enum values to
|
|
21
|
+
* StatusBucket. Per-project overrides land via config.status_buckets and
|
|
22
|
+
* shadow these defaults at lookup time (resolveStatusVocabulary spreads
|
|
23
|
+
* the user map over the defaults so user keys win on collision).
|
|
24
|
+
*
|
|
25
|
+
* Mappings cover the going-forward conception vocabulary — the status enums
|
|
26
|
+
* of packages/pi-context/samples/schemas/ (the DEC-0037 15-kind canon, all
|
|
27
|
+
* also live in this repo's .project/ registered block_kinds). Per DEC-0036
|
|
28
|
+
* (registry/ is retiring in favor of samples/→.context) these defaults track
|
|
29
|
+
* the conception, NOT the retired registry-only vocab (audit pass/fail/warn/
|
|
30
|
+
* skip, project inception/planning/development/maintenance, decisions
|
|
31
|
+
* revisit/tentative) — a substrate needing such vocab declares it via
|
|
32
|
+
* config.status_buckets (DEC-0025 override surface), never here.
|
|
33
|
+
* - decisions.status: open | enacted | superseded
|
|
34
|
+
* - framework-gaps.status: identified | accepted | in-progress | closed | wontfix
|
|
35
|
+
* - tasks.status: planned | in-progress | completed | blocked | cancelled
|
|
36
|
+
* - features.status: proposed | approved | in-progress | in-review | complete | blocked | cancelled
|
|
37
|
+
* - story.status: proposed | ready | in-progress | in-review | complete | blocked
|
|
38
|
+
* - research.status: planned | in-progress | complete | stale | superseded | revised
|
|
39
|
+
* - requirements.status: proposed | accepted | deferred | implemented | verified
|
|
40
|
+
* - verification.status: passed | failed | partial | skipped
|
|
41
|
+
* - spec-reviews.status: not-started | in-progress | complete | abandoned
|
|
42
|
+
* - layer-plans.status: draft | proposed | decided | in-progress | complete | abandoned
|
|
43
|
+
* - issues.status: open | resolved | deferred
|
|
44
|
+
* - phase.status: planned | in-progress | completed
|
|
45
|
+
*
|
|
46
|
+
* status-vocab.test.ts guards completeness: every samples/schemas status enum
|
|
47
|
+
* value must resolve here (only the intended terminal-not-complete set may map
|
|
48
|
+
* to "unknown"). Values still bucket to "unknown" without throwing — caller
|
|
49
|
+
* decides whether unknown statuses are warning-worthy (validateRoadmaps emits
|
|
50
|
+
* roadmap_status_unknown_value when relevant).
|
|
51
|
+
*/
|
|
52
|
+
export declare const STATUS_VOCABULARY_DEFAULTS: Record<string, StatusBucket>;
|
|
53
|
+
/**
|
|
54
|
+
* Resolve the active status-vocabulary map for `cwd` — defaults shadowed
|
|
55
|
+
* by config.status_buckets entries. Pure: builds a fresh map per call;
|
|
56
|
+
* callers caching for hot paths (rollupPhaseStatus over many phases)
|
|
57
|
+
* should pass the resolved map in directly.
|
|
58
|
+
*/
|
|
59
|
+
export declare function resolveStatusVocabulary(cwd: string): Record<string, StatusBucket>;
|
|
60
|
+
//# sourceMappingURL=status-vocab.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-vocab.d.ts","sourceRoot":"","sources":["../src/status-vocab.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAE9D,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,0BAA0B,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CA+CnE,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAGjF"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status-vocabulary primitives — pure helpers mapping per-schema status enum
|
|
3
|
+
* values to a normalized StatusBucket, plus the config-override resolver.
|
|
4
|
+
*
|
|
5
|
+
* Extracted here (from roadmap-plan.ts) so both roadmap-plan AND context-sdk
|
|
6
|
+
* can consume the vocabulary without forming a module import cycle. This
|
|
7
|
+
* mirrors the topo.ts extraction precedent: context-sdk's currentState +
|
|
8
|
+
* validateContext (status-consistency invariants) and roadmap-plan's
|
|
9
|
+
* rollupPhaseStatus both bucket statuses; routing both through one
|
|
10
|
+
* substrate-light module (it imports only loadContext from
|
|
11
|
+
* context, which depends on neither roadmap-plan nor context-sdk)
|
|
12
|
+
* keeps the dependency graph acyclic.
|
|
13
|
+
*
|
|
14
|
+
* StatusBucket itself is declared in context.ts (the substrate type
|
|
15
|
+
* surface) and imported/re-exported here; it is NOT redeclared.
|
|
16
|
+
*/
|
|
17
|
+
import { loadContext } from "./context.js";
|
|
18
|
+
/**
|
|
19
|
+
* Hardcoded baseline mapping from per-schema status enum values to
|
|
20
|
+
* StatusBucket. Per-project overrides land via config.status_buckets and
|
|
21
|
+
* shadow these defaults at lookup time (resolveStatusVocabulary spreads
|
|
22
|
+
* the user map over the defaults so user keys win on collision).
|
|
23
|
+
*
|
|
24
|
+
* Mappings cover the going-forward conception vocabulary — the status enums
|
|
25
|
+
* of packages/pi-context/samples/schemas/ (the DEC-0037 15-kind canon, all
|
|
26
|
+
* also live in this repo's .project/ registered block_kinds). Per DEC-0036
|
|
27
|
+
* (registry/ is retiring in favor of samples/→.context) these defaults track
|
|
28
|
+
* the conception, NOT the retired registry-only vocab (audit pass/fail/warn/
|
|
29
|
+
* skip, project inception/planning/development/maintenance, decisions
|
|
30
|
+
* revisit/tentative) — a substrate needing such vocab declares it via
|
|
31
|
+
* config.status_buckets (DEC-0025 override surface), never here.
|
|
32
|
+
* - decisions.status: open | enacted | superseded
|
|
33
|
+
* - framework-gaps.status: identified | accepted | in-progress | closed | wontfix
|
|
34
|
+
* - tasks.status: planned | in-progress | completed | blocked | cancelled
|
|
35
|
+
* - features.status: proposed | approved | in-progress | in-review | complete | blocked | cancelled
|
|
36
|
+
* - story.status: proposed | ready | in-progress | in-review | complete | blocked
|
|
37
|
+
* - research.status: planned | in-progress | complete | stale | superseded | revised
|
|
38
|
+
* - requirements.status: proposed | accepted | deferred | implemented | verified
|
|
39
|
+
* - verification.status: passed | failed | partial | skipped
|
|
40
|
+
* - spec-reviews.status: not-started | in-progress | complete | abandoned
|
|
41
|
+
* - layer-plans.status: draft | proposed | decided | in-progress | complete | abandoned
|
|
42
|
+
* - issues.status: open | resolved | deferred
|
|
43
|
+
* - phase.status: planned | in-progress | completed
|
|
44
|
+
*
|
|
45
|
+
* status-vocab.test.ts guards completeness: every samples/schemas status enum
|
|
46
|
+
* value must resolve here (only the intended terminal-not-complete set may map
|
|
47
|
+
* to "unknown"). Values still bucket to "unknown" without throwing — caller
|
|
48
|
+
* decides whether unknown statuses are warning-worthy (validateRoadmaps emits
|
|
49
|
+
* roadmap_status_unknown_value when relevant).
|
|
50
|
+
*/
|
|
51
|
+
export const STATUS_VOCABULARY_DEFAULTS = {
|
|
52
|
+
// → complete
|
|
53
|
+
resolved: "complete",
|
|
54
|
+
completed: "complete",
|
|
55
|
+
complete: "complete",
|
|
56
|
+
done: "complete",
|
|
57
|
+
enacted: "complete",
|
|
58
|
+
implemented: "complete",
|
|
59
|
+
passed: "complete",
|
|
60
|
+
archived: "complete",
|
|
61
|
+
closed: "complete", // framework-gaps: gap resolved/done
|
|
62
|
+
verified: "complete", // requirements: terminal-done, beyond "implemented"
|
|
63
|
+
// → in_progress
|
|
64
|
+
in_progress: "in_progress",
|
|
65
|
+
"in-progress": "in_progress",
|
|
66
|
+
active: "in_progress",
|
|
67
|
+
accepted: "in_progress",
|
|
68
|
+
"in-review": "in_progress", // features/story: under review, still active (not yet complete)
|
|
69
|
+
revised: "in_progress", // research: transient state during re-investigation
|
|
70
|
+
partial: "in_progress", // verification: incomplete — NOT a clean pass, must not assert complete
|
|
71
|
+
// → blocked
|
|
72
|
+
blocked: "blocked",
|
|
73
|
+
paused: "blocked",
|
|
74
|
+
failed: "blocked",
|
|
75
|
+
// → todo
|
|
76
|
+
open: "todo",
|
|
77
|
+
todo: "todo",
|
|
78
|
+
planned: "todo",
|
|
79
|
+
proposed: "todo",
|
|
80
|
+
draft: "todo",
|
|
81
|
+
identified: "todo",
|
|
82
|
+
"not-started": "todo",
|
|
83
|
+
pending: "todo",
|
|
84
|
+
approved: "todo", // features: approved to build, not yet started
|
|
85
|
+
ready: "todo", // story/features: refined + ready to pick up, not started
|
|
86
|
+
decided: "todo", // layer-plans: plan decided to execute, before in-progress
|
|
87
|
+
// superseded / cancelled / deferred / abandoned / wontfix / skipped / stale
|
|
88
|
+
// bucket to unknown — terminal-but-not-complete states that don't fit the
|
|
89
|
+
// linear progress narrative. Roadmap/plan rollups treat them as "doesn't
|
|
90
|
+
// count toward progress" rather than as complete or todo.
|
|
91
|
+
superseded: "unknown",
|
|
92
|
+
cancelled: "unknown",
|
|
93
|
+
deferred: "unknown",
|
|
94
|
+
abandoned: "unknown", // layer-plans/spec-reviews: work stopped, not completed
|
|
95
|
+
wontfix: "unknown", // framework-gaps: decided not to address
|
|
96
|
+
skipped: "unknown", // verification: waived/not run — must not assert complete
|
|
97
|
+
stale: "unknown", // research: grounding no longer authoritative (degraded-complete)
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Resolve the active status-vocabulary map for `cwd` — defaults shadowed
|
|
101
|
+
* by config.status_buckets entries. Pure: builds a fresh map per call;
|
|
102
|
+
* callers caching for hot paths (rollupPhaseStatus over many phases)
|
|
103
|
+
* should pass the resolved map in directly.
|
|
104
|
+
*/
|
|
105
|
+
export function resolveStatusVocabulary(cwd) {
|
|
106
|
+
const ctx = loadContext(cwd);
|
|
107
|
+
return { ...STATUS_VOCABULARY_DEFAULTS, ...(ctx.config?.status_buckets ?? {}) };
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=status-vocab.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-vocab.js","sourceRoot":"","sources":["../src/status-vocab.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,WAAW,EAAqB,MAAM,cAAc,CAAC;AAI9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAiC;IACvE,aAAa;IACb,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,UAAU;IACrB,QAAQ,EAAE,UAAU;IACpB,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,UAAU;IACnB,WAAW,EAAE,UAAU;IACvB,MAAM,EAAE,UAAU;IAClB,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,UAAU,EAAE,oCAAoC;IACxD,QAAQ,EAAE,UAAU,EAAE,oDAAoD;IAC1E,gBAAgB;IAChB,WAAW,EAAE,aAAa;IAC1B,aAAa,EAAE,aAAa;IAC5B,MAAM,EAAE,aAAa;IACrB,QAAQ,EAAE,aAAa;IACvB,WAAW,EAAE,aAAa,EAAE,gEAAgE;IAC5F,OAAO,EAAE,aAAa,EAAE,oDAAoD;IAC5E,OAAO,EAAE,aAAa,EAAE,wEAAwE;IAChG,YAAY;IACZ,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,SAAS;IACjB,SAAS;IACT,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,MAAM;IACf,QAAQ,EAAE,MAAM;IAChB,KAAK,EAAE,MAAM;IACb,UAAU,EAAE,MAAM;IAClB,aAAa,EAAE,MAAM;IACrB,OAAO,EAAE,MAAM;IACf,QAAQ,EAAE,MAAM,EAAE,+CAA+C;IACjE,KAAK,EAAE,MAAM,EAAE,0DAA0D;IACzE,OAAO,EAAE,MAAM,EAAE,2DAA2D;IAC5E,4EAA4E;IAC5E,0EAA0E;IAC1E,yEAAyE;IACzE,0DAA0D;IAC1D,UAAU,EAAE,SAAS;IACrB,SAAS,EAAE,SAAS;IACpB,QAAQ,EAAE,SAAS;IACnB,SAAS,EAAE,SAAS,EAAE,wDAAwD;IAC9E,OAAO,EAAE,SAAS,EAAE,yCAAyC;IAC7D,OAAO,EAAE,SAAS,EAAE,0DAA0D;IAC9E,KAAK,EAAE,SAAS,EAAE,kEAAkE;CACpF,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,GAAW;IAClD,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC7B,OAAO,EAAE,GAAG,0BAA0B,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,IAAI,EAAE,CAAC,EAAE,CAAC;AACjF,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared test helpers for pi-project tests — mock factories for ctx and pi.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Create a mock extension context for testing.
|
|
6
|
+
*/
|
|
7
|
+
export declare function mockCtx(cwd: string): any;
|
|
8
|
+
/**
|
|
9
|
+
* Create a mock pi API for testing.
|
|
10
|
+
*/
|
|
11
|
+
export declare function mockPi(): any;
|
|
12
|
+
//# sourceMappingURL=test-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-helpers.d.ts","sourceRoot":"","sources":["../src/test-helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAS7B,GAAG,CACR;AAED;;GAEG;AACH,wBAAgB,MAAM,IAKhB,GAAG,CACR"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared test helpers for pi-project tests — mock factories for ctx and pi.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Create a mock extension context for testing.
|
|
6
|
+
*/
|
|
7
|
+
export function mockCtx(cwd) {
|
|
8
|
+
return {
|
|
9
|
+
cwd,
|
|
10
|
+
hasUI: false,
|
|
11
|
+
ui: {
|
|
12
|
+
setWidget: () => { },
|
|
13
|
+
notify: () => { },
|
|
14
|
+
setStatus: () => { },
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Create a mock pi API for testing.
|
|
20
|
+
*/
|
|
21
|
+
export function mockPi() {
|
|
22
|
+
const messages = [];
|
|
23
|
+
return {
|
|
24
|
+
sendMessage: (msg, opts) => messages.push({ msg, opts }),
|
|
25
|
+
_messages: messages,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=test-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-helpers.js","sourceRoot":"","sources":["../src/test-helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,UAAU,OAAO,CAAC,GAAW;IAClC,OAAO;QACN,GAAG;QACH,KAAK,EAAE,KAAK;QACZ,EAAE,EAAE;YACH,SAAS,EAAE,GAAG,EAAE,GAAE,CAAC;YACnB,MAAM,EAAE,GAAG,EAAE,GAAE,CAAC;YAChB,SAAS,EAAE,GAAG,EAAE,GAAE,CAAC;SACnB;KACM,CAAC;AACV,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,MAAM;IACrB,MAAM,QAAQ,GAAU,EAAE,CAAC;IAC3B,OAAO;QACN,WAAW,EAAE,CAAC,GAAQ,EAAE,IAAS,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;QAClE,SAAS,EAAE,QAAQ;KACZ,CAAC;AACV,CAAC"}
|
package/dist/topo.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic topological sort + cycle detection — a pure utility with no
|
|
3
|
+
* substrate dependency. Extracted here (from roadmap-plan.ts) so both
|
|
4
|
+
* roadmap-plan and context-sdk can consume it without forming a module
|
|
5
|
+
* import cycle (context-sdk.currentState + roadmap-plan both topo-order).
|
|
6
|
+
*
|
|
7
|
+
* Returns:
|
|
8
|
+
* order — dependency-respecting id order (Kahn's algorithm; stable,
|
|
9
|
+
* preserves input order within a stratum).
|
|
10
|
+
* cycles — array of cycle paths, each a string[] starting and ending
|
|
11
|
+
* with the same id. Empty when the graph is acyclic.
|
|
12
|
+
*
|
|
13
|
+
* Callers choose whether cycles are fatal.
|
|
14
|
+
*/
|
|
15
|
+
export declare function topoSort<T>(nodes: T[], idOf: (n: T) => string, deps: (n: T) => string[]): {
|
|
16
|
+
order: string[];
|
|
17
|
+
cycles: string[][];
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=topo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"topo.d.ts","sourceRoot":"","sources":["../src/topo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EACzB,KAAK,EAAE,CAAC,EAAE,EACV,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,EACtB,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,EAAE,GACtB;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAA;CAAE,CAkFzC"}
|