@pmelab/gtd 24.3.0 → 24.4.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/.claude-plugin/plugin.json +1 -1
- package/README.md +15 -4
- package/dist/chunks/{reserved-DJwU5C4z.mjs → reserved-B9pG93Fc.mjs} +52 -12
- package/dist/chunks/{steering-D-PvRC5W.mjs → steering-DVILanVf.mjs} +16 -5
- package/dist/flows.mjs +9 -1
- package/dist/gtd.bundle.mjs +779 -812
- package/dist/steering.mjs +2 -2
- package/dist/testkit.mjs +663 -158
- package/dist/workflow-kit.mjs +9 -7
- package/dist/workflows/feature.mjs +152 -35
- package/dist/workflows/fix.mjs +2 -2
- package/dist/workflows/review.mjs +1 -1
- package/dist/workflows.mjs +223 -54
- package/package.json +1 -1
- package/src/cli/Program.test.ts +3 -8
- package/src/cli/Program.ts +1 -8
- package/src/edge/Edge.test.ts +5 -2
- package/src/edge/Edge.ts +3 -4
- package/src/emit/index.ts +1 -0
- package/src/flows/scripts.ts +6 -0
- package/src/platform/Git.test.ts +6 -9
- package/src/steering/FORMATS.md +1 -1
- package/src/steering/SteeringFormat.test.ts +9 -1
- package/src/steering/SteeringFormat.ts +7 -0
- package/src/steering/contract.test.ts +3 -0
- package/src/steering/index.ts +1 -0
- package/src/steering/review.test.ts +30 -0
- package/src/steering/review.ts +8 -2
- package/src/testkit/EmittedScriptRecognizer.test.ts +29 -30
- package/src/testkit/EmittedScriptRecognizer.ts +148 -51
- package/src/testkit/EmittedScripts.test.ts +166 -0
- package/src/testkit/FlowScripts.test.ts +242 -0
- package/src/testkit/FlowScripts.ts +326 -0
- package/src/testkit/GitTiers.ts +140 -49
- package/src/testkit/InMemRepo.ts +35 -2
- package/src/testkit/Layers.ts +10 -2
- package/src/testkit/TestRepo.ts +4 -1
- package/src/testkit/index.ts +1 -1
- package/src/workflow/discovery.test.ts +147 -0
- package/src/workflow/discovery.ts +5 -0
- package/src/workflow/fingerprint.test.ts +20 -4
- package/src/workflow/fingerprint.ts +8 -9
- package/src/workflow/index.ts +1 -6
- package/src/workflow/load.test.ts +5 -19
- package/src/workflow/load.ts +94 -10
- package/src/workflow-kit/review.test.ts +84 -0
- package/src/workflow-kit/review.ts +9 -6
- package/src/workflows/feature/review.test.ts +238 -12
- package/src/workflows/feature/review.ts +172 -31
- package/src/workflows/feature/steps.test.ts +12 -0
- package/src/workflows/feature/steps.ts +8 -1
- package/src/workflows/shared/access.test.ts +4 -2
- package/src/workflows/shared/access.ts +1 -0
- package/src/workflows/shared/options.test.ts +8 -0
- package/src/workflows/shared/options.ts +1 -0
- package/src/workflows/shared/steps.ts +2 -0
- package/src/workflows/shared/tail.ts +3 -11
- package/src/workflows/shared/text.test.ts +106 -0
- package/src/workflows/shared/text.ts +57 -1
- package/src/workflows/shared/vars.ts +1 -0
package/dist/workflow-kit.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { changes, changesSince, hasThreadFor, head, read, refuse, requireReplies, requireThreadsClosed, scope } from "./flows.mjs";
|
|
2
|
-
import { c as stripCodeThreads, d as reviewNotes, f as reviewRisks } from "./chunks/steering-
|
|
2
|
+
import { c as stripCodeThreads, d as reviewNotes, f as reviewRisks } from "./chunks/steering-DVILanVf.mjs";
|
|
3
3
|
//#region src/workflow-kit/health.ts
|
|
4
4
|
/** Hand a red suite that repeated attempts could not fix to a person, until `limit` rounds are spent. */
|
|
5
5
|
const escalation = async (count, steps) => {
|
|
@@ -196,16 +196,17 @@ const converse = async (p, base, collectedBefore) => {
|
|
|
196
196
|
if (!hasThreadFor("human", p.file)) return collectedAt;
|
|
197
197
|
}
|
|
198
198
|
};
|
|
199
|
-
/** Judge every note, then run each verdict's route: answers, then nit fixes, then the edits' lap. */
|
|
199
|
+
/** Judge every note, then run each verdict's route: answers, then nit fixes, then deferrals, then the edits' lap. */
|
|
200
200
|
const routeNotes = async (p, notes, r) => {
|
|
201
201
|
const verdicts = await p.triage(notes);
|
|
202
202
|
const of = (v) => notes.filter((n) => (verdicts.get(n.id) ?? "edit") === v);
|
|
203
|
-
const [edits, questions, nits] = [
|
|
203
|
+
const [edits, questions, nits, deferred] = [
|
|
204
204
|
of("edit"),
|
|
205
205
|
of("question"),
|
|
206
|
-
of("nit")
|
|
206
|
+
of("nit"),
|
|
207
|
+
of("defer")
|
|
207
208
|
];
|
|
208
|
-
if (edits.length + questions.length + nits.length === 0) return r.unfolded();
|
|
209
|
+
if (edits.length + questions.length + nits.length + deferred.length === 0) return r.unfolded();
|
|
209
210
|
let answeredAt;
|
|
210
211
|
if (questions.length > 0) {
|
|
211
212
|
await p.answerQuestions(questions);
|
|
@@ -215,6 +216,7 @@ const routeNotes = async (p, notes, r) => {
|
|
|
215
216
|
await p.fixNits(nits);
|
|
216
217
|
await p.keepGreen();
|
|
217
218
|
}
|
|
219
|
+
if (deferred.length > 0) await p.defer(deferred);
|
|
218
220
|
if (edits.length > 0) {
|
|
219
221
|
await r.close();
|
|
220
222
|
return r.outcome(await collect(p, p.captures.editNotes(r.round, edits, answeredAt)));
|
|
@@ -228,7 +230,7 @@ const routeNotes = async (p, notes, r) => {
|
|
|
228
230
|
}
|
|
229
231
|
return {
|
|
230
232
|
next: "await",
|
|
231
|
-
reviewed: answeredAt
|
|
233
|
+
reviewed: answeredAt ?? r.round
|
|
232
234
|
};
|
|
233
235
|
};
|
|
234
236
|
/** A code edit, not a thread-only change: lines that only add, answer or remove code threads don't count. */
|
|
@@ -349,4 +351,4 @@ const reviewToHandOff = async (base, p) => {
|
|
|
349
351
|
}
|
|
350
352
|
};
|
|
351
353
|
//#endregion
|
|
352
|
-
export { driftedScenarios, escalation, fixFindings, freezeScenarios, gate, healthy, holdWording, lensScopes, lensesOf, qualityLap, review, reviewToHandOff, scenarioText, untilSettled, wordingDrift };
|
|
354
|
+
export { driftedScenarios, escalation, fixFindings, freezeScenarios, gate, healthy, holdWording, lensScopes, lensesOf, qualityLap, review, reviewToHandOff, routeNotes, scenarioText, untilSettled, wordingDrift };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { answered, changes, changesSince, glob, hasThreadFor, head, human, judge, numeric, read, refuse, removeScript, requireAnswers, requireProgress, requireReplies, requireRevert, requireThreadsClosed, restoreScript, revertScript, run, scope, start, vars } from "../flows.mjs";
|
|
2
2
|
import { freezeScenarios, review as review$1 } from "../workflow-kit.mjs";
|
|
3
|
-
import { $ as
|
|
3
|
+
import { $ as startGateBlockedMessage, A as architectureAuthorPrompt, B as designGateAnswerMessage, C as fixCheck, D as reviewing, E as reviewMissing, F as buildReviewCollectingPrompt, G as idleMessage, H as designTriagePrompt, I as buildReviewFixNitsPrompt, J as reviewEditNotesCapture, K as packagesItemBuildingPrompt, L as buildReviewTriageMessage, M as architectureGateAnswerMessage, N as buildReviewAnswerQuestionsPrompt, O as agentWithSkills, P as buildReviewAwaitAfterDeferMessage, Q as reviewerSystem, R as builderSystem, S as coder, T as planner, V as designSystem, Y as reviewEditsCapture, Z as reviewNotesCapture, _ as ARCHITECTURE, b as REVIEW, c as refusePendingHandOff, d as shipped, et as unwindFailedMessage, f as defaults, g as healthy, h as gate, i as skills, j as architectureDecomposePrompt, k as architectSystem, l as tail, n as summary, o as closeReview, p as envDefaults, q as packagesItemFixSuitePrompt, r as access, t as steering, tt as unwindFailure, u as guarded, v as FEEDBACK, w as fixRisks, x as awaitReview, y as REQUIREMENTS, z as deferNotesScript } from "../chunks/reserved-B9pG93Fc.mjs";
|
|
4
4
|
//#region src/workflows/feature/steps.ts
|
|
5
5
|
/** Turn the sketch since `base` into `.gtd/REQUIREMENTS.md`. */
|
|
6
6
|
const triage = (base) => agentWithSkills("triage", designTriagePrompt(base), {
|
|
@@ -71,6 +71,11 @@ const collecting = (capture) => agentWithSkills("review.collecting", buildReview
|
|
|
71
71
|
system: reviewerSystem(),
|
|
72
72
|
allowEmpty: true
|
|
73
73
|
});
|
|
74
|
+
/** `build.review.defer`: append `notes` to `.gtd/TODO.md` as one section; the step's landing is the commit. */
|
|
75
|
+
const deferNotes = (notes, round) => run("review.defer", deferNotesScript(notes, round), {
|
|
76
|
+
label: "Deferring could-notes to TODO.md",
|
|
77
|
+
file: ".gtd/TODO.md"
|
|
78
|
+
});
|
|
74
79
|
//#endregion
|
|
75
80
|
//#region src/workflows/feature/packages.ts
|
|
76
81
|
/** Package 0: the e2e scenarios, written red. */
|
|
@@ -194,23 +199,106 @@ const verdictQuestion = (note) => ({
|
|
|
194
199
|
instructions: `Classify the human's note on review item "${note.anchor}" (in .gtd/REVIEW.md). Its evidence holds the anchor, the reviewer's text and the human's text.`,
|
|
195
200
|
criteria: "edit: a request to change behaviour, design or scope — anything needing a plan, or any note you are unsure about. question: asks something and wants an answer, with no change requested. nit: a small, local, unambiguous fix (naming, typo, formatting, comment wording) needing no re-plan. praise: an approving remark with nothing to do."
|
|
196
201
|
});
|
|
202
|
+
const SEVERITY_ANSWERS = {
|
|
203
|
+
security: ["yes", "no"],
|
|
204
|
+
reversibility: ["one-way", "two-way"],
|
|
205
|
+
blastRadius: [
|
|
206
|
+
"local",
|
|
207
|
+
"module",
|
|
208
|
+
"contract"
|
|
209
|
+
],
|
|
210
|
+
newConcept: ["yes", "no"]
|
|
211
|
+
};
|
|
212
|
+
/**
|
|
213
|
+
* Deferring is the risky direction: anything unanswered, unrecognised, cut or
|
|
214
|
+
* below `minP` is `critical`, never `could`.
|
|
215
|
+
*/
|
|
216
|
+
const severityOf = (note, judgment, minP) => {
|
|
217
|
+
const ans = (q) => judgment.answers[`${note.id}.${q}`];
|
|
218
|
+
const a = (q) => ans(q)?.answer;
|
|
219
|
+
const rank = () => a("reversibility") === "one-way" ? 0 : a("newConcept") === "yes" ? 1 : 2;
|
|
220
|
+
if (note.forced) return {
|
|
221
|
+
tier: "critical",
|
|
222
|
+
reason: "critical: forced by `!`",
|
|
223
|
+
rank: 2
|
|
224
|
+
};
|
|
225
|
+
if (judgment.truncated.includes(note.id) || Object.entries(SEVERITY_ANSWERS).some(([q, allowed]) => !allowed.includes(a(q) ?? "") || !((ans(q)?.p ?? NaN) >= minP))) return {
|
|
226
|
+
tier: "critical",
|
|
227
|
+
reason: "critical: judge unsure",
|
|
228
|
+
rank: 2
|
|
229
|
+
};
|
|
230
|
+
const critical = [...a("security") === "yes" ? ["security"] : [], ...a("reversibility") === "one-way" ? ["one-way door"] : []];
|
|
231
|
+
if (critical.length > 0) return {
|
|
232
|
+
tier: "critical",
|
|
233
|
+
reason: `critical: ${critical.join(", ")}`,
|
|
234
|
+
rank: rank()
|
|
235
|
+
};
|
|
236
|
+
const should = [...a("blastRadius") === "contract" ? ["contract"] : [], ...a("newConcept") === "yes" ? ["new concept"] : []];
|
|
237
|
+
if (should.length > 0) return {
|
|
238
|
+
tier: "should",
|
|
239
|
+
reason: `should: ${should.join(", ")}`,
|
|
240
|
+
rank: rank()
|
|
241
|
+
};
|
|
242
|
+
return {
|
|
243
|
+
tier: "could",
|
|
244
|
+
reason: "could",
|
|
245
|
+
rank: 2
|
|
246
|
+
};
|
|
247
|
+
};
|
|
248
|
+
const severityQuestions = (note) => [
|
|
249
|
+
{
|
|
250
|
+
id: `${note.id}.security`,
|
|
251
|
+
primitive: "noul",
|
|
252
|
+
instructions: `Does the change the human asks for in note "${note.id}" (on "${note.anchor}") touch security — authentication, authorisation, secrets, untrusted input or data exposure?`,
|
|
253
|
+
criteria: "yes: it changes or could weaken a security property. no: it does not."
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
id: `${note.id}.reversibility`,
|
|
257
|
+
primitive: "choice",
|
|
258
|
+
instructions: `Once the change in note "${note.id}" ships, can it be undone without breaking anyone who already depends on it?`,
|
|
259
|
+
criteria: "one-way: a published API, file format, persisted data, protocol or other contract that cannot be taken back. two-way: can be reverted freely."
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
id: `${note.id}.blastRadius`,
|
|
263
|
+
primitive: "choice",
|
|
264
|
+
instructions: `How far does the change in note "${note.id}" reach?`,
|
|
265
|
+
criteria: "local: one function or file. module: a whole module or several files. contract: a public interface other code or users depend on."
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
id: `${note.id}.newConcept`,
|
|
269
|
+
primitive: "noul",
|
|
270
|
+
instructions: `Does the change in note "${note.id}" introduce a concept new to this codebase — a new abstraction, entity or term? Judge from the evidence, never a glossary; reusing or extending an existing concept is not new.`,
|
|
271
|
+
criteria: "yes: a genuinely new concept. no: reuses or extends an existing one."
|
|
272
|
+
}
|
|
273
|
+
];
|
|
197
274
|
/**
|
|
198
|
-
* One judge rest
|
|
275
|
+
* One judge rest: a verdict per unforced note (a forced note is asked
|
|
276
|
+
* nothing) plus four severity answers. Dismissing a note is the risky
|
|
199
277
|
* direction, so only a confident non-`edit` verdict on uncut evidence counts;
|
|
200
|
-
* a cut, unanswered or below-floor note is an `edit
|
|
201
|
-
*
|
|
278
|
+
* a cut, unanswered or below-floor note is an `edit`. Severity answers on a
|
|
279
|
+
* non-`edit` note are ignored. A confident `could` edit becomes `defer`.
|
|
202
280
|
*/
|
|
203
|
-
const triage$1 = async (notes) => {
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
281
|
+
const triage$1 = (severities) => async (notes) => {
|
|
282
|
+
const asked = notes.filter((n) => !n.forced);
|
|
283
|
+
const judgment = asked.length === 0 ? {
|
|
284
|
+
answers: {},
|
|
285
|
+
truncated: []
|
|
286
|
+
} : await judge("review.triage", {
|
|
287
|
+
questions: asked.flatMap((n) => [verdictQuestion(n), ...severityQuestions(n)]),
|
|
288
|
+
evidence: Object.fromEntries(asked.map((n) => [n.id, `Anchor: ${n.anchor}\nReviewer's text: ${n.before}\nHuman's text: ${n.text}`])),
|
|
207
289
|
message: buildReviewTriageMessage(),
|
|
208
290
|
label: "Judging each note"
|
|
209
291
|
});
|
|
292
|
+
const { answers, truncated } = judgment;
|
|
210
293
|
const minP = numeric(vars.reviewNoteActionable, Infinity);
|
|
294
|
+
const severityMinP = numeric(vars.reviewSeverityMinP, Infinity);
|
|
295
|
+
severities.clear();
|
|
211
296
|
return new Map(notes.map((n) => {
|
|
212
|
-
const verdict = VERDICTS.find((v) => v !== "edit" && answered(answers[n.id], v, minP));
|
|
213
|
-
|
|
297
|
+
const verdict = n.forced ? void 0 : VERDICTS.find((v) => v !== "edit" && answered(answers[n.id], v, minP));
|
|
298
|
+
if (verdict !== void 0 && !truncated.includes(n.id)) return [n.id, verdict];
|
|
299
|
+
const severity = severityOf(n, judgment, severityMinP);
|
|
300
|
+
severities.set(n.id, severity);
|
|
301
|
+
return [n.id, severity.tier === "could" ? "defer" : "edit"];
|
|
214
302
|
}));
|
|
215
303
|
};
|
|
216
304
|
const isCode = (path) => path !== ".gtd" && !path.startsWith(".gtd/");
|
|
@@ -220,30 +308,59 @@ const isCode = (path) => path !== ".gtd" && !path.startsWith(".gtd/");
|
|
|
220
308
|
* another planning lap, questions are answered in place, nits fixed in one
|
|
221
309
|
* batch, praise dropped.
|
|
222
310
|
*/
|
|
223
|
-
const review = (base, escalations = { rounds: 0 }, frozen) =>
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
311
|
+
const review = (base, escalations = { rounds: 0 }, frozen) => {
|
|
312
|
+
const severities = /* @__PURE__ */ new Map();
|
|
313
|
+
let deferred = [];
|
|
314
|
+
return review$1(base, {
|
|
315
|
+
file: REVIEW,
|
|
316
|
+
feedback: REQUIREMENTS,
|
|
317
|
+
isCode,
|
|
318
|
+
reviewing: (b, carry) => {
|
|
319
|
+
deferred = [];
|
|
320
|
+
return reviewing(b, carry);
|
|
321
|
+
},
|
|
322
|
+
fixRisks: (risks) => guarded(frozen, () => fixRisks(risks), "review")(),
|
|
323
|
+
keepGreen: () => healthy(guarded(frozen, fixCheck, "review"), { escalations }),
|
|
324
|
+
awaitReview: (b) => {
|
|
325
|
+
const notes = deferred;
|
|
326
|
+
deferred = [];
|
|
327
|
+
return notes.length > 0 ? awaitReview(b, buildReviewAwaitAfterDeferMessage(b, notes), true) : awaitReview(b);
|
|
328
|
+
},
|
|
329
|
+
reviewMissing,
|
|
330
|
+
collecting,
|
|
331
|
+
triage: triage$1(severities),
|
|
332
|
+
defer: (notes) => {
|
|
333
|
+
deferred = notes.map((n) => ({
|
|
334
|
+
id: n.id,
|
|
335
|
+
anchor: n.anchor,
|
|
336
|
+
text: n.text,
|
|
337
|
+
label: severities.get(n.id).reason
|
|
338
|
+
}));
|
|
339
|
+
return deferNotes(deferred, head());
|
|
340
|
+
},
|
|
341
|
+
answerQuestions: answerReviewQuestions,
|
|
342
|
+
fixNits: (notes) => guarded(frozen, () => fixNits(notes), "review")(),
|
|
343
|
+
close: closeReview,
|
|
344
|
+
captures: {
|
|
345
|
+
edits: reviewEditsCapture,
|
|
346
|
+
notes: reviewNotesCapture,
|
|
347
|
+
editNotes: (round, edits, answeredAt) => reviewEditNotesCapture(round, edits.map((n, i) => ({
|
|
348
|
+
n,
|
|
349
|
+
i,
|
|
350
|
+
s: severities.get(n.id)
|
|
351
|
+
})).sort((x, y) => Number(x.s?.tier === "should") - Number(y.s?.tier === "should") || (x.s?.rank ?? 2) - (y.s?.rank ?? 2) || x.i - y.i).map(({ n, s }) => ({
|
|
352
|
+
id: n.id,
|
|
353
|
+
anchor: n.anchor,
|
|
354
|
+
text: n.forced ? n.text.replace(/^!\s*/, "") : n.text,
|
|
355
|
+
...s === void 0 ? {} : { label: s.reason }
|
|
356
|
+
})), answeredAt)
|
|
357
|
+
},
|
|
358
|
+
refusals: {
|
|
359
|
+
deleted: "gtd land: review-doc: .gtd/REVIEW.md was deleted — restore it, or leave a note (or edit code) to request changes.",
|
|
360
|
+
unmatched: "gtd land: no declared pattern matches the pending changes — write .gtd/REQUIREMENTS.md from the feedback, or change nothing when it asks for nothing"
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
};
|
|
247
364
|
/** The build tail: fix (when entered red), keep green, the quality lap, then human review since `base`. */
|
|
248
365
|
const buildTail = (fixFirst, base, built) => tail(fixFirst, (escalations, frozen) => review(base, escalations, frozen), built);
|
|
249
366
|
//#endregion
|
|
@@ -312,4 +429,4 @@ const feature = shipped(ordinaryStart);
|
|
|
312
429
|
//#region src/workflows/feature/index.ts
|
|
313
430
|
var feature_default = feature;
|
|
314
431
|
//#endregion
|
|
315
|
-
export { SCENARIO_PACKAGE, access, afterTail, answerProductQuestions, answerReviewQuestions, answerTechnicalQuestions, architecture, author, build, buildTail, collecting, declaredTests, decompose, feature_default as default, defaults, design, envDefaults, feature, fixNits, fixSuite, nextPackage, ordinaryStart, packageItem, packages, planAndBuild, reUnwind, requireDeclaredTests, skills, steering, summary, triage, unwind };
|
|
432
|
+
export { SCENARIO_PACKAGE, access, afterTail, answerProductQuestions, answerReviewQuestions, answerTechnicalQuestions, architecture, author, build, buildTail, collecting, declaredTests, decompose, feature_default as default, defaults, deferNotes, design, envDefaults, feature, fixNits, fixSuite, nextPackage, ordinaryStart, packageItem, packages, planAndBuild, reUnwind, requireDeclaredTests, skills, steering, summary, triage, unwind };
|
package/dist/workflows/fix.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { read, refuse, removeScript, run, scope, start } from "../flows.mjs";
|
|
2
|
-
import { d as reviewNotes, f as reviewRisks } from "../chunks/steering-
|
|
3
|
-
import {
|
|
2
|
+
import { d as reviewNotes, f as reviewRisks } from "../chunks/steering-DVILanVf.mjs";
|
|
3
|
+
import { O as agentWithSkills, S as coder, U as finisherSystem, W as fixReviewNotesPrompt, a as REVIEW_ORIG, b as REVIEW, d as shipped, f as defaults, i as skills, m as baseline, n as summary, p as envDefaults, r as access, s as handOffTail, t as steering } from "../chunks/reserved-B9pG93Fc.mjs";
|
|
4
4
|
//#region src/workflows/fix/fix.ts
|
|
5
5
|
/**
|
|
6
6
|
* Fix every note a human left in a handed-off `.gtd/REVIEW.md` and every
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { start } from "../flows.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { X as reviewGateBlockedMessage, c as refusePendingHandOff, d as shipped, f as defaults, h as gate, i as skills, n as summary, p as envDefaults, r as access, s as handOffTail, t as steering } from "../chunks/reserved-B9pG93Fc.mjs";
|
|
3
3
|
//#region src/workflows/review/review.ts
|
|
4
4
|
/**
|
|
5
5
|
* Pure review of everything since `reviewBase`: a green gate, the quality
|