@pmelab/gtd 55.0.0 → 57.0.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 +72 -80
- package/dist/chunks/{reserved-DHafcW7t.mjs → reserved-X2RkNHin.mjs} +110 -318
- package/dist/chunks/{review-BJGKwlYv.mjs → review-v7sh5GF4.mjs} +30 -125
- package/dist/chunks/{steering-CLhu8C7q.mjs → steering-CCNvngSH.mjs} +256 -65
- package/dist/chunks/{tail-B9Hw2AFB.mjs → tail-S04KEewi.mjs} +144 -56
- package/dist/gtd.bundle.mjs +259 -22
- package/dist/steering.mjs +2 -2
- package/dist/testkit.mjs +6 -6
- package/dist/web/main.css +1 -1
- package/dist/web/main.js +551 -66
- package/dist/workflow-kit.mjs +1 -1
- package/dist/workflows/cleanup.mjs +2 -2
- package/dist/workflows/feature.mjs +63 -175
- package/dist/workflows/fix.mjs +3 -3
- package/dist/workflows/review.mjs +3 -3
- package/dist/workflows/rollout.mjs +1 -1
- package/dist/workflows.mjs +603 -727
- package/package.json +1 -1
- package/skills/authoring/SKILL.md +3 -3
- package/src/cli/Cli.ts +5 -5
- package/src/edge/Edge.test.ts +1 -1
- package/src/steering/FORMATS.md +5 -1
- package/src/steering/SteeringFormats.test.ts +2 -2
- package/src/steering/contract.test.ts +1 -0
- package/src/steering/findings.test.ts +47 -0
- package/src/steering/findings.ts +350 -0
- package/src/steering/fixtures/findings/gate.md +34 -0
- package/src/steering/fixtures/findings/gate.read.json +87 -0
- package/src/steering/index.test.ts +2 -2
- package/src/steering/index.ts +4 -3
- package/src/steering/review.test.ts +1 -75
- package/src/steering/review.ts +1 -74
- package/src/workflow/compile.test.ts +1 -0
- package/src/workflows/feature/criteria-coverage.feature +1 -7
- package/src/workflows/feature/criteria.test.ts +1 -41
- package/src/workflows/feature/criteria.ts +2 -14
- package/src/workflows/feature/fast-path.feature +0 -1
- package/src/workflows/feature/feature.test.ts +1 -1
- package/src/workflows/feature/feature.ts +16 -25
- package/src/workflows/feature/flag-mode.feature +1 -1
- package/src/workflows/feature/lens-models.feature +0 -1
- package/src/workflows/feature/lens-review.feature +323 -172
- package/src/workflows/feature/naive-test.feature +258 -0
- package/src/workflows/feature/one-step-land.feature +0 -1
- package/src/workflows/feature/refactor-absorbs.feature +1 -8
- package/src/workflows/feature/refactor-first.feature +2 -11
- package/src/workflows/feature/refactor-rebuild.feature +4 -25
- package/src/workflows/feature/refactor-review.feature +33 -118
- package/src/workflows/feature/refactor.test.ts +0 -2
- package/src/workflows/feature/refactor.ts +0 -1
- package/src/workflows/feature/review-gate.feature +7 -24
- package/src/workflows/feature/reviewer-walkthrough.feature +16 -104
- package/src/workflows/feature/seam-rejection.feature +0 -1
- package/src/workflows/feature/seam.feature +0 -1
- package/src/workflows/feature/seam.test.ts +1 -2
- package/src/workflows/feature/seam.ts +56 -10
- package/src/workflows/feature/standards.feature +75 -35
- package/src/workflows/fix/fix-lens-origin.feature +20 -7
- package/src/workflows/fix/fix-quality.feature +102 -23
- package/src/workflows/review/review-door.feature +62 -59
- package/src/workflows/shared/learn.test.ts +0 -14
- package/src/workflows/shared/learn.ts +1 -6
- package/src/workflows/shared/lenses.ts +149 -43
- package/src/workflows/shared/options.ts +9 -1
- package/src/workflows/shared/prose.ts +0 -6
- package/src/workflows/shared/review.test.ts +27 -26
- package/src/workflows/shared/review.ts +29 -196
- package/src/workflows/shared/skills.test.ts +0 -4
- package/src/workflows/shared/skills.ts +0 -5
- package/src/workflows/shared/steps.ts +1 -1
- package/src/workflows/shared/tail.ts +18 -9
- package/src/workflows/shared/text.test.ts +125 -329
- package/src/workflows/shared/text.ts +173 -471
- package/src/workflows/shared/vars.ts +2 -3
- package/src/workflows/feature/hands-on-skip.feature +0 -316
- package/src/workflows/feature/prototype-rounds.feature +0 -156
- package/src/workflows/feature/prototype.feature +0 -428
- package/src/workflows/feature/prototype.test.ts +0 -43
- package/src/workflows/feature/prototype.ts +0 -198
- package/src/workflows/feature/review-answers.feature +0 -324
- package/src/workflows/feature/severity-budget.feature +0 -116
- package/src/workflows/feature/severity-sorted-review.feature +0 -198
package/dist/workflow-kit.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { changes, changesSince, hasThreadFor, head, mark, read, refuse, requireReplies, requireThreadsClosed, scope } from "./flows.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { A as parseThreads, C as unansweredNotes, b as reviewNotes, c as stripCodeThreads, x as reviewRisks, y as reviewDecisions } from "./chunks/steering-CCNvngSH.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) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { agent, changes, glob, read, refuse, scope, start, vars } from "../flows.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { a as refusePendingHandOff, r as handOffTail } from "../chunks/tail-
|
|
2
|
+
import { Ct as envDefaults, Ft as flagReferences, Lt as registryEntry, Rt as requireFlag, S as coder, St as defaults, i as skills, n as summary, o as flagShipped, r as access, t as steering } from "../chunks/reserved-X2RkNHin.mjs";
|
|
3
|
+
import { a as refusePendingHandOff, r as handOffTail } from "../chunks/tail-S04KEewi.mjs";
|
|
4
4
|
//#region src/workflows/cleanup/cleanup.ts
|
|
5
5
|
const removingPrompt = (name, registry) => `Clean up the release flag "${name}", which is default-on: delete its entry in ${registry}, and remove every \`GTD_FLAG_${name.toUpperCase()}\` check from the shipped sources. Keep the flag-on path; delete code only the off path reached, including tests that pin the off path.`;
|
|
6
6
|
const cleanupFlow = async () => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { agent, answered, applyScript, changes, changesSince, check, codeChanges, env, hasThreadFor, head, human, judge, judgeDiffShape, kept, mark, matches, quote, read, refuse, removeScript, requireAnswers, requireProgress, requireReplies, requireThreadsClosed, revertScript, run, scope, start, vars, wrote } from "../flows.mjs";
|
|
1
|
+
import { agent, answered, applyScript, changes, changesSince, check, codeChanges, env, hasThreadFor, head, human, judge, judgeDiffShape, kept, mark, matches, quote, read, refuse, removeScript, requireAnswers, requireProgress, requireReplies, requireThreadsClosed, restoreScript, revertScript, run, scope, start, vars, wrote } from "../flows.mjs";
|
|
2
2
|
import { lensEntriesOf } from "../workflow-kit.mjs";
|
|
3
|
-
import { $ as
|
|
4
|
-
import { a as refusePendingHandOff
|
|
5
|
-
import {
|
|
3
|
+
import { $ as naiveTryMessage, B as designImpactPrompt, C as collecting, Ct as envDefaults, F as builderSystem, H as designTriagePrompt, I as clearCriteriaMessage, J as idleMessage, L as clearCriteriaQuestion, M as agentWithSkills, N as buildReviewCollectingPrompt, O as planner, Q as naivePassPrompt, R as criterionLine, S as coder, St as defaults, T as fixNits, V as designSystem, X as implementFixPrompt, Y as implementBuildingPrompt, Z as naiveApplyFailure, _ as REFACTOR_NOTE, _t as startGateBlockedMessage, a as flagModeOn, at as refactorDroppedRefusal, b as answerReviewQuestions, c as shipped, ct as refactorRules, f as healthy, g as REFACTOR, gt as seamSteerMessage, ht as seamByHandMessage, i as skills, it as refactorBuildingPrompt, m as NAIVE_TEST, mt as reviewerSystem, n as summary, ot as refactorFixPrompt, p as FEEDBACK, r as access, s as naiveTestOn, st as refactorNotePrompt, t as steering, tt as normaliseCriteriaScript, u as gate, v as REQUIREMENTS, vt as unwindFailedMessage, wt as testFileGlobs, yt as unwindFailure, z as designGateAnswerMessage } from "../chunks/reserved-X2RkNHin.mjs";
|
|
4
|
+
import { a as refusePendingHandOff } from "../chunks/tail-S04KEewi.mjs";
|
|
5
|
+
import { n as isCode$1, r as reUnwind, t as buildTail } from "../chunks/review-v7sh5GF4.mjs";
|
|
6
6
|
import { posix } from "node:path";
|
|
7
7
|
//#region src/workflows/shared/fences.ts
|
|
8
8
|
const markFenced = (text) => {
|
|
@@ -26,11 +26,10 @@ const ITEM = /^ ?(?:[-*+]|\d+[.)])\s+(?:\[[ xX]\]\s+)?(.*)$/;
|
|
|
26
26
|
//#region src/workflows/feature/criteria.ts
|
|
27
27
|
/** Below this the judge's `yes` is not trusted: a wrong skip builds against criteria nobody can check. */
|
|
28
28
|
const CLEAR_MIN_P = .8;
|
|
29
|
-
const ID = /^(AC-\d+)
|
|
29
|
+
const ID = /^(AC-\d+):\s*(.*)$/;
|
|
30
30
|
const criterion = (id, as = id[1]) => ({
|
|
31
31
|
id: as,
|
|
32
|
-
text: id[
|
|
33
|
-
...id[2] === void 0 ? {} : { noHandsOn: true }
|
|
32
|
+
text: id[2]
|
|
34
33
|
});
|
|
35
34
|
/** The list items under the first heading `title` matches (at `level` when given), up to the next heading; wrapped lines joined, fenced lines ignored. */
|
|
36
35
|
const listUnder = (text, title, level) => {
|
|
@@ -67,11 +66,6 @@ const criteriaOf = (text) => listUnder(text, /^acceptance criteria$/i, 2)?.map((
|
|
|
67
66
|
});
|
|
68
67
|
/** The ID'd criteria of `text`. */
|
|
69
68
|
const criterionIds = (text) => (criteriaOf(text) ?? []).map((c) => c.id).filter((id) => id !== "");
|
|
70
|
-
/** The ID'd criteria of `text` a person can try by hand: none tagged `(no hands-on)`. */
|
|
71
|
-
const handsOnIds = (text) => {
|
|
72
|
-
const tagged = (criteriaOf(text) ?? []).filter((c) => c.noHandsOn).map((c) => c.id);
|
|
73
|
-
return criterionIds(text).filter((id) => !tagged.includes(id));
|
|
74
|
-
};
|
|
75
69
|
/** Items numbered `AC-1`…, unless every one already carries its own distinct ID. */
|
|
76
70
|
const numbered = (items) => {
|
|
77
71
|
const ids = items.map((item) => ID.exec(item));
|
|
@@ -314,147 +308,6 @@ const green = () => healthy(() => agentWithSkills("fix.suite.fixing", implementF
|
|
|
314
308
|
guardRests: false
|
|
315
309
|
});
|
|
316
310
|
//#endregion
|
|
317
|
-
//#region src/workflows/feature/prototype.ts
|
|
318
|
-
/** Only a `no` at this or above skips a criterion: no verdict, or an unsure one, sends it to the hands-on test. */
|
|
319
|
-
const UNOBSERVABLE_MIN_P = .5;
|
|
320
|
-
/** The `prototypeRounds` setting. Anything but a non-negative integer fails rather than guess a cap. */
|
|
321
|
-
const prototypeRounds = () => {
|
|
322
|
-
const value = vars.prototypeRounds ?? defaults.prototypeRounds;
|
|
323
|
-
if (!/^(0|[1-9]\d*)$/.test(value)) refuse(`gtd: prototypeRounds must be a non-negative integer, got ${JSON.stringify(value)}`);
|
|
324
|
-
return Number(value);
|
|
325
|
-
};
|
|
326
|
-
const CHUNK = /^(AC-\d+|Problem\b.*?)\s*:\s*(pass|fail|blocked)$/i;
|
|
327
|
-
const UNGUIDED = /^no testing instructions$/i;
|
|
328
|
-
/** The `## ` chunks of a prototype report; a heading in neither shape is prose, not an item. */
|
|
329
|
-
const reportOf = (text) => {
|
|
330
|
-
let unguided = false;
|
|
331
|
-
const items = [];
|
|
332
|
-
const malformed = [];
|
|
333
|
-
for (const { line, fenced } of markFenced(text)) {
|
|
334
|
-
const heading = fenced ? null : HEADING.exec(line);
|
|
335
|
-
if (heading?.[1] !== "##") continue;
|
|
336
|
-
if (UNGUIDED.test(heading[2])) unguided = true;
|
|
337
|
-
const chunk = CHUNK.exec(heading[2]);
|
|
338
|
-
if (chunk === null && /^(ac-\d|problem)/i.test(heading[2])) malformed.push(heading[2]);
|
|
339
|
-
if (chunk !== null) items.push({
|
|
340
|
-
subject: /^ac-/i.test(chunk[1]) ? chunk[1].toUpperCase() : chunk[1],
|
|
341
|
-
verdict: chunk[2].toLowerCase()
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
return {
|
|
345
|
-
unguided,
|
|
346
|
-
items,
|
|
347
|
-
malformed
|
|
348
|
-
};
|
|
349
|
-
};
|
|
350
|
-
/**
|
|
351
|
-
* The report the testing turn left, refused unless it is the only change and
|
|
352
|
-
* names each of `ids` once, with its open items: any other criterion is not
|
|
353
|
-
* this test's to fix.
|
|
354
|
-
*/
|
|
355
|
-
const requireReport = (ids, retest) => {
|
|
356
|
-
const others = changes().map((c) => c.path).filter((path) => path !== PROTOTYPE);
|
|
357
|
-
if (others.length > 0) refuse(`gtd land: prototype-report: test in a disposable place and change nothing but ${PROTOTYPE} — revert these:\n${others.map((path) => ` - ${path}`).join("\n")}`);
|
|
358
|
-
const text = read(PROTOTYPE);
|
|
359
|
-
if (text === void 0) return refuse(`gtd land: prototype-report: write ${PROTOTYPE}`);
|
|
360
|
-
const report = reportOf(text);
|
|
361
|
-
if (report.malformed.length > 0) refuse(`gtd land: prototype-report: head each chunk \`## <ID>: pass|fail|blocked\` or \`## Problem <title>: pass|fail|blocked\` — these miss it:\n${report.malformed.map((h) => ` - ${h}`).join("\n")}`);
|
|
362
|
-
if (report.unguided && report.items.length === 0 && !retest) return {
|
|
363
|
-
unguided: true,
|
|
364
|
-
open: []
|
|
365
|
-
};
|
|
366
|
-
const elsewhere = criterionIds(read(".gtd/REQUIREMENTS.md") ?? "").filter((id) => !ids.includes(id));
|
|
367
|
-
const count = (id) => report.items.filter((i) => i.subject === id).length;
|
|
368
|
-
const wrong = ids.filter((id) => count(id) !== 1);
|
|
369
|
-
if (wrong.length > 0) refuse(`gtd land: prototype-report: ${PROTOTYPE} needs exactly one chunk headed \`## <ID>: pass|fail|blocked\` for ${wrong.join(", ")}`);
|
|
370
|
-
return {
|
|
371
|
-
unguided: false,
|
|
372
|
-
open: report.items.filter((i) => i.verdict !== "pass" && !elsewhere.includes(i.subject))
|
|
373
|
-
};
|
|
374
|
-
};
|
|
375
|
-
/**
|
|
376
|
-
* The criteria a person can observe by using the change, by the judge: those
|
|
377
|
-
* tagged `(no hands-on)` are never asked about.
|
|
378
|
-
*/
|
|
379
|
-
const observable = async () => {
|
|
380
|
-
const requirements = read(".gtd/REQUIREMENTS.md") ?? "";
|
|
381
|
-
const own = handsOnIds(requirements);
|
|
382
|
-
const criteria = (criteriaOf(requirements) ?? []).filter((c) => own.includes(c.id));
|
|
383
|
-
if (criteria.length === 0) return [];
|
|
384
|
-
const { answers } = await judge("observable", {
|
|
385
|
-
questions: criteria.map(observableQuestion),
|
|
386
|
-
evidence: { requirements },
|
|
387
|
-
message: observableMessage(),
|
|
388
|
-
label: "Judging which criteria to test by hand"
|
|
389
|
-
});
|
|
390
|
-
return own.filter((id) => !answered(answers[id], "no", UNOBSERVABLE_MIN_P));
|
|
391
|
-
};
|
|
392
|
-
const frozen = () => requireCriteriaFrozen(REQUIREMENTS);
|
|
393
|
-
const testing = async (ids, retest) => {
|
|
394
|
-
await agentWithSkills("testing", prototypeTestingPrompt(criterionIds(read(".gtd/REQUIREMENTS.md") ?? "").filter((id) => !ids.includes(id)), retest), {
|
|
395
|
-
label: retest ? "Re-testing the change by hand" : "Testing the change by hand",
|
|
396
|
-
file: PROTOTYPE,
|
|
397
|
-
model: coder(),
|
|
398
|
-
system: testerSystem(),
|
|
399
|
-
allowEmpty: true
|
|
400
|
-
});
|
|
401
|
-
return requireReport(ids, retest);
|
|
402
|
-
};
|
|
403
|
-
const fixing = async () => {
|
|
404
|
-
await scope("fix", () => agentWithSkills("fixing", prototypeFixingPrompt(), {
|
|
405
|
-
label: "Fixing what the hands-on test found",
|
|
406
|
-
file: PROTOTYPE,
|
|
407
|
-
model: coder(),
|
|
408
|
-
system: builderSystem(),
|
|
409
|
-
allowEmpty: true
|
|
410
|
-
}));
|
|
411
|
-
if (changes().some((c) => c.path === ".gtd/PROTOTYPE.md")) refuse(`gtd land: prototype-fix: leave ${PROTOTYPE} as it is — the next round re-tests from it`);
|
|
412
|
-
frozen();
|
|
413
|
-
};
|
|
414
|
-
/** A person's rest; resolves `true` when they changed something to test again, `false` on a clean overrule. */
|
|
415
|
-
const askPerson = async (name, message, label) => {
|
|
416
|
-
await human(name, {
|
|
417
|
-
message,
|
|
418
|
-
label,
|
|
419
|
-
file: PROTOTYPE,
|
|
420
|
-
acceptClean: true
|
|
421
|
-
});
|
|
422
|
-
if (!changes().some((c) => c.path !== ".gtd/PROTOTYPE.md")) return false;
|
|
423
|
-
frozen();
|
|
424
|
-
return true;
|
|
425
|
-
};
|
|
426
|
-
/**
|
|
427
|
-
* Use the change by hand: a testing turn reports on every criterion a person
|
|
428
|
-
* can observe, a fix turn takes each failure, and the change is tested again —
|
|
429
|
-
* until the report is clean, or `prototypeRounds` fixes are spent and a person
|
|
430
|
-
* decides. A change with no such criterion is not tested by hand.
|
|
431
|
-
*/
|
|
432
|
-
const prototypeTest = async () => {
|
|
433
|
-
const cap = prototypeRounds();
|
|
434
|
-
if (cap === 0) return;
|
|
435
|
-
await scope("prototype", async () => {
|
|
436
|
-
const ids = await observable();
|
|
437
|
-
if (ids.length === 0) return;
|
|
438
|
-
let fixes = 0;
|
|
439
|
-
let retest = false;
|
|
440
|
-
for (;;) {
|
|
441
|
-
const { unguided, open } = await testing(ids, retest);
|
|
442
|
-
retest = !unguided;
|
|
443
|
-
if (unguided) {
|
|
444
|
-
if (!await askPerson("unguided", prototypeUnguidedMessage(), "No way to test by hand")) return;
|
|
445
|
-
} else if (open.length === 0) return;
|
|
446
|
-
else if (fixes < cap && open.some((i) => i.verdict === "fail")) {
|
|
447
|
-
fixes++;
|
|
448
|
-
await fixing();
|
|
449
|
-
} else {
|
|
450
|
-
if (!await askPerson("open", prototypeOpenMessage(open, fixes), "Hands-on test still failing")) return;
|
|
451
|
-
fixes = 0;
|
|
452
|
-
}
|
|
453
|
-
await green();
|
|
454
|
-
}
|
|
455
|
-
});
|
|
456
|
-
};
|
|
457
|
-
//#endregion
|
|
458
311
|
//#region src/workflows/feature/refactor.ts
|
|
459
312
|
const REFACTOR_PACKAGE = REFACTOR;
|
|
460
313
|
const isCode = (path) => path !== ".gtd" && !path.startsWith(".gtd/");
|
|
@@ -696,7 +549,6 @@ const reviewedRefactor = async (shape, options = {}) => {
|
|
|
696
549
|
fixAccess: strayAccess(p.strays),
|
|
697
550
|
lensBase: entry,
|
|
698
551
|
rules: refactorRules(p.strays, p.pattern),
|
|
699
|
-
walkthrough: true,
|
|
700
552
|
lap: "refactor"
|
|
701
553
|
});
|
|
702
554
|
if (outcome.verdict === "signoff") return true;
|
|
@@ -826,13 +678,8 @@ const implementing = (options) => scope("implement", async () => {
|
|
|
826
678
|
if (options.naive === void 0 || !await applied(options.naive)) await build(options);
|
|
827
679
|
else requireCriteriaFrozen(REQUIREMENTS);
|
|
828
680
|
await green();
|
|
829
|
-
await prototypeTest();
|
|
830
681
|
const ids = criterionIds(read(".gtd/REQUIREMENTS.md") ?? "");
|
|
831
|
-
await run("closing", removeScript([
|
|
832
|
-
REQUIREMENTS,
|
|
833
|
-
REFACTOR_NOTE,
|
|
834
|
-
PROTOTYPE
|
|
835
|
-
]), { label: "Closing out the implementation" });
|
|
682
|
+
await run("closing", removeScript([REQUIREMENTS, REFACTOR_NOTE]), { label: "Closing out the implementation" });
|
|
836
683
|
return ids;
|
|
837
684
|
});
|
|
838
685
|
/** Resolves `true` when the human steered (edited), `false` on a clean overrule. */
|
|
@@ -900,6 +747,39 @@ const ruled = async (tip, again) => {
|
|
|
900
747
|
tip
|
|
901
748
|
} : next;
|
|
902
749
|
};
|
|
750
|
+
/** Back to `before`: every code path, and the notes file. `.gtd/` edits (the requirements) stay. */
|
|
751
|
+
const untryScript = (before) => {
|
|
752
|
+
const code = changesSince(before).filter((c) => isCode$1(c.path));
|
|
753
|
+
return restoreScript(head(), {
|
|
754
|
+
restore: code.filter((c) => c.status !== "added").map((c) => c.path),
|
|
755
|
+
remove: [...code.filter((c) => c.status === "added").map((c) => c.path), NAIVE_TEST]
|
|
756
|
+
}, before);
|
|
757
|
+
};
|
|
758
|
+
/**
|
|
759
|
+
* A person tries the green pass `tip` in the working tree. Resolves
|
|
760
|
+
* `undefined` on a clean landing (signed off), else what they sent back;
|
|
761
|
+
* either way the pass, their code edits and the notes file leave the tree.
|
|
762
|
+
*/
|
|
763
|
+
const tried = async (tip) => {
|
|
764
|
+
const before = head();
|
|
765
|
+
await run("applying", applyScript(tip.hash, FEEDBACK, naiveApplyFailure(tip.hash), [".gtd"]), { label: "Applying the naive pass to try it" });
|
|
766
|
+
await human("try", {
|
|
767
|
+
message: naiveTryMessage(flagModeOn()),
|
|
768
|
+
label: "Try the naive pass",
|
|
769
|
+
file: NAIVE_TEST,
|
|
770
|
+
acceptClean: true
|
|
771
|
+
});
|
|
772
|
+
const landed = changes();
|
|
773
|
+
const edits = landed.some((c) => isCode$1(c.path)) ? head() : void 0;
|
|
774
|
+
const notes = read(".gtd/NAIVE-TEST.md")?.trim() || void 0;
|
|
775
|
+
if (landed.some((c) => c.path === ".gtd/REQUIREMENTS.md")) requireCriteria(REQUIREMENTS);
|
|
776
|
+
await run("restoring", untryScript(before), { label: "Taking the naive pass out again" });
|
|
777
|
+
return landed.length === 0 ? void 0 : {
|
|
778
|
+
tested: tip.hash,
|
|
779
|
+
notes,
|
|
780
|
+
edits
|
|
781
|
+
};
|
|
782
|
+
};
|
|
903
783
|
const decide = () => scope("seam", async () => {
|
|
904
784
|
const vetting = {
|
|
905
785
|
again: budget(),
|
|
@@ -909,7 +789,16 @@ const decide = () => scope("seam", async () => {
|
|
|
909
789
|
for (;;) {
|
|
910
790
|
await naivePass(retry);
|
|
911
791
|
const tip = kept("naive");
|
|
912
|
-
const
|
|
792
|
+
const verdict = await vetted(tip, vetting);
|
|
793
|
+
if (verdict === void 0 && naiveTestOn()) {
|
|
794
|
+
const sentBack = await tried(tip);
|
|
795
|
+
if (sentBack !== void 0) {
|
|
796
|
+
vetting.again = budget();
|
|
797
|
+
retry = sentBack;
|
|
798
|
+
continue;
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
const outcome = verdict ?? (flagModeOn() ? await ruled(tip, vetting.again) : {
|
|
913
802
|
reference: tip.hash,
|
|
914
803
|
tip
|
|
915
804
|
});
|
|
@@ -996,7 +885,11 @@ const buildFeature = async (firstBase) => {
|
|
|
996
885
|
});
|
|
997
886
|
const carried = seam.rebuild?.acceptance?.tests ?? [];
|
|
998
887
|
const base = seam.refactored === true && !changesSince(seam.base).some((c) => isCode$1(c.path) && !carried.includes(c.path)) ? firstBase : seam.base;
|
|
999
|
-
const outcome = await
|
|
888
|
+
const outcome = await buildTail(base, {
|
|
889
|
+
green: true,
|
|
890
|
+
lensBase: base,
|
|
891
|
+
requirements
|
|
892
|
+
});
|
|
1000
893
|
await featureFeedback(outcome, base, {
|
|
1001
894
|
closed,
|
|
1002
895
|
used
|
|
@@ -1007,16 +900,6 @@ const gather = (handedOut) => {
|
|
|
1007
900
|
for (const id of listedIds()) handedOut.add(id);
|
|
1008
901
|
return [...handedOut];
|
|
1009
902
|
};
|
|
1010
|
-
/** The quality lap, then a reviewer's walkthrough since `base` for the human. */
|
|
1011
|
-
const reviewedTail = (base, lensBase, requirements, lap = "first") => tail((escalations, report) => humanReview(base, escalations, {
|
|
1012
|
-
report,
|
|
1013
|
-
walkthrough: true,
|
|
1014
|
-
lap
|
|
1015
|
-
}), {
|
|
1016
|
-
green: true,
|
|
1017
|
-
lensBase,
|
|
1018
|
-
requirements
|
|
1019
|
-
});
|
|
1020
903
|
const featureFeedback = async (first, lensBase, ids) => {
|
|
1021
904
|
let outcome = first;
|
|
1022
905
|
let closed = ids.closed;
|
|
@@ -1037,7 +920,12 @@ const featureFeedback = async (first, lensBase, ids) => {
|
|
|
1037
920
|
tier,
|
|
1038
921
|
amend: true
|
|
1039
922
|
});
|
|
1040
|
-
outcome = await
|
|
923
|
+
outcome = await buildTail(outcome.base, {
|
|
924
|
+
green: true,
|
|
925
|
+
lensBase,
|
|
926
|
+
requirements,
|
|
927
|
+
lap: "feedback"
|
|
928
|
+
});
|
|
1041
929
|
}
|
|
1042
930
|
};
|
|
1043
931
|
/** Design — skipped when the sketch's own criteria are judged clear — then `buildFeature`. */
|
|
@@ -1072,7 +960,7 @@ const ordinaryStart = async () => {
|
|
|
1072
960
|
});
|
|
1073
961
|
refusePendingHandOff();
|
|
1074
962
|
flagModeOn();
|
|
1075
|
-
|
|
963
|
+
naiveTestOn();
|
|
1076
964
|
const stated = statedCriteria(changes(), head());
|
|
1077
965
|
await unwind();
|
|
1078
966
|
if (changes(".gtd/FEEDBACK.md").some((c) => c.status !== "deleted")) await human("unwind-failed", {
|
|
@@ -1088,4 +976,4 @@ const feature = shipped(ordinaryStart);
|
|
|
1088
976
|
//#region src/workflows/feature/index.ts
|
|
1089
977
|
var feature_default = feature;
|
|
1090
978
|
//#endregion
|
|
1091
|
-
export { COMMENT, REFACTOR_PACKAGE, acceptanceFault, access, afterTail, answerProductQuestions, answerReviewQuestions, buildFeature, buildTail, collecting, criteriaOf, criterionIds, feature_default as default, defaults, design, envDefaults, feature, fixNits,
|
|
979
|
+
export { COMMENT, REFACTOR_PACKAGE, acceptanceFault, access, afterTail, answerProductQuestions, answerReviewQuestions, buildFeature, buildTail, collecting, criteriaOf, criterionIds, feature_default as default, defaults, design, envDefaults, feature, fixNits, hasImpact, holdsCallSites, implement, implementing, isTestFile, judgeSeam, naiveAcceptance, naivePass, ordinaryStart, planAndBuild, reUnwind, refactorCollecting, refactorFirst, refactorNote, refactorStrays, requireCriteria, requireCriteriaFrozen, requireImpact, requireImpactOnly, requireNoNewFlags, requireNoTestFiles, requireStableIds, requireTestCallSitesOnly, requireWithin, reviewedRefactor, seamBuild, skills, skipDesign, statedCriteria, steering, summary, triage, unstableIds, unwind };
|
package/dist/workflows/fix.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { read, refuse, removeScript, run, scope, start } from "../flows.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { r as handOffTail, t as REVIEW_ORIG } from "../chunks/tail-
|
|
2
|
+
import { b as reviewNotes, x as reviewRisks } from "../chunks/steering-CCNvngSH.mjs";
|
|
3
|
+
import { Ct as envDefaults, G as finisherSystem, K as fixReviewNotesPrompt, M as agentWithSkills, S as coder, St as defaults, c as shipped, i as skills, l as baseline, n as summary, r as access, t as steering, y as REVIEW } from "../chunks/reserved-X2RkNHin.mjs";
|
|
4
|
+
import { r as handOffTail, t as REVIEW_ORIG } from "../chunks/tail-S04KEewi.mjs";
|
|
5
5
|
//#region src/workflows/fix/fix.ts
|
|
6
6
|
/**
|
|
7
7
|
* Fix every note a human left in a handed-off `.gtd/REVIEW.md` and every
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { read, refuse, removeScript, run, start } from "../flows.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { a as refusePendingHandOff } from "../chunks/tail-
|
|
4
|
-
import {
|
|
2
|
+
import { Ct as envDefaults, G as finisherSystem, M as agentWithSkills, S as coder, St as defaults, c as shipped, dt as reviewFeedbackFixPrompt, ft as reviewGateBlockedMessage, i as skills, n as summary, r as access, t as steering, u as gate, v as REQUIREMENTS } from "../chunks/reserved-X2RkNHin.mjs";
|
|
3
|
+
import { a as refusePendingHandOff } from "../chunks/tail-S04KEewi.mjs";
|
|
4
|
+
import { r as reUnwind, t as buildTail } from "../chunks/review-v7sh5GF4.mjs";
|
|
5
5
|
//#region src/workflows/review/review.ts
|
|
6
6
|
const fixFeedback = async () => {
|
|
7
7
|
await agentWithSkills("feedback.fixing", reviewFeedbackFixPrompt(), {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { agent, changesSince, glob, head, mark, read, refuse, removeScript, run, scope, vars } from "../flows.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { Ct as envDefaults, It as flipProblems, Pt as flagMentions, Rt as requireFlag, S as coder, St as defaults, i as skills, n as summary, o as flagShipped, p as FEEDBACK, r as access, t as steering, u as gate } from "../chunks/reserved-X2RkNHin.mjs";
|
|
3
3
|
//#region src/workflows/rollout/rollout.ts
|
|
4
4
|
const flippingPrompt = (name, registry) => `Roll out the release flag "${name}": in ${registry}, set \`defaultOn: true\` on its entry. Change nothing else — no other entry, no other field, no other file, no comments.`;
|
|
5
5
|
const suiteBlockedMessage = () => "The suite is red after the rollout. Fix it by hand — a rollout may only touch the flag's registry entry — then land.";
|