instar 1.3.197 → 1.3.199
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/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +16 -1
- package/dist/commands/setup.js.map +1 -1
- package/dist/core/ApprenticeshipProgram.d.ts +211 -0
- package/dist/core/ApprenticeshipProgram.d.ts.map +1 -0
- package/dist/core/ApprenticeshipProgram.js +433 -0
- package/dist/core/ApprenticeshipProgram.js.map +1 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +25 -2
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/retroHarvestValidator.d.ts +79 -0
- package/dist/core/retroHarvestValidator.d.ts.map +1 -0
- package/dist/core/retroHarvestValidator.js +256 -0
- package/dist/core/retroHarvestValidator.js.map +1 -0
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +7 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts +1 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +48 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +16 -0
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/routes.d.ts +5 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +99 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/scripts/validate-retro-harvest.mjs +31 -237
- package/src/data/builtin-manifest.json +63 -63
- package/src/scaffold/templates.ts +7 -0
- package/upgrades/1.3.198.md +24 -0
- package/upgrades/1.3.199.md +24 -0
- package/upgrades/side-effects/APPRENTICESHIP-STEP1-PROGRAM-SCAFFOLD-SPEC.md +82 -0
- package/upgrades/side-effects/fix-bootwrapper-install-path.md +83 -0
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ApprenticeshipProgram — the standing program scaffold for apprenticeship /
|
|
3
|
+
* mentorship instances (Apprenticeship Step 1, APPRENTICESHIP-STEP1-PROGRAM-
|
|
4
|
+
* SCAFFOLD-SPEC.md).
|
|
5
|
+
*
|
|
6
|
+
* Each instance is a project under a standing program that crystallizes by
|
|
7
|
+
* bootstrap. This module is the instance-as-project REGISTRY plus the two
|
|
8
|
+
* lifecycle GATES that make "review before you start / capture before you
|
|
9
|
+
* close" unskippable at the state-mutating transition:
|
|
10
|
+
*
|
|
11
|
+
* - the RETRO-GATE (pending→active): refused unless the prior instance's
|
|
12
|
+
* retro-harvest exists at its CANONICAL CONFINED PATH and passes the
|
|
13
|
+
* Step 0 validator (the first instance is seeded by the Echo→Codey
|
|
14
|
+
* bootstrap harvest).
|
|
15
|
+
* - the DOC-AS-REQUIRED-ARTIFACT GATE (active→complete): refused until the
|
|
16
|
+
* instance's declared-required artifacts are VERIFIED PRESENT FROM LIVE
|
|
17
|
+
* STATE (never a stored flag).
|
|
18
|
+
*
|
|
19
|
+
* Signal vs Authority / The Body and the Mind: the gates are structural
|
|
20
|
+
* preconditions on OBJECTIVE artifacts ("does a validated harvest exist?",
|
|
21
|
+
* "is there ≥1 instance-scoped ledger entry?"). They are NOT quality
|
|
22
|
+
* judgments — whether the mentor truly internalized the lessons stays with
|
|
23
|
+
* the overseer (the mind), informed by the gate. Every verdict is appended
|
|
24
|
+
* to logs/apprenticeship-decisions.jsonl (the decision audit).
|
|
25
|
+
*
|
|
26
|
+
* Concurrency: file-backed store at `.instar/apprenticeship/instances.json`,
|
|
27
|
+
* atomic tmp-write+rename, with a single in-process serialized mutator and an
|
|
28
|
+
* optimistic `version` CAS (lost-update safe under the single-process-per-agent
|
|
29
|
+
* AgentServer model). A corrupt/unparseable store FAILS CLOSED — gates return
|
|
30
|
+
* `allow:false`, never "no prior instance → open the gate".
|
|
31
|
+
*/
|
|
32
|
+
import fs from 'node:fs';
|
|
33
|
+
import path from 'node:path';
|
|
34
|
+
import { validateRetroHarvest, parseArtifact, safeArtifactPath, } from './retroHarvestValidator.js';
|
|
35
|
+
/** The typed no-op overseer stub (§2). */
|
|
36
|
+
export const noopApprenticeshipOverseer = {
|
|
37
|
+
computeDifferential(_instance) {
|
|
38
|
+
return { implemented: false, reason: 'differential read-channel is implemented in Step 4 (need-001)' };
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
const CHARSET_RE = /^[a-z0-9-]+$/;
|
|
42
|
+
/** Legal status transitions (§3.4). `complete` is terminal. */
|
|
43
|
+
const TRANSITIONS = {
|
|
44
|
+
pending: ['active'],
|
|
45
|
+
active: ['complete', 'blocked'],
|
|
46
|
+
blocked: ['active'],
|
|
47
|
+
complete: [], // terminal
|
|
48
|
+
};
|
|
49
|
+
// ── Implementation ───────────────────────────────────────────────────
|
|
50
|
+
export class ApprenticeshipProgram {
|
|
51
|
+
storePath;
|
|
52
|
+
decisionLogPath;
|
|
53
|
+
projectDir;
|
|
54
|
+
store;
|
|
55
|
+
/** True when the on-disk store was unparseable → gates fail closed. */
|
|
56
|
+
corrupt = false;
|
|
57
|
+
deps;
|
|
58
|
+
constructor(config) {
|
|
59
|
+
this.storePath = path.join(config.stateDir, 'apprenticeship', 'instances.json');
|
|
60
|
+
this.decisionLogPath =
|
|
61
|
+
config.decisionLogPath ?? path.join(config.stateDir, 'logs', 'apprenticeship-decisions.jsonl');
|
|
62
|
+
this.projectDir = config.projectDir;
|
|
63
|
+
this.deps = {
|
|
64
|
+
readHarvest: config.deps?.readHarvest ?? ((rel) => this.defaultReadHarvest(rel)),
|
|
65
|
+
validate: config.deps?.validate ?? validateRetroHarvest,
|
|
66
|
+
countInstanceLedgerEntries: config.deps?.countInstanceLedgerEntries ?? (() => 0),
|
|
67
|
+
detectorAuditExists: config.deps?.detectorAuditExists ?? (() => false),
|
|
68
|
+
};
|
|
69
|
+
this.store = this.loadStore();
|
|
70
|
+
}
|
|
71
|
+
/** Default harvest reader — resolves the confined relative path under projectDir. */
|
|
72
|
+
defaultReadHarvest(relPath) {
|
|
73
|
+
try {
|
|
74
|
+
const full = path.join(this.projectDir, relPath);
|
|
75
|
+
if (!fs.existsSync(full))
|
|
76
|
+
return null;
|
|
77
|
+
return fs.readFileSync(full, 'utf-8');
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// ── Persistence ────────────────────────────────────────────────────
|
|
84
|
+
loadStore() {
|
|
85
|
+
try {
|
|
86
|
+
if (fs.existsSync(this.storePath)) {
|
|
87
|
+
const raw = fs.readFileSync(this.storePath, 'utf-8');
|
|
88
|
+
const data = JSON.parse(raw);
|
|
89
|
+
if (data && data.version === 1 && Array.isArray(data.instances)) {
|
|
90
|
+
this.corrupt = false;
|
|
91
|
+
return data;
|
|
92
|
+
}
|
|
93
|
+
// Present but unparseable shape → fail closed (do NOT silently reset).
|
|
94
|
+
this.corrupt = true;
|
|
95
|
+
return { version: 1, instances: [], lastModified: new Date().toISOString() };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// A present-but-corrupt file fails closed; a truly-missing file is fresh.
|
|
100
|
+
if (fs.existsSync(this.storePath)) {
|
|
101
|
+
this.corrupt = true;
|
|
102
|
+
return { version: 1, instances: [], lastModified: new Date().toISOString() };
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
this.corrupt = false;
|
|
106
|
+
return { version: 1, instances: [], lastModified: new Date().toISOString() };
|
|
107
|
+
}
|
|
108
|
+
saveStore() {
|
|
109
|
+
this.store.lastModified = new Date().toISOString();
|
|
110
|
+
const dir = path.dirname(this.storePath);
|
|
111
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
112
|
+
const tmpPath = `${this.storePath}.${process.pid}.tmp`;
|
|
113
|
+
fs.writeFileSync(tmpPath, JSON.stringify(this.store, null, 2) + '\n');
|
|
114
|
+
fs.renameSync(tmpPath, this.storePath);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* The single in-process serialized mutator with optimistic `version` CAS.
|
|
118
|
+
* JS is single-threaded and `fn` is synchronous, so a straight read → apply
|
|
119
|
+
* → version++ → persist cannot interleave with another mutate() under the
|
|
120
|
+
* single-process model; the CAS guards against a same-tick stale read by
|
|
121
|
+
* re-reading the live record before commit. Returns the persisted snapshot.
|
|
122
|
+
*/
|
|
123
|
+
mutate(id, fn) {
|
|
124
|
+
const idx = this.store.instances.findIndex((i) => i.id === id);
|
|
125
|
+
if (idx === -1)
|
|
126
|
+
throw new Error(`ApprenticeshipProgram.mutate: unknown instance id ${id}`);
|
|
127
|
+
const current = this.store.instances[idx];
|
|
128
|
+
const observedVersion = current.version ?? 0;
|
|
129
|
+
const next = fn({ ...current });
|
|
130
|
+
// CAS re-read: under single-process this is belt-and-braces.
|
|
131
|
+
const latestIdx = this.store.instances.findIndex((i) => i.id === id);
|
|
132
|
+
if (latestIdx === -1)
|
|
133
|
+
throw new Error(`ApprenticeshipProgram.mutate: instance ${id} disappeared mid-apply`);
|
|
134
|
+
if ((this.store.instances[latestIdx].version ?? 0) !== observedVersion) {
|
|
135
|
+
throw new Error(`ApprenticeshipProgram.mutate: version drift on ${id} (CAS abort)`);
|
|
136
|
+
}
|
|
137
|
+
const committed = {
|
|
138
|
+
...next,
|
|
139
|
+
// requiredArtifacts is immutable after create — restore from the live record.
|
|
140
|
+
requiredArtifacts: current.requiredArtifacts,
|
|
141
|
+
version: observedVersion + 1,
|
|
142
|
+
updatedAt: new Date().toISOString(),
|
|
143
|
+
};
|
|
144
|
+
this.store.instances[latestIdx] = committed;
|
|
145
|
+
this.saveStore();
|
|
146
|
+
return committed;
|
|
147
|
+
}
|
|
148
|
+
// ── Read ───────────────────────────────────────────────────────────
|
|
149
|
+
list() {
|
|
150
|
+
return [...this.store.instances];
|
|
151
|
+
}
|
|
152
|
+
get(id) {
|
|
153
|
+
return this.store.instances.find((i) => i.id === id) ?? null;
|
|
154
|
+
}
|
|
155
|
+
/** True when the on-disk store was present but unparseable (gates fail closed). */
|
|
156
|
+
isCorrupt() {
|
|
157
|
+
return this.corrupt;
|
|
158
|
+
}
|
|
159
|
+
// ── Create ─────────────────────────────────────────────────────────
|
|
160
|
+
/**
|
|
161
|
+
* Create an instance. Charset-clamps id/overseer/mentor/mentee/framework to
|
|
162
|
+
* ^[a-z0-9-]+$, rejects a duplicate id, computes harvestFrom=mentor /
|
|
163
|
+
* harvestTo=mentee. requiredArtifacts defaults to all-required.
|
|
164
|
+
*/
|
|
165
|
+
createInstance(input) {
|
|
166
|
+
if (this.corrupt) {
|
|
167
|
+
throw new Error('ApprenticeshipProgram: store is corrupt — refusing to create (fail closed)');
|
|
168
|
+
}
|
|
169
|
+
const overseer = input.overseer ?? '';
|
|
170
|
+
const fields = {
|
|
171
|
+
id: input.id,
|
|
172
|
+
mentor: input.mentor,
|
|
173
|
+
mentee: input.mentee,
|
|
174
|
+
framework: input.framework,
|
|
175
|
+
};
|
|
176
|
+
// overseer is optional (apprenticeship has none); clamp only when present.
|
|
177
|
+
if (overseer)
|
|
178
|
+
fields.overseer = overseer;
|
|
179
|
+
for (const [k, v] of Object.entries(fields)) {
|
|
180
|
+
if (typeof v !== 'string' || !CHARSET_RE.test(v)) {
|
|
181
|
+
throw new Error(`ApprenticeshipProgram.createInstance: ${k}="${v}" must match ^[a-z0-9-]+$`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (input.instanceType !== 'apprenticeship' && input.instanceType !== 'mentorship') {
|
|
185
|
+
throw new Error(`ApprenticeshipProgram.createInstance: invalid instanceType "${input.instanceType}"`);
|
|
186
|
+
}
|
|
187
|
+
if (this.store.instances.some((i) => i.id === input.id)) {
|
|
188
|
+
throw new Error(`ApprenticeshipProgram.createInstance: duplicate id "${input.id}"`);
|
|
189
|
+
}
|
|
190
|
+
const now = new Date().toISOString();
|
|
191
|
+
const harvestFrom = input.mentor; // a harvest is named for the mentoring edge (§3.1)
|
|
192
|
+
const harvestTo = input.mentee;
|
|
193
|
+
// Record the canonical path for humans only — NEVER the resolution source.
|
|
194
|
+
let harvestRef = null;
|
|
195
|
+
try {
|
|
196
|
+
harvestRef = safeArtifactPath(harvestFrom, harvestTo, input.instanceType);
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
harvestRef = null;
|
|
200
|
+
}
|
|
201
|
+
const instance = {
|
|
202
|
+
id: input.id,
|
|
203
|
+
instanceType: input.instanceType,
|
|
204
|
+
overseer,
|
|
205
|
+
mentor: input.mentor,
|
|
206
|
+
mentee: input.mentee,
|
|
207
|
+
framework: input.framework,
|
|
208
|
+
status: 'pending',
|
|
209
|
+
priorInstanceId: input.priorInstanceId ?? null,
|
|
210
|
+
requiredArtifacts: {
|
|
211
|
+
retroHarvest: input.requiredArtifacts?.retroHarvest ?? true,
|
|
212
|
+
ledgerEntries: input.requiredArtifacts?.ledgerEntries ?? true,
|
|
213
|
+
detectorAudit: input.requiredArtifacts?.detectorAudit ?? true,
|
|
214
|
+
},
|
|
215
|
+
programNeeds: input.programNeeds ?? [],
|
|
216
|
+
harvestFrom,
|
|
217
|
+
harvestTo,
|
|
218
|
+
harvestRef,
|
|
219
|
+
version: 0,
|
|
220
|
+
createdAt: now,
|
|
221
|
+
updatedAt: now,
|
|
222
|
+
};
|
|
223
|
+
this.store.instances.push(instance);
|
|
224
|
+
this.saveStore();
|
|
225
|
+
return instance;
|
|
226
|
+
}
|
|
227
|
+
// ── Gates (pure; truth re-derived from injected deps) ───────────────
|
|
228
|
+
/**
|
|
229
|
+
* The retro-gate (§3.3). priorInstanceId === null → the bootstrap seed (the
|
|
230
|
+
* Echo→Codey artifact at its canonical path) must exist + validate. Else the
|
|
231
|
+
* prior instance must be status:'complete' AND its canonical harvest must
|
|
232
|
+
* exist + validate. partial-accepted passes ONLY with acceptance metadata
|
|
233
|
+
* (acceptedBy + acceptedAt); complete always passes.
|
|
234
|
+
*
|
|
235
|
+
* The path is recomputed via safeArtifactPath(harvestFrom, harvestTo,
|
|
236
|
+
* instanceType) — never a stored harvestRef.
|
|
237
|
+
*/
|
|
238
|
+
evaluateStartGate(instance) {
|
|
239
|
+
if (this.corrupt) {
|
|
240
|
+
return { allow: false, reason: 'instance store is corrupt — fail closed' };
|
|
241
|
+
}
|
|
242
|
+
let priorInstance = null;
|
|
243
|
+
let from;
|
|
244
|
+
let to;
|
|
245
|
+
let type;
|
|
246
|
+
let priorHarvestExists;
|
|
247
|
+
if (instance.priorInstanceId === null) {
|
|
248
|
+
// Bootstrap: validate THIS instance's own canonical harvest (the seed).
|
|
249
|
+
from = instance.harvestFrom;
|
|
250
|
+
to = instance.harvestTo;
|
|
251
|
+
type = instance.instanceType;
|
|
252
|
+
priorHarvestExists = false;
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
priorInstance = this.get(instance.priorInstanceId);
|
|
256
|
+
if (!priorInstance) {
|
|
257
|
+
return { allow: false, reason: `prior instance "${instance.priorInstanceId}" not found` };
|
|
258
|
+
}
|
|
259
|
+
if (priorInstance.status !== 'complete') {
|
|
260
|
+
return {
|
|
261
|
+
allow: false,
|
|
262
|
+
reason: `prior instance "${priorInstance.id}" is "${priorInstance.status}", must be "complete"`,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
from = priorInstance.harvestFrom;
|
|
266
|
+
to = priorInstance.harvestTo;
|
|
267
|
+
type = priorInstance.instanceType;
|
|
268
|
+
priorHarvestExists = true;
|
|
269
|
+
}
|
|
270
|
+
// Recompute the confined path (NEVER the stored harvestRef).
|
|
271
|
+
let relPath;
|
|
272
|
+
try {
|
|
273
|
+
relPath = safeArtifactPath(from, to, type);
|
|
274
|
+
}
|
|
275
|
+
catch (e) {
|
|
276
|
+
return { allow: false, reason: `cannot resolve canonical harvest path: ${e.message}` };
|
|
277
|
+
}
|
|
278
|
+
const text = this.deps.readHarvest(relPath);
|
|
279
|
+
if (text === null) {
|
|
280
|
+
return { allow: false, reason: `retro-harvest missing at canonical path ${relPath}` };
|
|
281
|
+
}
|
|
282
|
+
const result = this.deps.validate(text, { priorHarvestExists });
|
|
283
|
+
if (!result.valid) {
|
|
284
|
+
return { allow: false, reason: `retro-harvest at ${relPath} is invalid: ${result.errors.join('; ')}` };
|
|
285
|
+
}
|
|
286
|
+
// partial-accepted requires acceptance metadata (acceptedBy + acceptedAt).
|
|
287
|
+
let fm;
|
|
288
|
+
try {
|
|
289
|
+
fm = parseArtifact(text).frontmatter;
|
|
290
|
+
}
|
|
291
|
+
catch (e) {
|
|
292
|
+
return { allow: false, reason: `cannot parse harvest frontmatter: ${e.message}` };
|
|
293
|
+
}
|
|
294
|
+
const completeness = fm.completeness;
|
|
295
|
+
if (completeness === 'partial-accepted') {
|
|
296
|
+
const acceptedBy = fm.acceptedBy;
|
|
297
|
+
const acceptedAt = fm.acceptedAt;
|
|
298
|
+
if (!acceptedBy || !acceptedAt) {
|
|
299
|
+
return {
|
|
300
|
+
allow: false,
|
|
301
|
+
reason: `partial harvest at ${relPath} awaiting acceptance (acceptedBy + acceptedAt required)`,
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return {
|
|
306
|
+
allow: true,
|
|
307
|
+
reason: instance.priorInstanceId === null
|
|
308
|
+
? `bootstrap seed ${relPath} present + valid (completeness=${String(completeness)})`
|
|
309
|
+
: `prior instance "${priorInstance.id}" complete; harvest ${relPath} present + valid`,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* The doc-as-required-artifact gate (§3.3). Each requiredArtifacts flag the
|
|
314
|
+
* instance DECLARES required is checked against LIVE state via injected deps —
|
|
315
|
+
* harvestExists+validates, an instance-scoped ledger count ≥1, detectorAudit
|
|
316
|
+
* present. A stored requiredArtifacts:true is NEVER treated as evidence of
|
|
317
|
+
* presence.
|
|
318
|
+
*/
|
|
319
|
+
evaluateCompletionGate(instance) {
|
|
320
|
+
if (this.corrupt) {
|
|
321
|
+
return { allow: false, reason: 'instance store is corrupt — fail closed', missing: ['store-corrupt'] };
|
|
322
|
+
}
|
|
323
|
+
const missing = [];
|
|
324
|
+
if (instance.requiredArtifacts.retroHarvest) {
|
|
325
|
+
// This instance's OWN harvest (mentor→mentee edge), at its canonical path.
|
|
326
|
+
let relPath = null;
|
|
327
|
+
try {
|
|
328
|
+
relPath = safeArtifactPath(instance.harvestFrom, instance.harvestTo, instance.instanceType);
|
|
329
|
+
}
|
|
330
|
+
catch {
|
|
331
|
+
relPath = null;
|
|
332
|
+
}
|
|
333
|
+
const text = relPath ? this.deps.readHarvest(relPath) : null;
|
|
334
|
+
if (text === null) {
|
|
335
|
+
missing.push('retroHarvest:absent');
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
const result = this.deps.validate(text, { priorHarvestExists: instance.priorInstanceId !== null });
|
|
339
|
+
if (!result.valid)
|
|
340
|
+
missing.push('retroHarvest:invalid');
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
if (instance.requiredArtifacts.ledgerEntries) {
|
|
344
|
+
const n = this.deps.countInstanceLedgerEntries(instance);
|
|
345
|
+
if (!(n >= 1))
|
|
346
|
+
missing.push('ledgerEntries:none');
|
|
347
|
+
}
|
|
348
|
+
if (instance.requiredArtifacts.detectorAudit) {
|
|
349
|
+
if (!this.deps.detectorAuditExists(instance))
|
|
350
|
+
missing.push('detectorAudit:absent');
|
|
351
|
+
}
|
|
352
|
+
if (missing.length > 0) {
|
|
353
|
+
return {
|
|
354
|
+
allow: false,
|
|
355
|
+
reason: `completion blocked — missing live artifacts: ${missing.join(', ')}`,
|
|
356
|
+
missing,
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
return { allow: true, reason: 'all declared-required artifacts verified present from live state', missing: [] };
|
|
360
|
+
}
|
|
361
|
+
// ── Status transitions (the gates are not advisory) ─────────────────
|
|
362
|
+
/**
|
|
363
|
+
* The ONLY way status changes (§3.4). pending→active runs evaluateStartGate
|
|
364
|
+
* and refuses on !allow; active→complete runs evaluateCompletionGate;
|
|
365
|
+
* active→blocked / blocked→active (re-gate) allowed; complete is terminal.
|
|
366
|
+
* Any transition not in the table is rejected with a reason. Every gate
|
|
367
|
+
* verdict is appended to the decision audit.
|
|
368
|
+
*/
|
|
369
|
+
transition(id, to) {
|
|
370
|
+
if (this.corrupt) {
|
|
371
|
+
return { ok: false, reason: 'instance store is corrupt — fail closed' };
|
|
372
|
+
}
|
|
373
|
+
const instance = this.get(id);
|
|
374
|
+
if (!instance)
|
|
375
|
+
return { ok: false, reason: `instance "${id}" not found` };
|
|
376
|
+
const allowed = TRANSITIONS[instance.status] ?? [];
|
|
377
|
+
if (!allowed.includes(to)) {
|
|
378
|
+
return {
|
|
379
|
+
ok: false,
|
|
380
|
+
reason: `illegal transition ${instance.status}→${to} (allowed: ${allowed.join(', ') || 'none — terminal'})`,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
// Gate the guarded transitions.
|
|
384
|
+
if (instance.status === 'pending' && to === 'active') {
|
|
385
|
+
const verdict = this.evaluateStartGate(instance);
|
|
386
|
+
this.recordDecision({ gate: 'start', instanceId: id, allow: verdict.allow, reason: verdict.reason });
|
|
387
|
+
if (!verdict.allow)
|
|
388
|
+
return { ok: false, reason: `start gate refused: ${verdict.reason}` };
|
|
389
|
+
}
|
|
390
|
+
if (instance.status === 'blocked' && to === 'active') {
|
|
391
|
+
// Re-gate on resume from blocked.
|
|
392
|
+
const verdict = this.evaluateStartGate(instance);
|
|
393
|
+
this.recordDecision({ gate: 'start', instanceId: id, allow: verdict.allow, reason: verdict.reason });
|
|
394
|
+
if (!verdict.allow)
|
|
395
|
+
return { ok: false, reason: `start gate refused (re-gate): ${verdict.reason}` };
|
|
396
|
+
}
|
|
397
|
+
if (instance.status === 'active' && to === 'complete') {
|
|
398
|
+
const verdict = this.evaluateCompletionGate(instance);
|
|
399
|
+
this.recordDecision({
|
|
400
|
+
gate: 'completion',
|
|
401
|
+
instanceId: id,
|
|
402
|
+
allow: verdict.allow,
|
|
403
|
+
reason: verdict.reason,
|
|
404
|
+
missing: verdict.missing,
|
|
405
|
+
});
|
|
406
|
+
if (!verdict.allow)
|
|
407
|
+
return { ok: false, reason: `completion gate refused: ${verdict.reason}` };
|
|
408
|
+
}
|
|
409
|
+
const updated = this.mutate(id, (i) => ({ ...i, status: to }));
|
|
410
|
+
return { ok: true, reason: `transitioned ${instance.status}→${to}`, instance: updated };
|
|
411
|
+
}
|
|
412
|
+
// ── Decision audit (§3.6) ───────────────────────────────────────────
|
|
413
|
+
recordDecision(entry) {
|
|
414
|
+
try {
|
|
415
|
+
const dir = path.dirname(this.decisionLogPath);
|
|
416
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
417
|
+
const line = JSON.stringify({
|
|
418
|
+
ts: new Date().toISOString(),
|
|
419
|
+
gate: entry.gate,
|
|
420
|
+
instanceId: entry.instanceId,
|
|
421
|
+
allow: entry.allow,
|
|
422
|
+
reason: entry.reason,
|
|
423
|
+
...(entry.missing && entry.missing.length ? { missing: entry.missing } : {}),
|
|
424
|
+
}) + '\n';
|
|
425
|
+
fs.appendFileSync(this.decisionLogPath, line);
|
|
426
|
+
}
|
|
427
|
+
catch {
|
|
428
|
+
// @silent-fallback-ok — the audit is observability; a write failure must
|
|
429
|
+
// not block the (already-decided) transition.
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
//# sourceMappingURL=ApprenticeshipProgram.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApprenticeshipProgram.js","sourceRoot":"","sources":["../../src/core/ApprenticeshipProgram.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PostUpdateMigrator.d.ts","sourceRoot":"","sources":["../../src/core/PostUpdateMigrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAsCH,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAC3B,MAAM,yBAAyB,CAAC;AAIjC,MAAM,WAAW,eAAe;IAC9B,wBAAwB;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,kCAAkC;IAClC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,2CAA2C;IAC3C,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAiB;IAC/B;;;;;;OAMG;IACH,OAAO,CAAC,UAAU,CAAiC;gBAEvC,MAAM,EAAE,cAAc;IAIlC;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,oBAAoB;IAoB5B;;;;;;;;;;;OAWG;IACH,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAItC;;;;;;OAMG;IACG,eAAe,CACnB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,qBAAqB,CAAC;IAIjC,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,kBAAkB;IAO1B;;;;OAIG;IACH,OAAO,CAAC,YAAY;IASpB;;;OAGG;IACH,OAAO,IAAI,eAAe;IA+C1B;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,0BAA0B;
|
|
1
|
+
{"version":3,"file":"PostUpdateMigrator.d.ts","sourceRoot":"","sources":["../../src/core/PostUpdateMigrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -222,14 +222,18 @@ export class PostUpdateMigrator {
|
|
|
222
222
|
return;
|
|
223
223
|
}
|
|
224
224
|
// Marker strings the current boot wrapper must contain to be considered
|
|
225
|
-
// up-to-date.
|
|
225
|
+
// up-to-date. All are required:
|
|
226
226
|
// - 'cannot load better-sqlite3 (ABI drift)' — the ABI-check self-heal branch.
|
|
227
227
|
// - 'version-managed node candidates' — the asdf/nvm `which node` candidate
|
|
228
228
|
// discovery (instar-codey node-25/ABI-141 deadlock fix). An install that has
|
|
229
229
|
// the ABI check but NOT this marker (e.g. instar-codey) self-heals FORWARD to
|
|
230
230
|
// the wrong ABI and cannot recover — it must be regenerated.
|
|
231
|
+
// - 'npm_config_scripts_prepend_node_path' — the reinstall now puts the resolved
|
|
232
|
+
// node dir on PATH so native postinstalls (sharp) don't die with "command not
|
|
233
|
+
// found" under a launchd-spawned boot child. Wrappers lacking it must regenerate.
|
|
231
234
|
if (content.includes('cannot load better-sqlite3 (ABI drift)') &&
|
|
232
|
-
content.includes('version-managed node candidates')
|
|
235
|
+
content.includes('version-managed node candidates') &&
|
|
236
|
+
content.includes('npm_config_scripts_prepend_node_path')) {
|
|
233
237
|
result.skipped.push('boot-wrapper ABI-check: already current');
|
|
234
238
|
return;
|
|
235
239
|
}
|
|
@@ -2509,6 +2513,25 @@ Rule: I do not state that work landed inside another agent's state unless I have
|
|
|
2509
2513
|
patched = true;
|
|
2510
2514
|
result.upgraded.push('CLAUDE.md: added Cross-Agent Communication Discipline (anti-confabulation) section');
|
|
2511
2515
|
}
|
|
2516
|
+
// Apprenticeship Program (Step 1, APPRENTICESHIP-STEP1-PROGRAM-SCAFFOLD-SPEC.md).
|
|
2517
|
+
// Existing agents need to know the program registry + lifecycle gates exist —
|
|
2518
|
+
// an agent that doesn't know about a capability effectively doesn't have it.
|
|
2519
|
+
// Content-sniffed on a distinctive marker for idempotency (the same heading the
|
|
2520
|
+
// template emits, so a freshly-initialized agent is never double-patched).
|
|
2521
|
+
if (!content.includes('**Apprenticeship Program**')) {
|
|
2522
|
+
const apprenticeshipSection = `
|
|
2523
|
+
### Apprenticeship Program
|
|
2524
|
+
|
|
2525
|
+
The standing program that each apprenticeship/mentorship instance plugs into (e.g. Echo mentors Codey, then Codey mentors Gemini while Echo oversees). **Apprenticeship Program** instances are projects with a locked role triple (overseer / mentor / mentee), a framework, and a required-artifact checklist. Two lifecycle GATES make "review before you start / capture before you close" unskippable at the state-mutating transition: the retro-gate refuses \`pending→active\` unless the prior instance's retro-harvest exists at its canonical confined path AND passes the Step 0 validator (the first instance is seeded by the Echo→Codey bootstrap harvest); the doc-as-required-artifact gate refuses \`active→complete\` until the declared-required artifacts are verified present FROM LIVE STATE (never a stored flag). The gates are structural preconditions on objective artifacts — quality stays with the overseer (the mind); every verdict is audited to \`logs/apprenticeship-decisions.jsonl\`.
|
|
2526
|
+
- List / inspect: \`curl -H "Authorization: Bearer $AUTH" http://localhost:${port}/apprenticeship/instances\` · \`GET /apprenticeship/instances/:id\`
|
|
2527
|
+
- Create: \`POST /apprenticeship/instances\` \`{"id":"codey-to-gemini","instanceType":"mentorship","overseer":"echo","mentor":"codey","mentee":"gemini","framework":"gemini-cli","priorInstanceId":null}\` (id/overseer/mentor/mentee/framework charset-clamped to \`^[a-z0-9-]+$\`; dup id rejected; harvestFrom=mentor / harvestTo=mentee).
|
|
2528
|
+
- Transition status (the ONLY way it changes — runs the gate): \`POST /apprenticeship/instances/:id/transition\` \`{"to":"active"}\` (refused + 409 on a failed gate or illegal transition; \`complete\` is terminal). Preview without mutating: \`.../can-start\` · \`.../can-complete\`.
|
|
2529
|
+
- **When to use** (PROACTIVE): when starting or closing a mentorship/apprenticeship instance, drive it through the registry + transitions so the retro-harvest is reviewed before the next instance starts and the lessons are captured before this one closes — never track the lifecycle by memory.
|
|
2530
|
+
`;
|
|
2531
|
+
content += '\n' + apprenticeshipSection;
|
|
2532
|
+
patched = true;
|
|
2533
|
+
result.upgraded.push('CLAUDE.md: added Apprenticeship Program section');
|
|
2534
|
+
}
|
|
2512
2535
|
// Close the Loop (Untracked = Abandoned) — STANDARDS-REGISTRY amendment
|
|
2513
2536
|
// ratified with Justin 2026-05-31. The "nothing slips through the cracks"
|
|
2514
2537
|
// principle was made a constitutional standard; existing agents need the
|