@pmelab/gtd 29.1.0 → 29.1.1
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 +14 -9
- package/dist/chunks/{reserved-DoHUII2D.mjs → reserved-fqf-c9dc.mjs} +34 -9
- package/dist/chunks/{tail-C6YBG5zh.mjs → tail-Do11DVcw.mjs} +1 -1
- package/dist/workflows/cleanup.mjs +2 -2
- package/dist/workflows/feature.mjs +127 -41
- package/dist/workflows/fix.mjs +2 -2
- package/dist/workflows/review.mjs +2 -2
- package/dist/workflows/rollout.mjs +1 -1
- package/dist/workflows.mjs +159 -48
- package/package.json +1 -1
- package/src/workflows/feature/feature.ts +6 -5
- package/src/workflows/feature/packages.test.ts +299 -5
- package/src/workflows/feature/packages.ts +109 -26
- package/src/workflows/feature/refactor.ts +9 -2
- package/src/workflows/feature/review.ts +25 -7
- package/src/workflows/feature/seam.ts +28 -8
- package/src/workflows/shared/text.test.ts +44 -0
- package/src/workflows/shared/text.ts +57 -10
package/README.md
CHANGED
|
@@ -420,15 +420,20 @@ noted in steps 3 and 4 below.
|
|
|
420
420
|
|
|
421
421
|
3. **You wait.** The work is split into vertical slices and built one at a time,
|
|
422
422
|
each one starting from the unit and e2e tests it declares (a build turn
|
|
423
|
-
missing one is refused
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
423
|
+
missing one is refused; a test the package only relies on is marked
|
|
424
|
+
`(unchanged)`; it must exist before the turn, and the build turn must not
|
|
425
|
+
create, edit or delete it — a wrong marker is fixed upstream, in the plan,
|
|
426
|
+
and a process stuck on one is ended with `gtd abandon`; and a package whose
|
|
427
|
+
work lies outside the repository, such as filing issues, closes on recorded
|
|
428
|
+
evidence), checked against the full suite (`testCommand`) and fixed until it
|
|
429
|
+
passes before moving on — so keep that suite fast; gtd has no lighter one.
|
|
430
|
+
Scenario wording is not frozen: you sign the scenarios off once, in the
|
|
431
|
+
review's `## Scenarios` chunk, where any assertion an existing scenario lost
|
|
432
|
+
is marked `Weakened:`. After the last package the quality lap runs. Two
|
|
433
|
+
points along the process are judged rather than always asking you outright —
|
|
434
|
+
each stops and hands you a verdict to make (`gtd judge answer`, or land with
|
|
435
|
+
a clean tree to accept the conservative default, which never skips work;
|
|
436
|
+
`gtd judge run --provider fixed --answers <path>` — or the
|
|
432
437
|
`GTD_JUDGE_ANSWERS` env var, inline JSON — answers one from a file, piped
|
|
433
438
|
between `gtd judge --json` and `gtd judge answer`;
|
|
434
439
|
`gtd judge run --provider jev` asks TypeSafe's Jev instead, with the key in
|
|
@@ -691,7 +691,12 @@ ${stateFileRules}
|
|
|
691
691
|
- Every package with tests has a \`## Tests\` section, one line per
|
|
692
692
|
declared test, copied from the architecture entries:
|
|
693
693
|
\`- unit: \\\`<path>\\\`\` or \`- e2e: \\\`<path>\\\`\`. Chore packages have
|
|
694
|
-
none
|
|
694
|
+
none. List every test the package writes or changes; also list an
|
|
695
|
+
existing test a criterion relies on, marked \`(unchanged)\` —
|
|
696
|
+
\`- unit: \\\`<path>\\\` (unchanged)\` or
|
|
697
|
+
\`- e2e: \\\`<path>\\\` (unchanged)\`; list no other untouched test;
|
|
698
|
+
never mark a file the package also writes or changes — list it once,
|
|
699
|
+
unmarked; only decompose places the marker
|
|
695
700
|
- Leave everything uncommitted and finish
|
|
696
701
|
`;
|
|
697
702
|
const architectureGateAnswerMessage = () => `This gate stops on every process, even with no open question, so
|
|
@@ -724,15 +729,26 @@ const packagesItemBuildingPrompt = (pkg) => `${stateFileRules}
|
|
|
724
729
|
never delete the package file (the declared-tests guard reads it
|
|
725
730
|
after you)
|
|
726
731
|
- The package to implement is \`${pkg}\`
|
|
727
|
-
- First check
|
|
728
|
-
an earlier fix turn may already
|
|
729
|
-
|
|
730
|
-
with
|
|
731
|
-
symbol
|
|
732
|
-
|
|
732
|
+
- First check the acceptance criteria against the current tree —
|
|
733
|
+
an earlier fix turn may already meet them
|
|
734
|
+
- **Every criterion already met in the tree**: write
|
|
735
|
+
\`.gtd/SATISFIED.md\` with evidence per criterion — commit, file,
|
|
736
|
+
symbol, issue URL, or command output — and change nothing else
|
|
737
|
+
- **No \`## Tests\` and work outside the tree**: first check it was
|
|
738
|
+
not already done by an earlier attempt (e.g. an existing issue
|
|
739
|
+
with the same title via \`gh\`) and reuse that as evidence, or do
|
|
740
|
+
the work; then write \`.gtd/SATISFIED.md\` with that evidence and
|
|
741
|
+
change nothing else in the tree
|
|
742
|
+
- **Any other package**: implement normally, write no
|
|
743
|
+
\`.gtd/SATISFIED.md\`
|
|
733
744
|
- Write the tests the package declares under \`## Tests\` first,
|
|
734
745
|
then the code that makes them pass; the turn is refused unless
|
|
735
|
-
every declared test is in your diff
|
|
746
|
+
every declared test is in your diff — except a line marked
|
|
747
|
+
\`(unchanged)\`, which must exist before the turn and stay
|
|
748
|
+
untouched — creating, editing or deleting it refuses the turn. If
|
|
749
|
+
it does not exist yet, or the marker is wrong because the package
|
|
750
|
+
must change that test, stop without creating it and leave it to
|
|
751
|
+
a person
|
|
736
752
|
- A declared e2e test is a scenario in the repository's own e2e
|
|
737
753
|
framework for the behaviour its \`## E2E Scenarios\` entry names.
|
|
738
754
|
Word it to fit the existing steps — reuse and generalise them
|
|
@@ -760,7 +776,16 @@ ${strays.map((path) => ` - \`${displayPath(path)}\``).join("\n")}
|
|
|
760
776
|
- Introduce no new flag read and add no second read of an existing one:
|
|
761
777
|
every match of \`${pattern}\` may move, never increase in number`;
|
|
762
778
|
const withRules = (rules) => rules === void 0 ? "" : `${rules}\n`;
|
|
763
|
-
|
|
779
|
+
function refactorBuildingPrompt(first, strays, pattern, reference, feedback) {
|
|
780
|
+
return refactorBuildingPromptOf(typeof first === "string" ? {
|
|
781
|
+
pkg: first,
|
|
782
|
+
strays: strays ?? [],
|
|
783
|
+
pattern: pattern ?? "",
|
|
784
|
+
reference,
|
|
785
|
+
feedback
|
|
786
|
+
} : first);
|
|
787
|
+
}
|
|
788
|
+
const refactorBuildingPromptOf = ({ pkg, strays, pattern, reference, feedback = false }) => `${stateFileRules}
|
|
764
789
|
- The package to implement is \`${pkg}\`; never delete it
|
|
765
790
|
${feedback ? `- The package carries a \`## Review feedback\` section: a human's review of the
|
|
766
791
|
last refactor. Act on it, within the rules below
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { read, refuse, removeScript, run, scope, showScript, vars } from "../flows.mjs";
|
|
2
2
|
import { fixFindings, lensesOf, qualityLap as qualityLap$1, reviewToHandOff } from "../workflow-kit.mjs";
|
|
3
|
-
import { E as reviewing, S as fixRisks, T as reviewQuality, W as handOffAwaitReviewMessage, _ as REVIEW, b as fixCheck, c as escalation, d as healthy, m as QUALITY, u as guarded, v as awaitReview, w as reviewMissing, x as fixQuality } from "./reserved-
|
|
3
|
+
import { E as reviewing, S as fixRisks, T as reviewQuality, W as handOffAwaitReviewMessage, _ as REVIEW, b as fixCheck, c as escalation, d as healthy, m as QUALITY, u as guarded, v as awaitReview, w as reviewMissing, x as fixQuality } from "./reserved-fqf-c9dc.mjs";
|
|
4
4
|
//#region src/workflows/shared/tail.ts
|
|
5
5
|
/** The reviewer's own `.gtd/REVIEW.md`, kept beside the human's notes so `fix` can tell them apart. */
|
|
6
6
|
const REVIEW_ORIG = ".gtd/REVIEW.orig.md";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { agent, changes, glob, read, refuse, scope, start, vars } from "../flows.mjs";
|
|
2
|
-
import { _t as registryEntry, a as flagShipped, dt as defaults, ft as envDefaults, ht as flagReferences, i as skills, n as summary, r as access, t as steering, vt as requireFlag, y as coder } from "../chunks/reserved-
|
|
3
|
-
import { i as refusePendingHandOff, r as handOffTail } from "../chunks/tail-
|
|
2
|
+
import { _t as registryEntry, a as flagShipped, dt as defaults, ft as envDefaults, ht as flagReferences, i as skills, n as summary, r as access, t as steering, vt as requireFlag, y as coder } from "../chunks/reserved-fqf-c9dc.mjs";
|
|
3
|
+
import { i as refusePendingHandOff, r as handOffTail } from "../chunks/tail-Do11DVcw.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,7 +1,7 @@
|
|
|
1
1
|
import { answered, changes, changesSince, glob, hasThreadFor, head, human, judge, judgeDiffShape, kept, mark, matches, numeric, quote, read, refuse, removeScript, requireAnswers, requireProgress, requireReplies, requireRevert, requireThreadsClosed, restoreScript, revertScript, run, scope, slice, start, vars } from "../flows.mjs";
|
|
2
2
|
import { lensesOf, review as review$1 } from "../workflow-kit.mjs";
|
|
3
|
-
import { $ as refactorFixPrompt, A as architectureDecomposePrompt, B as designSystem, C as planner, D as agentWithSkills, E as reviewing, F as buildReviewFixNitsPrompt, G as idleMessage, I as buildReviewTriageMessage, J as naivePassPrompt, K as implementBuildingPrompt, L as builderSystem, M as buildReviewAnswerQuestionsPrompt, N as buildReviewAwaitAfterDeferMessage, O as architectSystem, P as buildReviewCollectingPrompt, Q as refactorDroppedRefusal, R as deferNotesScript, S as fixRisks, V as designTriagePrompt, X as packagesItemFixSuitePrompt, Y as packagesItemBuildingPrompt, Z as refactorBuildingPrompt, _ as REVIEW, at as reviewerSystem, b as fixCheck, ct as startGateBlockedMessage, d as healthy, dt as defaults, et as refactorRules, f as ARCHITECTURE, ft as envDefaults, g as REQUIREMENTS, h as REFACTOR, i as skills, it as reviewNotesCapture, j as architectureGateAnswerMessage, k as architectureAuthorPrompt, l as gate, lt as unwindFailedMessage, n as summary, nt as reviewEditsCapture, o as shipped, ot as seamByHandMessage, p as FEEDBACK, pt as testFileGlobs, q as implementFixPrompt, r as access, st as seamSteerMessage, t as steering, tt as reviewEditNotesCapture, u as guarded, ut as unwindFailure, v as awaitReview, w as reviewMissing, y as coder, z as designGateAnswerMessage } from "../chunks/reserved-
|
|
4
|
-
import { a as tail, i as refusePendingHandOff, n as closeReview } from "../chunks/tail-
|
|
3
|
+
import { $ as refactorFixPrompt, A as architectureDecomposePrompt, B as designSystem, C as planner, D as agentWithSkills, E as reviewing, F as buildReviewFixNitsPrompt, G as idleMessage, I as buildReviewTriageMessage, J as naivePassPrompt, K as implementBuildingPrompt, L as builderSystem, M as buildReviewAnswerQuestionsPrompt, N as buildReviewAwaitAfterDeferMessage, O as architectSystem, P as buildReviewCollectingPrompt, Q as refactorDroppedRefusal, R as deferNotesScript, S as fixRisks, V as designTriagePrompt, X as packagesItemFixSuitePrompt, Y as packagesItemBuildingPrompt, Z as refactorBuildingPrompt, _ as REVIEW, at as reviewerSystem, b as fixCheck, ct as startGateBlockedMessage, d as healthy, dt as defaults, et as refactorRules, f as ARCHITECTURE, ft as envDefaults, g as REQUIREMENTS, h as REFACTOR, i as skills, it as reviewNotesCapture, j as architectureGateAnswerMessage, k as architectureAuthorPrompt, l as gate, lt as unwindFailedMessage, n as summary, nt as reviewEditsCapture, o as shipped, ot as seamByHandMessage, p as FEEDBACK, pt as testFileGlobs, q as implementFixPrompt, r as access, st as seamSteerMessage, t as steering, tt as reviewEditNotesCapture, u as guarded, ut as unwindFailure, v as awaitReview, w as reviewMissing, y as coder, z as designGateAnswerMessage } from "../chunks/reserved-fqf-c9dc.mjs";
|
|
4
|
+
import { a as tail, i as refusePendingHandOff, n as closeReview } from "../chunks/tail-Do11DVcw.mjs";
|
|
5
5
|
//#region src/workflows/shared/fences.ts
|
|
6
6
|
const markFenced = (text) => {
|
|
7
7
|
let fence;
|
|
@@ -148,34 +148,86 @@ const deferNotes = (notes, round) => run("review.defer", deferNotesScript(notes,
|
|
|
148
148
|
});
|
|
149
149
|
//#endregion
|
|
150
150
|
//#region src/workflows/feature/packages.ts
|
|
151
|
-
const TEST_LINE =
|
|
152
|
-
|
|
151
|
+
const TEST_LINE = /^-\s+(unit|e2e):\s+`([^`]+)`(.*)$/;
|
|
152
|
+
const MARKER = /^[ \t]+\(unchanged\)(?=\s|$)/i;
|
|
153
|
+
const ITEM = /^\s*-\s/;
|
|
154
|
+
/** The `## Tests` entries of a package file; malformed entries are ignored. */
|
|
153
155
|
const declaredTests = (packageText) => {
|
|
154
156
|
const found = [];
|
|
155
157
|
let inTests = false;
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
const match = TEST_LINE.exec(
|
|
158
|
+
let entry;
|
|
159
|
+
const flush = () => {
|
|
160
|
+
const match = entry === void 0 ? null : TEST_LINE.exec(entry);
|
|
159
161
|
if (match) found.push({
|
|
160
162
|
level: match[1],
|
|
161
|
-
path: match[2]
|
|
163
|
+
path: match[2],
|
|
164
|
+
unchanged: MARKER.test(match[3])
|
|
162
165
|
});
|
|
163
|
-
|
|
166
|
+
entry = void 0;
|
|
167
|
+
};
|
|
168
|
+
for (const line of packageText.replace(/\r\n?/g, "\n").split("\n")) if (/^##\s/.test(line)) {
|
|
169
|
+
flush();
|
|
170
|
+
inTests = /^##\s+Tests\s*$/.test(line);
|
|
171
|
+
} else if (!inTests) continue;
|
|
172
|
+
else if (ITEM.test(line)) {
|
|
173
|
+
flush();
|
|
174
|
+
entry = line.trim();
|
|
175
|
+
} else if (entry !== void 0 && /^\s/.test(line) && line.trim() !== "") entry = `${entry} ${line.trim()}`;
|
|
176
|
+
else flush();
|
|
177
|
+
flush();
|
|
164
178
|
return found;
|
|
165
179
|
};
|
|
180
|
+
const diffBucket = (test, status, turn, satisfied) => {
|
|
181
|
+
if (test.unchanged) {
|
|
182
|
+
if (turn !== "build") return void 0;
|
|
183
|
+
if (status === "modified") return "modifiedMarked";
|
|
184
|
+
return status === "added" ? "addedMarked" : void 0;
|
|
185
|
+
}
|
|
186
|
+
return !satisfied && (status === void 0 || status === "deleted") ? "notInDiff" : void 0;
|
|
187
|
+
};
|
|
188
|
+
const treeBucket = (test, status) => {
|
|
189
|
+
if (read(test.path) !== void 0) return void 0;
|
|
190
|
+
return test.unchanged && status === "deleted" ? "deletedMarked" : "notInTree";
|
|
191
|
+
};
|
|
192
|
+
const unmetBucket = (test, change, turn, satisfied) => diffBucket(test, change?.status, turn, satisfied) ?? treeBucket(test, change?.status);
|
|
166
193
|
/**
|
|
167
194
|
* Refuse a build or fix turn unless every test `pkg` declares exists and is in the
|
|
168
195
|
* diff since `since`. The package text is read as of `since`, so a builder
|
|
169
|
-
* editing its own `## Tests` cannot dodge the guard;
|
|
170
|
-
* written,
|
|
196
|
+
* editing its own `## Tests` (or adding `(unchanged)`) cannot dodge the guard;
|
|
197
|
+
* with `.gtd/SATISFIED.md` written, or the line marked, existing suffices. The
|
|
198
|
+
* build turn must neither modify nor add a marked test; a fix turn may edit it.
|
|
171
199
|
*/
|
|
172
|
-
const requireDeclaredTests = (pkg, since) => {
|
|
200
|
+
const requireDeclaredTests = (pkg, since, turn = "fix") => {
|
|
173
201
|
const range = changesSince(since);
|
|
174
202
|
const text = range.get(pkg)?.before ?? read(pkg) ?? "";
|
|
175
203
|
const satisfied = read(".gtd/SATISFIED.md") !== void 0;
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
204
|
+
const buckets = {
|
|
205
|
+
notInDiff: [],
|
|
206
|
+
modifiedMarked: [],
|
|
207
|
+
addedMarked: [],
|
|
208
|
+
deletedMarked: [],
|
|
209
|
+
notInTree: []
|
|
210
|
+
};
|
|
211
|
+
const entries = declaredTests(text);
|
|
212
|
+
const seen = /* @__PURE__ */ new Set();
|
|
213
|
+
for (const test of entries) {
|
|
214
|
+
if (test.unchanged && entries.some((e) => !e.unchanged && e.path === test.path)) continue;
|
|
215
|
+
const bucket = unmetBucket(test, range.get(test.path), turn, satisfied);
|
|
216
|
+
if (bucket && !seen.has(test.path)) {
|
|
217
|
+
seen.add(test.path);
|
|
218
|
+
buckets[bucket].push(test.path);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
const { notInDiff, modifiedMarked, addedMarked, deletedMarked, notInTree } = buckets;
|
|
222
|
+
const reasons = [
|
|
223
|
+
["not in the package's diff — write them", notInDiff],
|
|
224
|
+
["marked (unchanged) but modified — revert them", modifiedMarked],
|
|
225
|
+
["marked (unchanged) but added by this turn — the marker promises an existing test; stop and leave it to a person", addedMarked],
|
|
226
|
+
["marked (unchanged) but deleted — restore them", deletedMarked],
|
|
227
|
+
["missing from the tree", notInTree]
|
|
228
|
+
].filter(([, paths]) => paths.length > 0);
|
|
229
|
+
if (reasons.length === 0) return;
|
|
230
|
+
refuse(`gtd land: declared-tests: ${pkg} declares tests this turn left unmet:\n${reasons.map(([reason, paths]) => `${reason}:\n${paths.map((path) => ` - ${path}`).join("\n")}`).join("\n")}`);
|
|
179
231
|
};
|
|
180
232
|
/**
|
|
181
233
|
* Build `pkg`, check its declared tests, keep the full suite green, and close
|
|
@@ -183,12 +235,12 @@ const requireDeclaredTests = (pkg, since) => {
|
|
|
183
235
|
*/
|
|
184
236
|
const packageItem = async (pkg) => {
|
|
185
237
|
const from = head();
|
|
186
|
-
const declared = (turn) => async () => {
|
|
238
|
+
const declared = (turn, kind) => async () => {
|
|
187
239
|
await turn();
|
|
188
|
-
requireDeclaredTests(pkg, from);
|
|
240
|
+
requireDeclaredTests(pkg, from, kind);
|
|
189
241
|
};
|
|
190
|
-
await declared(() => build(pkg))();
|
|
191
|
-
await healthy(declared(fixSuite));
|
|
242
|
+
await declared(() => build(pkg), "build")();
|
|
243
|
+
await healthy(declared(fixSuite, "fix"));
|
|
192
244
|
await run("closing", removeScript([
|
|
193
245
|
pkg,
|
|
194
246
|
".gtd/SATISFIED.md",
|
|
@@ -423,8 +475,15 @@ const review = (base, escalations = { rounds: 0 }, options = {}) => {
|
|
|
423
475
|
}
|
|
424
476
|
});
|
|
425
477
|
};
|
|
426
|
-
|
|
427
|
-
const
|
|
478
|
+
function buildTail(first, second, third = false, fourth = {}) {
|
|
479
|
+
const base = typeof first === "string" ? first : second;
|
|
480
|
+
const options = typeof first === "string" ? second ?? {} : {
|
|
481
|
+
...fourth,
|
|
482
|
+
fixFirst: first,
|
|
483
|
+
green: third
|
|
484
|
+
};
|
|
485
|
+
return tail(options.fixFirst ?? false, (escalations) => review(base, escalations, options), options.green ?? false, options.guard, options.lenses, options.guardRests, options.lensBase, options.rules);
|
|
486
|
+
}
|
|
428
487
|
/**
|
|
429
488
|
* Undo the human's review-round code edits. A path changed since the human
|
|
430
489
|
* left it is not overwritten; requireRevert names it instead.
|
|
@@ -565,7 +624,13 @@ const refactorLap = async (p, guard, feedback) => {
|
|
|
565
624
|
label: "Deriving the refactor package",
|
|
566
625
|
file: REFACTOR_PACKAGE
|
|
567
626
|
});
|
|
568
|
-
await agentWithSkills("building", refactorBuildingPrompt(
|
|
627
|
+
await agentWithSkills("building", refactorBuildingPrompt({
|
|
628
|
+
pkg: REFACTOR_PACKAGE,
|
|
629
|
+
strays,
|
|
630
|
+
pattern,
|
|
631
|
+
reference,
|
|
632
|
+
feedback: feedback !== void 0
|
|
633
|
+
}), {
|
|
569
634
|
label: "Refactoring",
|
|
570
635
|
model: coder(),
|
|
571
636
|
system: builderSystem()
|
|
@@ -621,7 +686,8 @@ const reviewedRefactor = async (shape, options = {}) => {
|
|
|
621
686
|
let collected;
|
|
622
687
|
for (;;) {
|
|
623
688
|
await refactorLap(p, guard, collected);
|
|
624
|
-
const outcome = await buildTail(
|
|
689
|
+
const outcome = await buildTail(entry, {
|
|
690
|
+
green: true,
|
|
625
691
|
guard,
|
|
626
692
|
guardRests: false,
|
|
627
693
|
lenses: lensesOf(vars.refactorQualityReviews ?? ""),
|
|
@@ -654,20 +720,27 @@ const naivePass = (rejection) => agentWithSkills("naive", naivePassPrompt(reject
|
|
|
654
720
|
model: coder(),
|
|
655
721
|
system: builderSystem()
|
|
656
722
|
});
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
723
|
+
function implement(first, tier, amend) {
|
|
724
|
+
const options = typeof first === "object" && first !== null ? first : {
|
|
725
|
+
reference: first,
|
|
726
|
+
tier,
|
|
727
|
+
amend
|
|
728
|
+
};
|
|
729
|
+
return scope("implement", async () => {
|
|
730
|
+
await agentWithSkills("building", implementBuildingPrompt(options.reference, options.tier, options.amend), {
|
|
731
|
+
label: "Implementing",
|
|
732
|
+
model: coder(),
|
|
733
|
+
system: builderSystem()
|
|
734
|
+
});
|
|
735
|
+
await healthy(() => agentWithSkills("fix.suite.fixing", implementFixPrompt(), {
|
|
736
|
+
label: "Fixing the check",
|
|
737
|
+
file: FEEDBACK,
|
|
738
|
+
model: coder(),
|
|
739
|
+
system: builderSystem()
|
|
740
|
+
}));
|
|
741
|
+
await run("closing", removeScript([REQUIREMENTS]), { label: "Closing out the implementation" });
|
|
662
742
|
});
|
|
663
|
-
|
|
664
|
-
label: "Fixing the check",
|
|
665
|
-
file: FEEDBACK,
|
|
666
|
-
model: coder(),
|
|
667
|
-
system: builderSystem()
|
|
668
|
-
}));
|
|
669
|
-
await run("closing", removeScript([REQUIREMENTS]), { label: "Closing out the implementation" });
|
|
670
|
-
});
|
|
743
|
+
}
|
|
671
744
|
const decide = () => scope("seam", async () => {
|
|
672
745
|
let rejection;
|
|
673
746
|
let retries = 0;
|
|
@@ -742,7 +815,10 @@ const planAndBuild = async (firstBase, firstLap = "first") => {
|
|
|
742
815
|
await design(base);
|
|
743
816
|
await architecture();
|
|
744
817
|
await packages();
|
|
745
|
-
const outcome = await buildTail(
|
|
818
|
+
const outcome = await buildTail(base, {
|
|
819
|
+
green: true,
|
|
820
|
+
...lap === "first" ? {} : { lap }
|
|
821
|
+
});
|
|
746
822
|
if (outcome.verdict === "signoff") return;
|
|
747
823
|
await reUnwind(outcome);
|
|
748
824
|
base = outcome.base;
|
|
@@ -754,8 +830,14 @@ const naivePlanAndBuild = async (firstBase) => {
|
|
|
754
830
|
const tier = riskTierOn() ? recordRisk() : void 0;
|
|
755
831
|
const seam = await seamBuild(firstBase);
|
|
756
832
|
await slice("feature", async () => {
|
|
757
|
-
await implement(
|
|
758
|
-
|
|
833
|
+
await implement({
|
|
834
|
+
reference: seam.reference,
|
|
835
|
+
tier
|
|
836
|
+
});
|
|
837
|
+
await featureFeedback(await buildTail(seam.base, {
|
|
838
|
+
green: true,
|
|
839
|
+
lensBase: seam.base
|
|
840
|
+
}), seam.base);
|
|
759
841
|
});
|
|
760
842
|
};
|
|
761
843
|
const featureFeedback = async (first, lensBase) => {
|
|
@@ -763,8 +845,12 @@ const featureFeedback = async (first, lensBase) => {
|
|
|
763
845
|
while (outcome.verdict === "feedback") {
|
|
764
846
|
await reUnwind(outcome);
|
|
765
847
|
await design(outcome.base);
|
|
766
|
-
await implement(
|
|
767
|
-
|
|
848
|
+
await implement({
|
|
849
|
+
tier: riskTierOn() ? recordRisk() : void 0,
|
|
850
|
+
amend: true
|
|
851
|
+
});
|
|
852
|
+
outcome = await buildTail(outcome.base, {
|
|
853
|
+
green: true,
|
|
768
854
|
lap: "feedback",
|
|
769
855
|
...lensBase === void 0 ? {} : { lensBase }
|
|
770
856
|
});
|
package/dist/workflows/fix.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { read, refuse, removeScript, run, scope, start } from "../flows.mjs";
|
|
2
2
|
import { d as reviewNotes, f as reviewRisks } from "../chunks/steering-DVILanVf.mjs";
|
|
3
|
-
import { D as agentWithSkills, H as finisherSystem, U as fixReviewNotesPrompt, _ as REVIEW, dt as defaults, ft as envDefaults, i as skills, n as summary, o as shipped, r as access, s as baseline, t as steering, y as coder } from "../chunks/reserved-
|
|
4
|
-
import { r as handOffTail, t as REVIEW_ORIG } from "../chunks/tail-
|
|
3
|
+
import { D as agentWithSkills, H as finisherSystem, U as fixReviewNotesPrompt, _ as REVIEW, dt as defaults, ft as envDefaults, i as skills, n as summary, o as shipped, r as access, s as baseline, t as steering, y as coder } from "../chunks/reserved-fqf-c9dc.mjs";
|
|
4
|
+
import { r as handOffTail, t as REVIEW_ORIG } from "../chunks/tail-Do11DVcw.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,6 +1,6 @@
|
|
|
1
1
|
import { start } from "../flows.mjs";
|
|
2
|
-
import { dt as defaults, ft as envDefaults, i as skills, l as gate, n as summary, o as shipped, r as access, rt as reviewGateBlockedMessage, t as steering } from "../chunks/reserved-
|
|
3
|
-
import { i as refusePendingHandOff, r as handOffTail } from "../chunks/tail-
|
|
2
|
+
import { dt as defaults, ft as envDefaults, i as skills, l as gate, n as summary, o as shipped, r as access, rt as reviewGateBlockedMessage, t as steering } from "../chunks/reserved-fqf-c9dc.mjs";
|
|
3
|
+
import { i as refusePendingHandOff, r as handOffTail } from "../chunks/tail-Do11DVcw.mjs";
|
|
4
4
|
//#region src/workflows/review/review.ts
|
|
5
5
|
/**
|
|
6
6
|
* Pure review of everything since `reviewBase`: a green gate, the quality
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { agent, changesSince, glob, head, mark, read, refuse, removeScript, run, scope, vars } from "../flows.mjs";
|
|
2
|
-
import { a as flagShipped, dt as defaults, ft as envDefaults, gt as flipProblems, i as skills, l as gate, mt as flagMentions, n as summary, p as FEEDBACK, r as access, t as steering, vt as requireFlag, y as coder } from "../chunks/reserved-
|
|
2
|
+
import { a as flagShipped, dt as defaults, ft as envDefaults, gt as flipProblems, i as skills, l as gate, mt as flagMentions, n as summary, p as FEEDBACK, r as access, t as steering, vt as requireFlag, y as coder } from "../chunks/reserved-fqf-c9dc.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.";
|