@wildorder/nightshift 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/author.d.ts.map +1 -1
- package/dist/author.js +43 -0
- package/dist/author.js.map +1 -1
- package/dist/cli.js +73 -3
- package/dist/cli.js.map +1 -1
- package/dist/decision-ledger.d.ts +10 -0
- package/dist/decision-ledger.d.ts.map +1 -1
- package/dist/decision-ledger.js +7 -0
- package/dist/decision-ledger.js.map +1 -1
- package/dist/exit-codes.d.ts +16 -2
- package/dist/exit-codes.d.ts.map +1 -1
- package/dist/exit-codes.js +17 -2
- package/dist/exit-codes.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/manifest.d.ts +47 -13
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +80 -11
- package/dist/manifest.js.map +1 -1
- package/dist/preflight.d.ts +73 -0
- package/dist/preflight.d.ts.map +1 -0
- package/dist/preflight.js +225 -0
- package/dist/preflight.js.map +1 -0
- package/dist/publish.d.ts +36 -0
- package/dist/publish.d.ts.map +1 -1
- package/dist/publish.js +185 -0
- package/dist/publish.js.map +1 -1
- package/dist/run-program.d.ts +18 -1
- package/dist/run-program.d.ts.map +1 -1
- package/dist/run-program.js +152 -10
- package/dist/run-program.js.map +1 -1
- package/dist/skill-roots.d.ts +11 -3
- package/dist/skill-roots.d.ts.map +1 -1
- package/dist/skill-roots.js +59 -12
- package/dist/skill-roots.js.map +1 -1
- package/package.json +1 -1
- package/skills/plan-program/SKILL.md +125 -5
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AAKrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AAKrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC"}
|
package/dist/manifest.d.ts
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
/**
|
|
3
3
|
* The program manifest: the single canonical home for success criteria, the
|
|
4
|
-
* workstream roster, dependencies, and
|
|
5
|
-
* runner reads it and writes workstream status back.
|
|
6
|
-
* the program document, never here — one canonical home
|
|
4
|
+
* workstream roster, dependencies, scope, and human prerequisites. `/plan-
|
|
5
|
+
* program` writes it; the runner reads it and writes workstream status back.
|
|
6
|
+
* Narrative belongs in the program document, never here — one canonical home
|
|
7
|
+
* per fact.
|
|
7
8
|
*/
|
|
8
|
-
export declare const WORKSTREAM_STATUSES: readonly ["not_started", "in_progress", "complete", "failed", "parked"];
|
|
9
|
+
export declare const WORKSTREAM_STATUSES: readonly ["not_started", "in_progress", "complete", "failed", "parked", "awaiting_human"];
|
|
9
10
|
export type WorkstreamStatus = (typeof WORKSTREAM_STATUSES)[number];
|
|
10
|
-
declare const
|
|
11
|
+
export declare const PREREQUISITE_STATUSES: readonly ["pending", "satisfied"];
|
|
12
|
+
export type PrerequisiteStatus = (typeof PREREQUISITE_STATUSES)[number];
|
|
13
|
+
export declare const prerequisiteSchema: z.ZodObject<{
|
|
14
|
+
id: z.ZodString;
|
|
15
|
+
description: z.ZodString;
|
|
16
|
+
remediation: z.ZodString;
|
|
17
|
+
verifyCommand: z.ZodString;
|
|
18
|
+
status: z.ZodDefault<z.ZodEnum<{
|
|
19
|
+
pending: "pending";
|
|
20
|
+
satisfied: "satisfied";
|
|
21
|
+
}>>;
|
|
22
|
+
}, z.core.$strip>;
|
|
23
|
+
export type Prerequisite = z.infer<typeof prerequisiteSchema>;
|
|
24
|
+
export declare const workstreamSchema: z.ZodObject<{
|
|
11
25
|
id: z.ZodString;
|
|
12
26
|
name: z.ZodString;
|
|
13
27
|
taskFile: z.ZodString;
|
|
@@ -17,6 +31,7 @@ declare const workstreamSchema: z.ZodObject<{
|
|
|
17
31
|
in_progress: "in_progress";
|
|
18
32
|
complete: "complete";
|
|
19
33
|
parked: "parked";
|
|
34
|
+
awaiting_human: "awaiting_human";
|
|
20
35
|
}>>;
|
|
21
36
|
commit: z.ZodOptional<z.ZodString>;
|
|
22
37
|
size: z.ZodOptional<z.ZodString>;
|
|
@@ -27,6 +42,7 @@ declare const workstreamSchema: z.ZodObject<{
|
|
|
27
42
|
}, z.core.$strip>>;
|
|
28
43
|
dependencies: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
29
44
|
packages: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
45
|
+
prerequisites: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
30
46
|
specHash: z.ZodOptional<z.ZodString>;
|
|
31
47
|
}, z.core.$strip>;
|
|
32
48
|
declare const manifestSchema: z.ZodObject<{
|
|
@@ -57,6 +73,7 @@ declare const manifestSchema: z.ZodObject<{
|
|
|
57
73
|
in_progress: "in_progress";
|
|
58
74
|
complete: "complete";
|
|
59
75
|
parked: "parked";
|
|
76
|
+
awaiting_human: "awaiting_human";
|
|
60
77
|
}>>;
|
|
61
78
|
commit: z.ZodOptional<z.ZodString>;
|
|
62
79
|
size: z.ZodOptional<z.ZodString>;
|
|
@@ -67,23 +84,40 @@ declare const manifestSchema: z.ZodObject<{
|
|
|
67
84
|
}, z.core.$strip>>;
|
|
68
85
|
dependencies: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
69
86
|
packages: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
87
|
+
prerequisites: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
70
88
|
specHash: z.ZodOptional<z.ZodString>;
|
|
71
89
|
}, z.core.$loose>>;
|
|
72
90
|
outOfScope: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
91
|
+
prerequisites: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
92
|
+
id: z.ZodString;
|
|
93
|
+
description: z.ZodString;
|
|
94
|
+
remediation: z.ZodString;
|
|
95
|
+
verifyCommand: z.ZodString;
|
|
96
|
+
status: z.ZodDefault<z.ZodEnum<{
|
|
97
|
+
pending: "pending";
|
|
98
|
+
satisfied: "satisfied";
|
|
99
|
+
}>>;
|
|
100
|
+
}, z.core.$loose>>>;
|
|
73
101
|
}, z.core.$loose>;
|
|
74
102
|
export type Workstream = z.infer<typeof workstreamSchema>;
|
|
75
103
|
export type ProgramManifest = z.infer<typeof manifestSchema>;
|
|
76
104
|
/**
|
|
77
105
|
* Fingerprint of everything the authoring brief projects from the manifest
|
|
78
|
-
* for one workstream: its name and scope, its dependency edges,
|
|
79
|
-
* program-wide success criteria
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
106
|
+
* for one workstream: its name and scope, its dependency edges, the
|
|
107
|
+
* program-wide success criteria, and — when the workstream references at
|
|
108
|
+
* least one — its prerequisites resolved to exactly the fields the brief
|
|
109
|
+
* projects (id, description, verifyCommand; sorted by id). `remediation` and
|
|
110
|
+
* `status` are excluded: the brief never projects remediation, and a
|
|
111
|
+
* `pending` → `satisfied` flip must never re-author a spec. The key is
|
|
112
|
+
* omitted entirely for prerequisite-free workstreams so their hash stays
|
|
113
|
+
* byte-identical to before prerequisites existed. Deliberately excludes
|
|
114
|
+
* runner-owned bookkeeping (status, commit, specHash itself) and taskFile
|
|
115
|
+
* (moving the file makes the spec missing, which re-authors anyway).
|
|
116
|
+
* Computed after authoring's own dependency merges and stamped as
|
|
117
|
+
* `specHash`, so a run can tell "the human edited the manifest after this
|
|
118
|
+
* spec was written" from "the manifest is as the author saw it".
|
|
85
119
|
*/
|
|
86
|
-
export declare function specInputsHash(manifest: Pick<ProgramManifest, "successCriteria">, workstream: Pick<Workstream, "name" | "scope" | "dependencies">): string;
|
|
120
|
+
export declare function specInputsHash(manifest: Pick<ProgramManifest, "successCriteria" | "prerequisites">, workstream: Pick<Workstream, "name" | "scope" | "dependencies" | "prerequisites">): string;
|
|
87
121
|
export declare function manifestPath(root: string, programId: string): string;
|
|
88
122
|
export declare function loadManifest(root: string, programId: string): Promise<ProgramManifest>;
|
|
89
123
|
export declare function saveManifest(root: string, programId: string, manifest: ProgramManifest): Promise<void>;
|
package/dist/manifest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;GAMG;AAEH,eAAO,MAAM,mBAAmB,2FAOtB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpE,eAAO,MAAM,qBAAqB,mCAAoC,CAAC;AAEvE,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAExE,eAAO,MAAM,kBAAkB;;;;;;;;;iBAsB7B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAQ9D,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;iBA4B3B,CAAC;AAEH,QAAA,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuBV,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC1D,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE7D;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,IAAI,CAAC,eAAe,EAAE,iBAAiB,GAAG,eAAe,CAAC,EACpE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,GAAG,cAAc,GAAG,eAAe,CAAC,GAChF,MAAM,CA6BR;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAOpE;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CA4D1B;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC,IAAI,CAAC,CAMf"}
|
package/dist/manifest.js
CHANGED
|
@@ -4,9 +4,10 @@ import { join, resolve } from "node:path";
|
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
/**
|
|
6
6
|
* The program manifest: the single canonical home for success criteria, the
|
|
7
|
-
* workstream roster, dependencies, and
|
|
8
|
-
* runner reads it and writes workstream status back.
|
|
9
|
-
* the program document, never here — one canonical home
|
|
7
|
+
* workstream roster, dependencies, scope, and human prerequisites. `/plan-
|
|
8
|
+
* program` writes it; the runner reads it and writes workstream status back.
|
|
9
|
+
* Narrative belongs in the program document, never here — one canonical home
|
|
10
|
+
* per fact.
|
|
10
11
|
*/
|
|
11
12
|
export const WORKSTREAM_STATUSES = [
|
|
12
13
|
"not_started",
|
|
@@ -14,13 +15,38 @@ export const WORKSTREAM_STATUSES = [
|
|
|
14
15
|
"complete",
|
|
15
16
|
"failed",
|
|
16
17
|
"parked",
|
|
18
|
+
"awaiting_human",
|
|
17
19
|
];
|
|
20
|
+
export const PREREQUISITE_STATUSES = ["pending", "satisfied"];
|
|
21
|
+
export const prerequisiteSchema = z.object({
|
|
22
|
+
/**
|
|
23
|
+
* Stable id, conventionally `HP-xx` (a documented convention, not a
|
|
24
|
+
* schema-enforced format). Unique within a manifest — a duplicate is a
|
|
25
|
+
* named load error (see {@link loadManifest}).
|
|
26
|
+
*/
|
|
27
|
+
id: z.string().min(1),
|
|
28
|
+
/** Human-facing statement of the action only a human can perform. */
|
|
29
|
+
description: z.string().min(1),
|
|
30
|
+
/** The exact commands or console steps that perform the action. */
|
|
31
|
+
remediation: z.string().min(1),
|
|
32
|
+
/**
|
|
33
|
+
* A shell command that exits zero iff the action is done. Executed by the
|
|
34
|
+
* runner itself as a deterministic subprocess, never by a model. Trust
|
|
35
|
+
* boundary: the manifest is repo-tracked and human-reviewed at planning
|
|
36
|
+
* time, so this string is the same trust class as the verify commands in
|
|
37
|
+
* `nightshift.config.json` (see `configSchema.verify` in `src/config.ts`)
|
|
38
|
+
* — no sandbox beyond a bounded timeout and fail-open-to-unmet, both owned
|
|
39
|
+
* by the runner.
|
|
40
|
+
*/
|
|
41
|
+
verifyCommand: z.string().min(1),
|
|
42
|
+
status: z.enum(PREREQUISITE_STATUSES).default("pending"),
|
|
43
|
+
});
|
|
18
44
|
const scopeSchema = z.object({
|
|
19
45
|
summary: z.string().min(1),
|
|
20
46
|
includes: z.array(z.string()).default([]),
|
|
21
47
|
excludes: z.array(z.string()).default([]),
|
|
22
48
|
});
|
|
23
|
-
const workstreamSchema = z.object({
|
|
49
|
+
export const workstreamSchema = z.object({
|
|
24
50
|
id: z.string().min(1),
|
|
25
51
|
name: z.string().min(1),
|
|
26
52
|
taskFile: z.string().min(1),
|
|
@@ -31,6 +57,15 @@ const workstreamSchema = z.object({
|
|
|
31
57
|
scope: scopeSchema.optional(),
|
|
32
58
|
dependencies: z.array(z.string()).default([]),
|
|
33
59
|
packages: z.array(z.string()).default([]),
|
|
60
|
+
/**
|
|
61
|
+
* Ids of program-level prerequisites this workstream waits on. Validated
|
|
62
|
+
* at load exactly as {@link Workstream.dependencies} are — an id with no
|
|
63
|
+
* matching entry in the manifest's `prerequisites` array is a named load
|
|
64
|
+
* error, not a runtime surprise. Each referenced id resolves to exactly
|
|
65
|
+
* one record, because program-level prerequisite ids are unique (checked
|
|
66
|
+
* at load). Absent on manifests without prerequisites.
|
|
67
|
+
*/
|
|
68
|
+
prerequisites: z.array(z.string()).default([]),
|
|
34
69
|
/**
|
|
35
70
|
* {@link specInputsHash} of the manifest inputs the spec was authored
|
|
36
71
|
* from, stamped by the authoring stage. A mismatch on a later run means
|
|
@@ -59,19 +94,27 @@ const manifestSchema = z
|
|
|
59
94
|
packages: z.array(z.record(z.string(), z.unknown())).default([]),
|
|
60
95
|
workstreams: z.array(workstreamSchema.loose()).min(1),
|
|
61
96
|
outOfScope: z.array(z.string()).default([]),
|
|
97
|
+
prerequisites: z.array(prerequisiteSchema.loose()).default([]),
|
|
62
98
|
})
|
|
63
99
|
.loose();
|
|
64
100
|
/**
|
|
65
101
|
* Fingerprint of everything the authoring brief projects from the manifest
|
|
66
|
-
* for one workstream: its name and scope, its dependency edges,
|
|
67
|
-
* program-wide success criteria
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
102
|
+
* for one workstream: its name and scope, its dependency edges, the
|
|
103
|
+
* program-wide success criteria, and — when the workstream references at
|
|
104
|
+
* least one — its prerequisites resolved to exactly the fields the brief
|
|
105
|
+
* projects (id, description, verifyCommand; sorted by id). `remediation` and
|
|
106
|
+
* `status` are excluded: the brief never projects remediation, and a
|
|
107
|
+
* `pending` → `satisfied` flip must never re-author a spec. The key is
|
|
108
|
+
* omitted entirely for prerequisite-free workstreams so their hash stays
|
|
109
|
+
* byte-identical to before prerequisites existed. Deliberately excludes
|
|
110
|
+
* runner-owned bookkeeping (status, commit, specHash itself) and taskFile
|
|
111
|
+
* (moving the file makes the spec missing, which re-authors anyway).
|
|
112
|
+
* Computed after authoring's own dependency merges and stamped as
|
|
113
|
+
* `specHash`, so a run can tell "the human edited the manifest after this
|
|
114
|
+
* spec was written" from "the manifest is as the author saw it".
|
|
73
115
|
*/
|
|
74
116
|
export function specInputsHash(manifest, workstream) {
|
|
117
|
+
const prerequisiteById = new Map(manifest.prerequisites.map((entry) => [entry.id, entry]));
|
|
75
118
|
const inputs = {
|
|
76
119
|
name: workstream.name,
|
|
77
120
|
scope: workstream.scope ?? null,
|
|
@@ -80,6 +123,18 @@ export function specInputsHash(manifest, workstream) {
|
|
|
80
123
|
id: criterion.id,
|
|
81
124
|
description: criterion.description,
|
|
82
125
|
})),
|
|
126
|
+
...(workstream.prerequisites.length > 0
|
|
127
|
+
? {
|
|
128
|
+
prerequisites: [...workstream.prerequisites].sort().map((id) => {
|
|
129
|
+
const entry = prerequisiteById.get(id);
|
|
130
|
+
return {
|
|
131
|
+
id,
|
|
132
|
+
description: entry?.description ?? null,
|
|
133
|
+
verifyCommand: entry?.verifyCommand ?? null,
|
|
134
|
+
};
|
|
135
|
+
}),
|
|
136
|
+
}
|
|
137
|
+
: {}),
|
|
83
138
|
};
|
|
84
139
|
return createHash("sha256")
|
|
85
140
|
.update(JSON.stringify(inputs))
|
|
@@ -123,6 +178,20 @@ export async function loadManifest(root, programId) {
|
|
|
123
178
|
}
|
|
124
179
|
}
|
|
125
180
|
}
|
|
181
|
+
const prerequisiteIds = new Set();
|
|
182
|
+
for (const prerequisite of manifest.prerequisites) {
|
|
183
|
+
if (prerequisiteIds.has(prerequisite.id)) {
|
|
184
|
+
throw new Error(`${path}: duplicate prerequisite id "${prerequisite.id}"`);
|
|
185
|
+
}
|
|
186
|
+
prerequisiteIds.add(prerequisite.id);
|
|
187
|
+
}
|
|
188
|
+
for (const workstream of manifest.workstreams) {
|
|
189
|
+
for (const prerequisite of workstream.prerequisites) {
|
|
190
|
+
if (!prerequisiteIds.has(prerequisite)) {
|
|
191
|
+
throw new Error(`${path}: ${workstream.id} requires unknown prerequisite "${prerequisite}"`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
126
195
|
return manifest;
|
|
127
196
|
}
|
|
128
197
|
export async function saveManifest(root, programId, manifest) {
|
package/dist/manifest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { LedgerEvent } from "./decision-ledger.js";
|
|
2
|
+
import type { ProgramManifest } from "./manifest.js";
|
|
3
|
+
/**
|
|
4
|
+
* The preflight stage: at run start, before baseline verification and any
|
|
5
|
+
* agent spawn, executes every *pending* prerequisite's `verifyCommand` as a
|
|
6
|
+
* deterministic, bounded subprocess. Exit zero flips it to `satisfied` (in
|
|
7
|
+
* memory — the caller decides when to persist); anything else — nonzero
|
|
8
|
+
* exit, spawn failure, timeout — uniformly means unmet, with a captured
|
|
9
|
+
* reason, and never throws out of this module. See
|
|
10
|
+
* `tasks/human-prerequisites/ws-02-*.md` for the full design.
|
|
11
|
+
*/
|
|
12
|
+
/** The wall-clock ceiling on a single prerequisite check. A deterministic
|
|
13
|
+
* check that has not answered in this long is treated as unmet, and the
|
|
14
|
+
* process tree is killed so it can never outlive the run. A constant, never
|
|
15
|
+
* a config key — the charter keeps tuning knobs off the config surface. */
|
|
16
|
+
export declare const PREREQUISITE_TIMEOUT_MS = 60000;
|
|
17
|
+
export interface PrerequisiteRun {
|
|
18
|
+
exitCode: number;
|
|
19
|
+
output: string;
|
|
20
|
+
/** True when the process tree was killed for exceeding the timeout. */
|
|
21
|
+
timedOut: boolean;
|
|
22
|
+
}
|
|
23
|
+
export type PrerequisiteRunner = (command: string, cwd: string) => Promise<PrerequisiteRun>;
|
|
24
|
+
/**
|
|
25
|
+
* Builds a bounded, process-tree-killing `PrerequisiteRunner`. Fixing the
|
|
26
|
+
* timeout inside a `(command, cwd)` runner would leave a timeout test no
|
|
27
|
+
* choice but to wait out the real production ceiling; this factory keeps the
|
|
28
|
+
* ceiling a test seam while {@link defaultPrerequisiteRunner} wires the
|
|
29
|
+
* production constant once.
|
|
30
|
+
*/
|
|
31
|
+
export declare function makePrerequisiteRunner(timeoutMs?: number): PrerequisiteRunner;
|
|
32
|
+
/** The production runner: the 60 s ceiling, wired once. */
|
|
33
|
+
export declare const defaultPrerequisiteRunner: PrerequisiteRunner;
|
|
34
|
+
export interface PrerequisiteCheck {
|
|
35
|
+
id: string;
|
|
36
|
+
met: boolean;
|
|
37
|
+
/** Captured reason when unmet — always non-empty so the report never
|
|
38
|
+
* renders a blank line. The tailed verify output on a nonzero exit; on a
|
|
39
|
+
* nonzero exit that emitted no output, a fallback naming the exit code;
|
|
40
|
+
* the spawn error message (or a generic notice) on a spawn failure; a
|
|
41
|
+
* notice naming the ceiling on a timeout. Absent only when met. */
|
|
42
|
+
reason?: string;
|
|
43
|
+
/** True when this run's preflight flipped it pending → satisfied. False
|
|
44
|
+
* for an already-satisfied prerequisite (not re-run) and for an unmet
|
|
45
|
+
* one. */
|
|
46
|
+
newlySatisfied: boolean;
|
|
47
|
+
}
|
|
48
|
+
export interface PreflightResult {
|
|
49
|
+
checks: PrerequisiteCheck[];
|
|
50
|
+
/** Ledger events for the prerequisites this run newly satisfied. The
|
|
51
|
+
* caller appends these once its own baseline verification admits the run
|
|
52
|
+
* — see run-program.ts's staged-persistence wiring. */
|
|
53
|
+
events: LedgerEvent[];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Runs every pending prerequisite's `verifyCommand` once. Mutates
|
|
57
|
+
* `manifest.prerequisites` in place on a met check (pending → satisfied);
|
|
58
|
+
* the caller decides when (and whether) to persist that mutation to disk. An
|
|
59
|
+
* already-`satisfied` prerequisite is never re-run — settled facts stay
|
|
60
|
+
* settled (SC-06). No `verifyCommand` outcome can throw out of this
|
|
61
|
+
* function or halt the run (SC-03): a thrown spawn failure is caught here.
|
|
62
|
+
*/
|
|
63
|
+
export declare function runPreflight(args: {
|
|
64
|
+
manifest: ProgramManifest;
|
|
65
|
+
cwd: string;
|
|
66
|
+
runner: PrerequisiteRunner;
|
|
67
|
+
now: () => Date;
|
|
68
|
+
/** The run's identity, stamped on each `prerequisite-verified` event. */
|
|
69
|
+
runId: string;
|
|
70
|
+
runStartCommit: string | undefined;
|
|
71
|
+
log: (line: string) => void;
|
|
72
|
+
}): Promise<PreflightResult>;
|
|
73
|
+
//# sourceMappingURL=preflight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preflight.d.ts","sourceRoot":"","sources":["../src/preflight.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGrD;;;;;;;;GAQG;AAEH;;;4EAG4E;AAC5E,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAe9C,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,MAAM,kBAAkB,GAAG,CAC/B,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,KACR,OAAO,CAAC,eAAe,CAAC,CAAC;AAiD9B;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,GAAE,MAAgC,GAC1C,kBAAkB,CAqEpB;AAED,2DAA2D;AAC3D,eAAO,MAAM,yBAAyB,EAAE,kBACd,CAAC;AAE3B,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,OAAO,CAAC;IACb;;;;wEAIoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;eAEW;IACX,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B;;4DAEwD;IACxD,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE;IACvC,QAAQ,EAAE,eAAe,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,kBAAkB,CAAC;IAC3B,GAAG,EAAE,MAAM,IAAI,CAAC;IAChB,yEAAyE;IACzE,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B,GAAG,OAAO,CAAC,eAAe,CAAC,CA0E3B"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { tail } from "./agent-runner.js";
|
|
3
|
+
/**
|
|
4
|
+
* The preflight stage: at run start, before baseline verification and any
|
|
5
|
+
* agent spawn, executes every *pending* prerequisite's `verifyCommand` as a
|
|
6
|
+
* deterministic, bounded subprocess. Exit zero flips it to `satisfied` (in
|
|
7
|
+
* memory — the caller decides when to persist); anything else — nonzero
|
|
8
|
+
* exit, spawn failure, timeout — uniformly means unmet, with a captured
|
|
9
|
+
* reason, and never throws out of this module. See
|
|
10
|
+
* `tasks/human-prerequisites/ws-02-*.md` for the full design.
|
|
11
|
+
*/
|
|
12
|
+
/** The wall-clock ceiling on a single prerequisite check. A deterministic
|
|
13
|
+
* check that has not answered in this long is treated as unmet, and the
|
|
14
|
+
* process tree is killed so it can never outlive the run. A constant, never
|
|
15
|
+
* a config key — the charter keeps tuning knobs off the config surface. */
|
|
16
|
+
export const PREREQUISITE_TIMEOUT_MS = 60_000;
|
|
17
|
+
// In-memory output is kept to a bounded tail, mirroring agent-runner.ts's
|
|
18
|
+
// own OUTPUT_TAIL_LIMIT — this module intentionally does not import that
|
|
19
|
+
// private constant.
|
|
20
|
+
const OUTPUT_TAIL_LIMIT = 200_000;
|
|
21
|
+
/** How long a timed-out check waits, past its own ceiling, for the kill
|
|
22
|
+
* request to take effect before giving up on `close` and settling anyway.
|
|
23
|
+
* A kill (`taskkill`, a signalled process group) has no completion callback
|
|
24
|
+
* to await, so without this bound a slow or failed kill would turn a
|
|
25
|
+
* *bounded* check into an unbounded one — this is the backstop that keeps
|
|
26
|
+
* the promise settling promptly regardless. */
|
|
27
|
+
const KILL_GRACE_MS = 3_000;
|
|
28
|
+
/**
|
|
29
|
+
* Kills a spawned shell line's whole process tree, not just the shell
|
|
30
|
+
* process `spawn` returned — a `verifyCommand` may fork descendants (node,
|
|
31
|
+
* curl, a helper script), and `child.kill()` alone would orphan them: on
|
|
32
|
+
* Windows in particular, killing only the returned `cmd.exe` process leaves
|
|
33
|
+
* its own child (say, `node`) running and still holding the inherited stdio
|
|
34
|
+
* pipe handles, so `close` never fires until that orphan exits on its own —
|
|
35
|
+
* confirmed empirically (see the git history of this function's tests): a
|
|
36
|
+
* `child.kill()` issued *before* `taskkill /T` gets a chance to walk the
|
|
37
|
+
* still-live tree kills the wrapper first, orphans the descendant, and
|
|
38
|
+
* taskkill then reports "not found" for a pid that is already gone —
|
|
39
|
+
* reproducing exactly the unbounded-wait failure this function exists to
|
|
40
|
+
* prevent. So the whole tree is killed as a single unit, by pid, while the
|
|
41
|
+
* tree is still intact — never a separate signal to the immediate child
|
|
42
|
+
* first.
|
|
43
|
+
*
|
|
44
|
+
* POSIX: the child was spawned `detached: true`, making it its own
|
|
45
|
+
* process-group leader; signalling the negative pid signals the whole group
|
|
46
|
+
* atomically. `ESRCH` (the group already exited) is swallowed — best effort.
|
|
47
|
+
*
|
|
48
|
+
* Windows: there is no process-group signal, so `taskkill /T /F` is used,
|
|
49
|
+
* which walks the live process tree from `pid` and terminates it forcibly in
|
|
50
|
+
* one call. Fire-and-forget as far as this function is concerned — its
|
|
51
|
+
* caller (the grace timer in {@link makePrerequisiteRunner}) is what bounds
|
|
52
|
+
* the wait, since an external kill request has no completion callback of its
|
|
53
|
+
* own to await; a spawn failure for `taskkill` itself (e.g. an unusual PATH)
|
|
54
|
+
* is swallowed the same way.
|
|
55
|
+
*/
|
|
56
|
+
function killProcessTree(pid) {
|
|
57
|
+
if (process.platform === "win32") {
|
|
58
|
+
const killer = spawn("taskkill", ["/pid", String(pid), "/T", "/F"], {
|
|
59
|
+
windowsHide: true,
|
|
60
|
+
stdio: "ignore",
|
|
61
|
+
});
|
|
62
|
+
killer.on("error", () => {
|
|
63
|
+
// taskkill itself failed to spawn — the grace timer still bounds the
|
|
64
|
+
// wait regardless.
|
|
65
|
+
});
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
process.kill(-pid, "SIGKILL");
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// Already exited, or never became a group leader — best effort.
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Builds a bounded, process-tree-killing `PrerequisiteRunner`. Fixing the
|
|
77
|
+
* timeout inside a `(command, cwd)` runner would leave a timeout test no
|
|
78
|
+
* choice but to wait out the real production ceiling; this factory keeps the
|
|
79
|
+
* ceiling a test seam while {@link defaultPrerequisiteRunner} wires the
|
|
80
|
+
* production constant once.
|
|
81
|
+
*/
|
|
82
|
+
export function makePrerequisiteRunner(timeoutMs = PREREQUISITE_TIMEOUT_MS) {
|
|
83
|
+
return (command, cwd) => new Promise((resolvePromise, rejectPromise) => {
|
|
84
|
+
// shell: true, exactly like defaultVerifyRunner — a verifyCommand is a
|
|
85
|
+
// whole shell line the human/planner authored, run under cmd /c or
|
|
86
|
+
// /bin/sh -c. detached: true on POSIX makes the child a process-group
|
|
87
|
+
// leader so killProcessTree can signal the whole tree; Windows has no
|
|
88
|
+
// such option and uses taskkill /T instead.
|
|
89
|
+
const child = spawn(command, [], {
|
|
90
|
+
cwd,
|
|
91
|
+
shell: true,
|
|
92
|
+
windowsHide: true,
|
|
93
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
94
|
+
...(process.platform === "win32" ? {} : { detached: true }),
|
|
95
|
+
});
|
|
96
|
+
let buffered = "";
|
|
97
|
+
const push = (chunk) => {
|
|
98
|
+
buffered = (buffered + chunk).slice(-OUTPUT_TAIL_LIMIT);
|
|
99
|
+
};
|
|
100
|
+
child.stdout?.setEncoding("utf8");
|
|
101
|
+
child.stderr?.setEncoding("utf8");
|
|
102
|
+
child.stdout?.on("data", push);
|
|
103
|
+
child.stderr?.on("data", push);
|
|
104
|
+
// Never reads stdin, and ends it immediately — the same headless
|
|
105
|
+
// posture as defaultVerifyRunner (agent-runner.ts).
|
|
106
|
+
child.stdin?.end();
|
|
107
|
+
let settled = false;
|
|
108
|
+
let timedOut = false;
|
|
109
|
+
let graceTimer;
|
|
110
|
+
const settle = (result) => {
|
|
111
|
+
if (settled)
|
|
112
|
+
return;
|
|
113
|
+
settled = true;
|
|
114
|
+
clearTimeout(timer);
|
|
115
|
+
clearTimeout(graceTimer);
|
|
116
|
+
resolvePromise(result);
|
|
117
|
+
};
|
|
118
|
+
const timer = setTimeout(() => {
|
|
119
|
+
timedOut = true;
|
|
120
|
+
if (child.pid !== undefined)
|
|
121
|
+
killProcessTree(child.pid);
|
|
122
|
+
// The kill above is a request, not a confirmation — `taskkill` and a
|
|
123
|
+
// signalled process group have no completion callback this runner
|
|
124
|
+
// can await, and a slow or failed kill must never turn a *bounded*
|
|
125
|
+
// check into an unbounded one (SC-03/SC-11: the run always
|
|
126
|
+
// terminates). `close` still wins the race in the overwhelmingly
|
|
127
|
+
// common case where the kill lands promptly; this grace window is
|
|
128
|
+
// strictly a backstop for the rest.
|
|
129
|
+
graceTimer = setTimeout(() => {
|
|
130
|
+
settle({ exitCode: 1, output: buffered, timedOut: true });
|
|
131
|
+
}, KILL_GRACE_MS);
|
|
132
|
+
graceTimer.unref();
|
|
133
|
+
}, timeoutMs);
|
|
134
|
+
timer.unref();
|
|
135
|
+
child.on("error", (error) => {
|
|
136
|
+
if (settled)
|
|
137
|
+
return;
|
|
138
|
+
settled = true;
|
|
139
|
+
clearTimeout(timer);
|
|
140
|
+
clearTimeout(graceTimer);
|
|
141
|
+
rejectPromise(error);
|
|
142
|
+
});
|
|
143
|
+
child.on("close", (code) => {
|
|
144
|
+
settle({ exitCode: code ?? 1, output: buffered, timedOut });
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
/** The production runner: the 60 s ceiling, wired once. */
|
|
149
|
+
export const defaultPrerequisiteRunner = makePrerequisiteRunner();
|
|
150
|
+
/**
|
|
151
|
+
* Runs every pending prerequisite's `verifyCommand` once. Mutates
|
|
152
|
+
* `manifest.prerequisites` in place on a met check (pending → satisfied);
|
|
153
|
+
* the caller decides when (and whether) to persist that mutation to disk. An
|
|
154
|
+
* already-`satisfied` prerequisite is never re-run — settled facts stay
|
|
155
|
+
* settled (SC-06). No `verifyCommand` outcome can throw out of this
|
|
156
|
+
* function or halt the run (SC-03): a thrown spawn failure is caught here.
|
|
157
|
+
*/
|
|
158
|
+
export async function runPreflight(args) {
|
|
159
|
+
const { manifest, cwd, runner, now, runId, runStartCommit, log } = args;
|
|
160
|
+
const checks = [];
|
|
161
|
+
const events = [];
|
|
162
|
+
for (const prerequisite of manifest.prerequisites) {
|
|
163
|
+
if (prerequisite.status === "satisfied") {
|
|
164
|
+
checks.push({ id: prerequisite.id, met: true, newlySatisfied: false });
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
let run;
|
|
168
|
+
try {
|
|
169
|
+
run = await runner(prerequisite.verifyCommand, cwd);
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
const message = error?.message?.trim();
|
|
173
|
+
const reason = message && message !== ""
|
|
174
|
+
? message
|
|
175
|
+
: "the verify command could not be started";
|
|
176
|
+
checks.push({
|
|
177
|
+
id: prerequisite.id,
|
|
178
|
+
met: false,
|
|
179
|
+
reason,
|
|
180
|
+
newlySatisfied: false,
|
|
181
|
+
});
|
|
182
|
+
log(`preflight: ${prerequisite.id} unmet — ${reason}`);
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (run.timedOut) {
|
|
186
|
+
const reason = `the verify command did not finish within ` +
|
|
187
|
+
`${PREREQUISITE_TIMEOUT_MS}ms and was terminated`;
|
|
188
|
+
checks.push({
|
|
189
|
+
id: prerequisite.id,
|
|
190
|
+
met: false,
|
|
191
|
+
reason,
|
|
192
|
+
newlySatisfied: false,
|
|
193
|
+
});
|
|
194
|
+
log(`preflight: ${prerequisite.id} unmet — ${reason}`);
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
if (run.exitCode !== 0) {
|
|
198
|
+
const tailed = tail(run.output, 1500).trim();
|
|
199
|
+
const reason = tailed !== ""
|
|
200
|
+
? tailed
|
|
201
|
+
: `the verify command exited ${run.exitCode} with no output`;
|
|
202
|
+
checks.push({
|
|
203
|
+
id: prerequisite.id,
|
|
204
|
+
met: false,
|
|
205
|
+
reason,
|
|
206
|
+
newlySatisfied: false,
|
|
207
|
+
});
|
|
208
|
+
log(`preflight: ${prerequisite.id} unmet — ${reason}`);
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
prerequisite.status = "satisfied";
|
|
212
|
+
checks.push({ id: prerequisite.id, met: true, newlySatisfied: true });
|
|
213
|
+
events.push({
|
|
214
|
+
kind: "prerequisite-verified",
|
|
215
|
+
at: now().toISOString(),
|
|
216
|
+
id: prerequisite.id,
|
|
217
|
+
verifyCommand: prerequisite.verifyCommand,
|
|
218
|
+
runId,
|
|
219
|
+
...(runStartCommit === undefined ? {} : { commit: runStartCommit }),
|
|
220
|
+
});
|
|
221
|
+
log(`preflight: ${prerequisite.id} satisfied`);
|
|
222
|
+
}
|
|
223
|
+
return { checks, events };
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=preflight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preflight.js","sourceRoot":"","sources":["../src/preflight.ts"],"names":[],"mappings":"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"}
|