@pmelab/gtd 38.0.0 → 38.1.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 +6 -0
- package/dist/chunks/{reserved-sfMdy7v7.mjs → reserved-CfQ8eurM.mjs} +55 -11
- package/dist/chunks/{tail-Cgca5Gp-.mjs → tail-C7yaWvaS.mjs} +1 -1
- package/dist/chunks/{wire-CSsa3Wxd.mjs → wire-BJuZWR3C.mjs} +1 -1
- package/dist/gtd.bundle.mjs +1 -1
- package/dist/testkit.mjs +1 -1
- package/dist/wire.mjs +1 -1
- package/dist/workflows/cleanup.mjs +2 -2
- package/dist/workflows/feature.mjs +158 -42
- 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 +230 -70
- package/package.json +1 -1
- package/src/testkit/steps.ts +4 -0
- package/src/wire/ContextLimit.ts +1 -1
- package/src/workflows/feature/continuation-cap.feature +65 -0
- package/src/workflows/feature/continuation-rebuild.feature +88 -0
- package/src/workflows/feature/continuation-slices.feature +64 -0
- package/src/workflows/feature/continuation.feature +205 -0
- package/src/workflows/feature/criteria.ts +11 -0
- package/src/workflows/feature/refactor.ts +64 -30
- package/src/workflows/feature/seam.ts +102 -30
- package/src/workflows/shared/continuation.ts +92 -0
- package/src/workflows/shared/options.ts +2 -0
- package/src/workflows/shared/steps.ts +1 -0
- package/src/workflows/shared/text.test.ts +6 -2
- package/src/workflows/shared/text.ts +104 -8
- package/src/workflows/shared/vars.ts +5 -0
package/README.md
CHANGED
|
@@ -313,6 +313,12 @@ note, past 70% (or when the context is about to be compacted) the turn stops and
|
|
|
313
313
|
nothing lands. A step's `context` option, or the bundled workflows'
|
|
314
314
|
`contextLimit` option, moves the two limits — see
|
|
315
315
|
[Context limits](https://github.com/pmelab/gtd/blob/main/docs/driver.md#context-limits).
|
|
316
|
+
In `feature`, a naive pass, refactor or build turn that wrapped up that way is a
|
|
317
|
+
snapshot: a fresh turn picks up from it with the handoff note and the criteria
|
|
318
|
+
still open, up to 3 times per phase, across its retries (`continuations`), and a
|
|
319
|
+
phase whose continuations keep stopping, or close nothing twice in a row
|
|
320
|
+
(`continuationStall`), rests for a person — see
|
|
321
|
+
[Continuations](https://github.com/pmelab/gtd/blob/main/docs/configuration.md#continuations).
|
|
316
322
|
|
|
317
323
|
### Or drive it from inside Claude Code
|
|
318
324
|
|
|
@@ -136,7 +136,9 @@ const defaults = {
|
|
|
136
136
|
sliceMaxCriteria: "8",
|
|
137
137
|
flag_risk_tier: "0",
|
|
138
138
|
qualityReviews: "correctness, owasp-security, ponytail-review, test-audit, conventions, spec-challenge",
|
|
139
|
-
refactorQualityReviews: "correctness, ponytail-review, conventions"
|
|
139
|
+
refactorQualityReviews: "correctness, ponytail-review, conventions",
|
|
140
|
+
continuations: "3",
|
|
141
|
+
continuationStall: "2"
|
|
140
142
|
};
|
|
141
143
|
/** Environment settings. */
|
|
142
144
|
const envDefaults = {
|
|
@@ -654,7 +656,7 @@ ${strays.map((path) => ` - \`${displayPath(path)}\``).join("\n")}
|
|
|
654
656
|
- Introduce no new flag read and add no second read of an existing one:
|
|
655
657
|
every match of \`${pattern}\` may move, never increase in number`;
|
|
656
658
|
const withRules = (rules) => rules === void 0 ? "" : `${rules}\n`;
|
|
657
|
-
const refactorBuildingPrompt = ({ pkg, strays, pattern, reference, feedback = false, note = false }) => `${stateFileRules}
|
|
659
|
+
const refactorBuildingPrompt = ({ pkg, strays, pattern, reference, feedback = false, note = false, from }) => `${stateFileRules}
|
|
658
660
|
- The package to implement is \`${pkg}\`; never delete it
|
|
659
661
|
${note ? `- The package's \`## Refactor note\` section names the seams to open and the
|
|
660
662
|
shape each takes, written from the whole naive pass: build exactly those
|
|
@@ -669,8 +671,9 @@ ${reference === void 0 ? "" : `- Reference only: \`git show ${reference} -- ${st
|
|
|
669
671
|
restructuring afresh here, minus the feature's own behaviour. A
|
|
670
672
|
refactor that touches none of it is wrong, however clean — never
|
|
671
673
|
swap in an unrelated tidy-up
|
|
672
|
-
`}
|
|
673
|
-
|
|
674
|
+
`}${handoffRule()}
|
|
675
|
+
- Leave everything uncommitted and finish your turn — do not commit
|
|
676
|
+
${from === void 0 ? "" : continuationLines(from)}`;
|
|
674
677
|
const refactorFixPrompt = (strays, pattern) => `${stateFileRules}
|
|
675
678
|
${fixFeedbackPrompt}
|
|
676
679
|
${refactorRules(strays, pattern)}
|
|
@@ -1238,7 +1241,7 @@ Print the closing message and stop — this writes nothing itself.
|
|
|
1238
1241
|
const listed = (paths, unreadable = []) => paths.map((path) => ` - \`${displayPath(path)}\`${unreadable.includes(path) ? " (unreadable)" : ""}`).join("\n");
|
|
1239
1242
|
const isRed = (retry) => "red" in retry;
|
|
1240
1243
|
const isFault = (retry) => "fault" in retry;
|
|
1241
|
-
const pickUp = (hash) => `Pick it up — \`git diff --binary ${hash}^ ${hash} | git apply\``;
|
|
1244
|
+
const pickUp = (hash, exclude) => `Pick it up — \`git diff --binary --no-color --no-ext-diff --no-textconv ${hash}^ ${hash}${exclude === void 0 ? "" : ` -- ${quote(":(top)")} ${quote(`:(top,exclude)${exclude}`)}`} | git apply\``;
|
|
1242
1245
|
const criteriaBinding = (refused) => `- Its \`## Acceptance Criteria\` (\`AC-<n>\`) bind this turn: re-read them from
|
|
1243
1246
|
the file, never from memory, and stop only when each one holds. They are
|
|
1244
1247
|
settled — ${refused ? "a turn that changes them is refused" : "leave them as they are"}`;
|
|
@@ -1257,7 +1260,33 @@ re-implement. It changed these files outside the expected set:
|
|
|
1257
1260
|
${listed(retry.strays)}
|
|
1258
1261
|
Start over and choose a different approach; do not rebuild the same diff.
|
|
1259
1262
|
`;
|
|
1260
|
-
const
|
|
1263
|
+
const quoted = (text) => text.trimEnd().split("\n").map((line) => line === "" ? "" : ` > ${line}`).join("\n");
|
|
1264
|
+
/** Every turn a continuation may pick up tells its agent where the note goes. */
|
|
1265
|
+
const handoffRule = () => `- Should you be told to stop at a context limit, write the handoff note to
|
|
1266
|
+
\`.gtd/HANDOFF.md\` — what you touched, what was next — and finish your turn:
|
|
1267
|
+
a fresh turn picks up from what you leave, broken or not. That file is the one
|
|
1268
|
+
exception to any path rule here; write it at no other time`;
|
|
1269
|
+
/** `pickUp`: how the snapshot gets into the tree — absent when it already is. */
|
|
1270
|
+
const continuationLines = (from, pickUp) => `
|
|
1271
|
+
Your previous turn stopped at its context limit; this fresh turn picks up from
|
|
1272
|
+
its snapshot (\`${from.snapshot}\`). ${pickUp === void 0 ? "Its work is already in the tree." : `${pickUp}.`} Its handoff note:
|
|
1273
|
+
|
|
1274
|
+
${quoted(from.note === "" ? "(empty)" : from.note)}
|
|
1275
|
+
|
|
1276
|
+
Still open: ${from.open.length === 0 ? "nothing the workflow can count — finish what the note says is next" : from.open.join(", ")}.
|
|
1277
|
+
${pickUp === void 0 ? "Delete `.gtd/HANDOFF.md` once you are done; rewrite it should you be stopped again.\n" : ""}`;
|
|
1278
|
+
const oversizedMessage = (phase, from, why, narrowable = true) => `The ${phase} keeps outgrowing its context: ${"cap" in why ? why.cap === 0 ? "continuations are off (`continuations` is 0) and the turn stopped at its context limit" : `${why.cap} continuation${why.cap === 1 ? "" : "s"} ran and the last still stopped at its context limit` : `the last ${why.stall} continuation${why.stall === 1 ? "" : "s"} closed nothing still open`}. The last snapshot is \`${from.snapshot}\`; still open: ${from.open.length === 0 ? "nothing countable" : from.open.join(", ")}.
|
|
1279
|
+
|
|
1280
|
+
Its handoff note:
|
|
1281
|
+
|
|
1282
|
+
${quoted(from.note === "" ? "(empty)" : from.note)}
|
|
1283
|
+
|
|
1284
|
+
Land to go on: a fresh round of continuations picks up from that snapshot${narrowable ? ` — narrow
|
|
1285
|
+
\`.gtd/REQUIREMENTS.md\` first if the change is too big, or raise the context limit` : ` — raise
|
|
1286
|
+
the context limit first if the refactor is too big`}. \`gtd abandon\` gives the change up.
|
|
1287
|
+
`;
|
|
1288
|
+
/** `from`: a continuation of a pass that stopped at its context limit, in place of `retry`'s pick-up. */
|
|
1289
|
+
const naivePassPrompt = (retry, slice, from) => `${stateFileRules}
|
|
1261
1290
|
- Read \`.gtd/REQUIREMENTS.md\`: the settled requirements for this change
|
|
1262
1291
|
${sliceLine(slice)}${criteriaBinding(false)}
|
|
1263
1292
|
- Implement them the quickest way that works — the naive version. Do not
|
|
@@ -1274,9 +1303,20 @@ ${sliceLine(slice)}${criteriaBinding(false)}
|
|
|
1274
1303
|
- Run \`${env.testCommand}\` and finish only once it is green with every
|
|
1275
1304
|
criterion's test passing: the next step runs it on your diff and sends a red
|
|
1276
1305
|
pass back
|
|
1277
|
-
- Leave \`.gtd/\` untouched
|
|
1306
|
+
- Leave \`.gtd/\` untouched, a handoff note excepted
|
|
1307
|
+
${handoffRule()}
|
|
1278
1308
|
- Leave everything uncommitted and finish your turn — do not commit
|
|
1279
|
-
${retry === void 0 ? "" :
|
|
1309
|
+
${from !== void 0 ? `${continuationLines(from, pickUp(from.snapshot, ".gtd/HANDOFF.md"))}${retry === void 0 ? "" : isFault(retry) ? `
|
|
1310
|
+
The pass this continues was a retry: its tests fell short, and still must not:
|
|
1311
|
+
${retry.fault}
|
|
1312
|
+
` : isRed(retry) ? `
|
|
1313
|
+
The pass this continues was a retry after a red suite (\`.gtd/FEEDBACK.md\`
|
|
1314
|
+
holds the output): finish only once the suite is green.
|
|
1315
|
+
` : `
|
|
1316
|
+
The pass this continues was a retry after a \`reject\`: keep away from the
|
|
1317
|
+
approach that changed these files outside the expected set:
|
|
1318
|
+
${listed(retry.strays)}
|
|
1319
|
+
`}` : retry === void 0 ? "" : naiveRetry(retry)}`;
|
|
1280
1320
|
const carries = (rebuild) => (rebuild.acceptance?.ids.length ?? 0) > 0;
|
|
1281
1321
|
const rebuildLines = ({ note, acceptance }) => `${note === void 0 ? "" : `- The refactor note (\`.gtd/REFACTOR-NOTE.md\`) named the seams the refactor
|
|
1282
1322
|
opened; plug the change into them:
|
|
@@ -1313,7 +1353,7 @@ const flagLine = (flagMode, tier, amend, sliced) => !flagMode ? "- Add no releas
|
|
|
1313
1353
|
change added; only when none did, behind a new one, following the
|
|
1314
1354
|
repository's flag conventions` : `- Put the new behaviour behind a new release flag, following the
|
|
1315
1355
|
repository's flag conventions`;
|
|
1316
|
-
const implementBuildingPrompt = (reference, tier, amend, afterRefactor, flagMode = true, rebuild = {}, slice) => `${stateFileRules}
|
|
1356
|
+
const implementBuildingPrompt = (reference, tier, amend, afterRefactor, flagMode = true, rebuild = {}, slice, from) => `${stateFileRules}
|
|
1317
1357
|
- Read \`.gtd/REQUIREMENTS.md\`: the settled requirements for this change
|
|
1318
1358
|
${sliceLine(slice)}${criteriaBinding(true)}
|
|
1319
1359
|
${afterRefactor === true ? afterRefactorLine(rebuild) : ""}${amend === true ? `- The change already exists in the tree from an earlier lap; amend it to meet
|
|
@@ -1328,9 +1368,10 @@ ${afterRefactor === true ? afterRefactorLine(rebuild) : ""}${amend === true ? `-
|
|
|
1328
1368
|
- Write the tests first, then the code that makes them pass. Name each
|
|
1329
1369
|
criterion's ID in the test that covers it (\`[AC-3] …\`): once the suite is
|
|
1330
1370
|
green a judge checks every ID has a passing test, and sends uncovered ones back
|
|
1371
|
+
${handoffRule()}
|
|
1331
1372
|
- Leave \`.gtd/REQUIREMENTS.md\` in place and everything uncommitted, then
|
|
1332
1373
|
finish your turn
|
|
1333
|
-
`;
|
|
1374
|
+
${from === void 0 ? "" : continuationLines(from)}`;
|
|
1334
1375
|
const implementFixPrompt = () => `${stateFileRules}
|
|
1335
1376
|
${fixFeedbackPrompt}
|
|
1336
1377
|
- Leave everything uncommitted and finish your turn — do not commit
|
|
@@ -1435,6 +1476,7 @@ const REFACTOR = ".gtd/REFACTOR.md";
|
|
|
1435
1476
|
const REFACTOR_NOTE = ".gtd/REFACTOR-NOTE.md";
|
|
1436
1477
|
const QUALITY = ".gtd/QUALITY.md";
|
|
1437
1478
|
const SLICES = ".gtd/SLICES.md";
|
|
1479
|
+
const HANDOFF = ".gtd/HANDOFF.md";
|
|
1438
1480
|
const planner = () => env.plannerModel ?? "";
|
|
1439
1481
|
const coder = () => env.coderModel ?? "";
|
|
1440
1482
|
const fixCheck = (rules) => agentWithSkills("fix", buildFixPrompt(rules), {
|
|
@@ -1631,6 +1673,8 @@ const ShippedOptions = Struct({
|
|
|
1631
1673
|
sliceMaxCriteria: setting,
|
|
1632
1674
|
qualityReviews: setting,
|
|
1633
1675
|
refactorQualityReviews: setting,
|
|
1676
|
+
continuations: setting,
|
|
1677
|
+
continuationStall: setting,
|
|
1634
1678
|
testCommand: setting,
|
|
1635
1679
|
plannerModel: setting,
|
|
1636
1680
|
coderModel: setting,
|
|
@@ -1734,4 +1778,4 @@ const steering = {
|
|
|
1734
1778
|
[REVIEW]: "review"
|
|
1735
1779
|
};
|
|
1736
1780
|
//#endregion
|
|
1737
|
-
export {
|
|
1781
|
+
export { naiveApplyFailure as $, agentWithSkills as A, coverageQuestion as B, fixCheck as C, testFileGlobs as Ct, reviewMissing as D, registryEntry as Dt, planner as E, flipProblems as Et, buildReviewTriageMessage as F, designSystem as G, criterionLine as H, builderSystem as I, fixReviewNotesPrompt as J, designTriagePrompt as K, clearCriteriaMessage as L, buildReviewAwaitAfterDeferMessage as M, buildReviewCollectingPrompt as N, reviewQuality as O, requireFlag as Ot, buildReviewFixNitsPrompt as P, implementFixPrompt as Q, clearCriteriaQuestion as R, coder as S, envDefaults as St, fixRisks as T, flagReferences as Tt, deferNotesScript as U, coveringPrompt as V, designGateAnswerMessage as W, idleMessage as X, handOffAwaitReviewMessage as Y, implementBuildingPrompt as Z, REFACTOR_NOTE as _, startGateBlockedMessage as _t, flagModeOn as a, refactorDroppedRefusal as at, SLICES as b, unwindFailure as bt, baseline as c, refactorRules as ct, guarded as d, reviewGateBlockedMessage as dt, naivePassPrompt as et, healthy as f, reviewNotesCapture as ft, REFACTOR as g, slicingPrompt as gt, QUALITY as h, seamSteerMessage as ht, skills as i, refactorBuildingPrompt as it, buildReviewAnswerQuestionsPrompt as j, reviewing as k, escalation as l, reviewEditNotesCapture as lt, HANDOFF as m, seamByHandMessage as mt, summary as n, oversizedMessage as nt, flagShipped as o, refactorFixPrompt as ot, FEEDBACK as p, reviewerSystem as pt, finisherSystem as q, access as r, qualityUnresolvedMessage as rt, shipped as s, refactorNotePrompt as st, steering as t, normaliseCriteriaScript as tt, gate as u, reviewEditsCapture as ut, REQUIREMENTS as v, uncoveredMessage as vt, fixQuality as w, flagMentions as wt, awaitReview as x, defaults as xt, REVIEW as y, unwindFailedMessage as yt, coverageMessage as z };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { read, refuse, removeScript, run, scope, showScript, vars } from "../flows.mjs";
|
|
2
2
|
import { fixFindings, lensEntriesOf, lensOf, qualityLap as qualityLap$1, reviewToHandOff } from "../workflow-kit.mjs";
|
|
3
|
-
import { C as
|
|
3
|
+
import { C as fixCheck, D as reviewMissing, O as reviewQuality, T as fixRisks, Y as handOffAwaitReviewMessage, d as guarded, f as healthy, h as QUALITY, k as reviewing, l as escalation, w as fixQuality, x as awaitReview, y as REVIEW } from "./reserved-CfQ8eurM.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";
|
|
@@ -591,7 +591,7 @@ const contextHook = (input) => {
|
|
|
591
591
|
};
|
|
592
592
|
if (tokens >= limit.soft * window) return {
|
|
593
593
|
kind: "soft",
|
|
594
|
-
reason: `Context limit: ${used} used, past the ${percent(limit.soft)} soft limit. Stop working now. Do not start anything new; end your turn with a short handoff note as your answer: what you touched, and what was next.`
|
|
594
|
+
reason: `Context limit: ${used} used, past the ${percent(limit.soft)} soft limit. Stop working now. Do not start anything new; end your turn with a short handoff note as your answer: what you touched, and what was next. Where your instructions name a file for that note, write it there too.`
|
|
595
595
|
};
|
|
596
596
|
};
|
|
597
597
|
/** A decision as Claude Code's settings-hook JSON output. */
|
package/dist/gtd.bundle.mjs
CHANGED
|
@@ -37839,7 +37839,7 @@ var init_ContextLimit = __esmMin((() => {
|
|
|
37839
37839
|
};
|
|
37840
37840
|
if (tokens >= limit.soft * window) return {
|
|
37841
37841
|
kind: "soft",
|
|
37842
|
-
reason: `Context limit: ${used} used, past the ${percent(limit.soft)} soft limit. Stop working now. Do not start anything new; end your turn with a short handoff note as your answer: what you touched, and what was next.`
|
|
37842
|
+
reason: `Context limit: ${used} used, past the ${percent(limit.soft)} soft limit. Stop working now. Do not start anything new; end your turn with a short handoff note as your answer: what you touched, and what was next. Where your instructions name a file for that note, write it there too.`
|
|
37843
37843
|
};
|
|
37844
37844
|
};
|
|
37845
37845
|
hookOutput = (decision) => decision.kind === "soft" ? {
|
package/dist/testkit.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { applyScript, checkScript, configProblems, configure, installContext, isFactoryWorkflow, moveScript, protocolMismatch, removeScript, restoreScript, revertScript, showScript, t as flows_exports } from "./flows.mjs";
|
|
2
|
-
import { A as beatKindOf, B as ACCESS_REFUSAL, C as renderLandPlain, D as renderBeatJson, E as beatDocument, O as statusOf, S as renderLandJson, T as renderBeatPlain, U as renderFormat, _ as selectPath, a as contextLimitFault, g as resolveSession, h as globMatches, j as demandOf, l as parseContextWindow, m as slicesDocument, o as contextShapeFault, p as renderSlicesJson, v as judgeJson, x as noopText, y as landFields } from "./chunks/wire-
|
|
2
|
+
import { A as beatKindOf, B as ACCESS_REFUSAL, C as renderLandPlain, D as renderBeatJson, E as beatDocument, O as statusOf, S as renderLandJson, T as renderBeatPlain, U as renderFormat, _ as selectPath, a as contextLimitFault, g as resolveSession, h as globMatches, j as demandOf, l as parseContextWindow, m as slicesDocument, o as contextShapeFault, p as renderSlicesJson, v as judgeJson, x as noopText, y as landFields } from "./chunks/wire-BJuZWR3C.mjs";
|
|
3
3
|
import { C as headingSections, S as headingSectionBodies, a as unansweredQuestions, b as parseThreadsWithFindings, n as openThreads, r as steeringFormatFor, s as parseCodeThreads, t as BUILT_IN_MODE_NAMES, w as formatFinding } from "./chunks/steering-DVILanVf.mjs";
|
|
4
4
|
import { $ as logWarning, $i as NodeInspectSymbol, $n as map$5, $r as make$19, $t as provide$1, A as catchIf, Ai as add, An as scopeMake, Ar as flatMap$3, At as suspend$5, B as flatMap$4, Bi as getOrElse, Bn as get$3, Br as sync$1, Bt as unsafeMakeLatch, C as all$1, Ci as toArray, Cn as isInterrupted, Cr as exitFail, Ct as sandbox, D as async, Di as GenericTag, Dn as squash, Dr as exitZipRight, Dt as scopedWith$1, E as asVoid$1, Ei as unsafeHead, En as reduceWithContext, Er as exitVoid, Et as scoped$4, F as ensuring$2, Fi as fromIterable, Fn as join$3, Fr as map$3, Ft as tryMap, G as forkIn, Gi as none, Gn as TypeId$10, Gr as whenEffect, Gt as zipLeft, H as fnUntraced, Hi as isSome, Hn as modify$1, Hr as uninterruptible, Ht as when, I as exit, Ii as splitAt, In as sequential, Ir as onInterrupt, It as tryPromise, J as ignore, Ji as left, Jn as all, Jr as DeferredTypeId$1, Jt as spaced$1, K as forkScoped, Ki as some, Kn as Class, Kr as withFiberRuntime, Kt as zipRight$3, L as fail$5, Li as filter$1, Ln as bind, Lr as scopeClose, Lt as try_, M as die$2, Mi as getOption, Mn as _await$2, Mr as interruptAsFiber, Mt as tap, N as dieMessage, Ni as omit, Nn as inheritAll$1, Nr as interruptFiber, Nt as tapErrorCause, O as catchAll$1, Oi as Reference, On as ensuring$3, Or as fiberId, Ot as serviceOption, P as either, Pi as empty$5, Pn as interruptAllAs$1, Pr as interruptible$1, Pt as timeout, Q as isEffect, Qi as BaseProto, Qn as isFailure, Qr as ids, Qt as mergeAll$2, R as failCause$4, Ri as flatMap$5, Rn as bindTo, Rr as succeed$4, Rt as uninterruptible$1, S as addFinalizer$1, Si as takeRight, Sn as isDieType, Sr as exitAs, St as runtime, T as as, Ti as unsafeGet, Tn as map$6, Tr as exitSucceed, Tt as scopeWith, U as forEach$2, Ui as map$8, Un as set$1, Ur as uninterruptibleMask$1, Ut as withFiberRuntime$1, V as flatten$4, Vi as isNone, Vn as make$16, Vr as tap$1, Vt as unsafeMakeSemaphore$1, W as forkDaemon, Wi as match$4, Wn as update$1, Wr as void_$2, Wt as zip$1, X as interruptible, Xi as right, Xn as fail$4, Xr as combine, Xt as tagged, Y as interrupt$4, Yi as match$2, Yn as die, Yr as empty$6, Yt as TaggedError$1, Z as intoDeferred, Zi as pipeArguments, Zn as failCause$3, Zr as combineAll, Zt as fromEffect$5, _ as decodeSync, _i as of, _n as fail$3, _r as deferredIsDone, _t as raceWith, a as Literal, aa as constTrue, ai as size$2, an as updateContext$1, ar as zipRight$2, at as matchCause, b as acquireRelease, bi as reverse, bn as interrupt$3, br as deferredUnsafeDone, bt as runPromise, c as String$, ca as dual, ci as append$1, cn as Scope, cr as asyncInterrupt, ct as negate, d as Union, di as empty$4, dn as close, dr as deferredAwait, dt as orElse, ea as format, ei as none$1, en as provideMerge$1, er as mapBoth, et as makeSemaphore, f as between, fi as filter, fn as extend, fr as deferredComplete, ft as orElseSucceed, gi as map$7, gn as die$1, gr as deferredInterruptWith, gt as race, hi as isEmpty$2, hn as NoSuchElementException, hr as deferredInterrupt, ht as provideService, i as Defect, ia as constFalse, ii as has, in as unsafeRunPromiseExit, ir as zip$2, it as match$5, j as catchTag, ji as get$5, jn as scopeTag, jr as interrupt$2, jt as sync$2, k as catchAllCause, ki as Tag, kn as forEachConcurrentDiscard, kr as fiberRefLocally, kt as succeed$6, l as Struct, la as identity, li as appendAll, ln as addFinalizer, lr as catchAll, lt as onError, m as optional$1, mi as isChunk, mn as make$18, mr as deferredFailCause, mt as provide$2, n as Boolean$, na as equals, ni as make$17, nn as succeed$3, nr as succeed$5, nt as mapBoth$1, o as Never, oa as constUndefined, oi as decode, on as forkIn$1, or as as$1, ot as matchCauseEffect, p as decodeUnknown, pi as fromIterable$1, pn as fork, pr as deferredFail, pt as promise, q as gen, qi as isLeft, qn as spanTag, qr as zipRight$1, qt as zipWith, r as Cause, ra as hasProperty, ri as set$2, rn as unsafeFork, rr as void_$3, rt as mapError, s as Number$, sa as constVoid, si as isFinite, sn as unsafeMakeSemaphore, sr as asVoid, st as matchEffect, t as Array$, ta as toJSON, ti as get$4, tn as scoped$3, tr as match$3, tt as map$4, u as TaggedError, ua as pipe, ui as drop, un as addFinalizerExit, ur as currentContext$1, ut as orDie, v as encodeSync, vi as prepend, vn as failureOrCause, vr as deferredMake, vt as repeat, w as annotateLogs, wi as unsafeFromArray, wn as isInterruptedOnly, wr as exitFailCause, wt as scope, x as acquireUseRelease$2, xi as take$2, xn as interruptors, xr as deferredUnsafeMake, xt as runPromiseExit$1, y as _void, yi as reduce, yn as flipCauseOption, yr as deferredSucceed, yt as retry, z as fiberIdWith, zi as fromNullable, zn as sleep, zr as suspend$4, zt as uninterruptibleMask } from "./chunks/Schema-DO5ttJaI.mjs";
|
|
5
5
|
import { createRequire } from "node:module";
|
package/dist/wire.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as beatKindOf, B as ACCESS_REFUSAL, C as renderLandPlain, D as renderBeatJson, E as beatDocument, F as EXIT_RUNTIME_ERROR, H as WIRE_SCHEMA, I as EXIT_SIGINT, L as EXIT_SIGTERM, M as stallDiagnosis, N as EXIT_CODES, O as statusOf, P as EXIT_OK, R as EXIT_STRAYS_FOUND, S as renderLandJson, T as renderBeatPlain, U as renderFormat, V as UNATTRIBUTED_MODEL, _ as selectPath, a as contextLimitFault, b as landProseText, c as hookOutput, d as transcriptTokens, f as usageTokens, g as resolveSession, h as globMatches, i as contextHook, j as demandOf, k as BEAT_KINDS, l as parseContextWindow, m as slicesDocument, n as CONTEXT_STOP_FILE_ENV, o as contextShapeFault, p as renderSlicesJson, r as DEFAULT_CONTEXT_LIMIT, s as contextWindowFor, t as CONTEXT_LIMIT_MARKER, u as subagentTranscriptPath, v as judgeJson, w as DEMAND_BRIEFING, x as noopText, y as landFields, z as EXIT_USAGE_ERROR } from "./chunks/wire-
|
|
1
|
+
import { A as beatKindOf, B as ACCESS_REFUSAL, C as renderLandPlain, D as renderBeatJson, E as beatDocument, F as EXIT_RUNTIME_ERROR, H as WIRE_SCHEMA, I as EXIT_SIGINT, L as EXIT_SIGTERM, M as stallDiagnosis, N as EXIT_CODES, O as statusOf, P as EXIT_OK, R as EXIT_STRAYS_FOUND, S as renderLandJson, T as renderBeatPlain, U as renderFormat, V as UNATTRIBUTED_MODEL, _ as selectPath, a as contextLimitFault, b as landProseText, c as hookOutput, d as transcriptTokens, f as usageTokens, g as resolveSession, h as globMatches, i as contextHook, j as demandOf, k as BEAT_KINDS, l as parseContextWindow, m as slicesDocument, n as CONTEXT_STOP_FILE_ENV, o as contextShapeFault, p as renderSlicesJson, r as DEFAULT_CONTEXT_LIMIT, s as contextWindowFor, t as CONTEXT_LIMIT_MARKER, u as subagentTranscriptPath, v as judgeJson, w as DEMAND_BRIEFING, x as noopText, y as landFields, z as EXIT_USAGE_ERROR } from "./chunks/wire-BJuZWR3C.mjs";
|
|
2
2
|
export { ACCESS_REFUSAL, BEAT_KINDS, CONTEXT_LIMIT_MARKER, CONTEXT_STOP_FILE_ENV, DEFAULT_CONTEXT_LIMIT, DEMAND_BRIEFING, EXIT_CODES, EXIT_OK, EXIT_RUNTIME_ERROR, EXIT_SIGINT, EXIT_SIGTERM, EXIT_STRAYS_FOUND, EXIT_USAGE_ERROR, UNATTRIBUTED_MODEL, WIRE_SCHEMA, beatDocument, beatKindOf, contextHook, contextLimitFault, contextShapeFault, contextWindowFor, demandOf, globMatches, hookOutput, judgeJson, landFields, landProseText, noopText, parseContextWindow, renderBeatJson, renderBeatPlain, renderFormat, renderLandJson, renderLandPlain, renderSlicesJson, resolveSession, selectPath, slicesDocument, stallDiagnosis, statusOf, subagentTranscriptPath, transcriptTokens, usageTokens };
|
|
@@ -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 { Dt as registryEntry, Ot as requireFlag, S as coder, St as envDefaults, Tt as flagReferences, i as skills, n as summary, o as flagShipped, r as access, t as steering, xt as defaults } from "../chunks/reserved-CfQ8eurM.mjs";
|
|
3
|
+
import { a as refusePendingHandOff, r as handOffTail } from "../chunks/tail-C7yaWvaS.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 { agent, answered, applyScript, changes, changesSince, check, codeChanges, env, 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, wrote } from "../flows.mjs";
|
|
2
2
|
import { lensEntriesOf, review as review$1 } from "../workflow-kit.mjs";
|
|
3
|
-
import { $ as
|
|
4
|
-
import { a as refusePendingHandOff, i as isOptionalObject, n as closeReview, o as tail } from "../chunks/tail-
|
|
3
|
+
import { $ as naiveApplyFailure, A as agentWithSkills, B as coverageQuestion, C as fixCheck, Ct as testFileGlobs, D as reviewMissing, E as planner, F as buildReviewTriageMessage, G as designSystem, H as criterionLine, I as builderSystem, K as designTriagePrompt, L as clearCriteriaMessage, M as buildReviewAwaitAfterDeferMessage, N as buildReviewCollectingPrompt, P as buildReviewFixNitsPrompt, Q as implementFixPrompt, R as clearCriteriaQuestion, S as coder, St as envDefaults, T as fixRisks, U as deferNotesScript, V as coveringPrompt, W as designGateAnswerMessage, X as idleMessage, Z as implementBuildingPrompt, _ as REFACTOR_NOTE, _t as startGateBlockedMessage, a as flagModeOn, at as refactorDroppedRefusal, b as SLICES, bt as unwindFailure, ct as refactorRules, d as guarded, et as naivePassPrompt, f as healthy, ft as reviewNotesCapture, g as REFACTOR, gt as slicingPrompt, h as QUALITY, ht as seamSteerMessage, i as skills, it as refactorBuildingPrompt, j as buildReviewAnswerQuestionsPrompt, k as reviewing, lt as reviewEditNotesCapture, m as HANDOFF, mt as seamByHandMessage, n as summary, nt as oversizedMessage, ot as refactorFixPrompt, p as FEEDBACK, pt as reviewerSystem, r as access, rt as qualityUnresolvedMessage, s as shipped, st as refactorNotePrompt, t as steering, tt as normaliseCriteriaScript, u as gate, ut as reviewEditsCapture, v as REQUIREMENTS, vt as uncoveredMessage, x as awaitReview, xt as defaults, y as REVIEW, yt as unwindFailedMessage, z as coverageMessage } from "../chunks/reserved-CfQ8eurM.mjs";
|
|
4
|
+
import { a as refusePendingHandOff, i as isOptionalObject, n as closeReview, o as tail } from "../chunks/tail-C7yaWvaS.mjs";
|
|
5
5
|
import { posix } from "node:path";
|
|
6
6
|
//#region src/workflows/shared/fences.ts
|
|
7
7
|
const markFenced = (text) => {
|
|
@@ -145,6 +145,13 @@ const skipDesign = (stated) => stated === void 0 ? Promise.resolve(false) : scop
|
|
|
145
145
|
});
|
|
146
146
|
return true;
|
|
147
147
|
});
|
|
148
|
+
/** After a gate that invites narrowing the requirements: an edit must leave valid criteria. */
|
|
149
|
+
const requireCriteriaIfEdited = () => {
|
|
150
|
+
const change = changes().get(REQUIREMENTS);
|
|
151
|
+
if (change === void 0) return;
|
|
152
|
+
if (change.status === "deleted") refuse(`gtd land: criteria-missing: ${REQUIREMENTS} must stay — narrow its criteria, never delete it`);
|
|
153
|
+
requireCriteria(REQUIREMENTS);
|
|
154
|
+
};
|
|
148
155
|
//#endregion
|
|
149
156
|
//#region src/workflows/feature/tier.ts
|
|
150
157
|
/** GTD_FLAG_RISK_TIER: pinned at process start, so a mid-process flip never moves a process. */
|
|
@@ -493,6 +500,53 @@ const reUnwind = async (feedback) => {
|
|
|
493
500
|
requireRevert(edited, base);
|
|
494
501
|
};
|
|
495
502
|
//#endregion
|
|
503
|
+
//#region src/workflows/shared/continuation.ts
|
|
504
|
+
const phase = (name, steered) => ({
|
|
505
|
+
name,
|
|
506
|
+
spent: false,
|
|
507
|
+
count: 0,
|
|
508
|
+
stalled: 0,
|
|
509
|
+
steered
|
|
510
|
+
});
|
|
511
|
+
const own = (fn) => fn();
|
|
512
|
+
const continued = (fn) => scope("continue", fn);
|
|
513
|
+
const afresh = (fn) => scope("fresh", fn);
|
|
514
|
+
const setting = (name, least) => {
|
|
515
|
+
const raw = vars[name] ?? defaults[name];
|
|
516
|
+
const n = Number(raw);
|
|
517
|
+
if (raw.trim() === "" || !Number.isInteger(n) || n < least) refuse(`gtd: ${name} must be a whole number of at least ${least}, got ${JSON.stringify(raw)}`);
|
|
518
|
+
return n;
|
|
519
|
+
};
|
|
520
|
+
/**
|
|
521
|
+
* Run `turn` until one ends without a handoff note: each stopped turn is picked
|
|
522
|
+
* up by a continuation in a fresh conversation. Past `continuations` of them in
|
|
523
|
+
* the phase, or after `continuationStall` in a row that close nothing still
|
|
524
|
+
* open, the phase rests at `oversized` for a person; landing there grants a new round.
|
|
525
|
+
*/
|
|
526
|
+
const continuing = async (phase, turn) => {
|
|
527
|
+
const cap = setting("continuations", 0);
|
|
528
|
+
const stall = setting("continuationStall", 1);
|
|
529
|
+
let last = await turn(void 0, phase.spent ? afresh : own);
|
|
530
|
+
while (last.handoff !== void 0) {
|
|
531
|
+
phase.spent = true;
|
|
532
|
+
const from = last.handoff;
|
|
533
|
+
if (phase.count >= cap || phase.stalled >= stall) {
|
|
534
|
+
await human("oversized", {
|
|
535
|
+
message: oversizedMessage(phase.name, from, phase.count >= cap ? { cap } : { stall }, phase.steered !== void 0),
|
|
536
|
+
label: "Too big for its context",
|
|
537
|
+
acceptClean: true
|
|
538
|
+
});
|
|
539
|
+
phase.steered?.();
|
|
540
|
+
phase.count = 0;
|
|
541
|
+
phase.stalled = 0;
|
|
542
|
+
}
|
|
543
|
+
last = await turn(from, continued);
|
|
544
|
+
phase.count++;
|
|
545
|
+
phase.stalled = from.open.length === 0 || from.open.some((item) => !(last.handoff?.open ?? []).includes(item)) ? 0 : phase.stalled + 1;
|
|
546
|
+
}
|
|
547
|
+
return last.result;
|
|
548
|
+
};
|
|
549
|
+
//#endregion
|
|
496
550
|
//#region src/workflows/feature/refactor.ts
|
|
497
551
|
const REFACTOR_PACKAGE = REFACTOR;
|
|
498
552
|
const isCode = (path) => path !== ".gtd" && !path.startsWith(".gtd/");
|
|
@@ -638,7 +692,7 @@ const guardOf = ({ pattern, strays }, entry) => () => {
|
|
|
638
692
|
requireNoNewFlags(pattern, entry);
|
|
639
693
|
};
|
|
640
694
|
/** Derive, build, check and close one refactor lap; `feedback` is the collected review text of the lap before. */
|
|
641
|
-
const refactorLap = async (p, guard, feedback) => {
|
|
695
|
+
const refactorLap = async (p, guard, refactor, feedback) => {
|
|
642
696
|
const { pattern, strays, reference, note } = p;
|
|
643
697
|
await run("deriving", deriveScript([
|
|
644
698
|
...packageLines(strays, pattern, reference),
|
|
@@ -658,32 +712,48 @@ const refactorLap = async (p, guard, feedback) => {
|
|
|
658
712
|
label: "Deriving the refactor package",
|
|
659
713
|
file: REFACTOR_PACKAGE
|
|
660
714
|
});
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
guard();
|
|
674
|
-
await healthy(async () => {
|
|
675
|
-
await agentWithSkills("fix.suite.fixing", refactorFixPrompt(strays, pattern), {
|
|
676
|
-
label: "Fixing the check",
|
|
677
|
-
file: FEEDBACK,
|
|
715
|
+
const reached = /* @__PURE__ */ new Set();
|
|
716
|
+
await continuing(refactor, async (from, fresh) => {
|
|
717
|
+
await fresh(() => agentWithSkills("building", refactorBuildingPrompt({
|
|
718
|
+
pkg: REFACTOR_PACKAGE,
|
|
719
|
+
strays,
|
|
720
|
+
pattern,
|
|
721
|
+
reference,
|
|
722
|
+
feedback: feedback !== void 0,
|
|
723
|
+
note: note !== void 0,
|
|
724
|
+
from
|
|
725
|
+
}), {
|
|
726
|
+
label: from === void 0 ? "Refactoring" : "Continuing the refactor",
|
|
678
727
|
model: coder(),
|
|
679
728
|
system: builderSystem()
|
|
680
|
-
});
|
|
729
|
+
}));
|
|
730
|
+
const left = read(HANDOFF);
|
|
681
731
|
guard();
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
732
|
+
const snapshot = head();
|
|
733
|
+
for (const c of changes()) reached.add(c.path);
|
|
734
|
+
await healthy(async () => {
|
|
735
|
+
await agentWithSkills("fix.suite.fixing", refactorFixPrompt(strays, pattern), {
|
|
736
|
+
label: "Fixing the check",
|
|
737
|
+
file: FEEDBACK,
|
|
738
|
+
model: coder(),
|
|
739
|
+
system: builderSystem()
|
|
740
|
+
});
|
|
741
|
+
guard();
|
|
742
|
+
}, {
|
|
743
|
+
describeGuard: guard,
|
|
744
|
+
rules: refactorRules(strays, pattern)
|
|
745
|
+
});
|
|
746
|
+
if (left === void 0) return { result: void 0 };
|
|
747
|
+
return {
|
|
748
|
+
result: void 0,
|
|
749
|
+
handoff: {
|
|
750
|
+
snapshot,
|
|
751
|
+
note: left.trim(),
|
|
752
|
+
open: strays.filter((path) => !reached.has(path))
|
|
753
|
+
}
|
|
754
|
+
};
|
|
685
755
|
});
|
|
686
|
-
await run("closing", removeScript([REFACTOR_PACKAGE]), { label: "Closing out the refactor" });
|
|
756
|
+
await run("closing", removeScript([REFACTOR_PACKAGE, HANDOFF]), { label: "Closing out the refactor" });
|
|
687
757
|
};
|
|
688
758
|
const strayAccess = (strays) => ({ write: [
|
|
689
759
|
...strays,
|
|
@@ -697,7 +767,7 @@ const refactorFirst = async (shape, options = {}) => {
|
|
|
697
767
|
name: "refactor",
|
|
698
768
|
access: strayAccess(p.strays)
|
|
699
769
|
}, async () => {
|
|
700
|
-
await refactorLap(p, guardOf(p, head()));
|
|
770
|
+
await refactorLap(p, guardOf(p, head()), phase("refactor"));
|
|
701
771
|
return true;
|
|
702
772
|
});
|
|
703
773
|
};
|
|
@@ -722,9 +792,10 @@ const reviewedRefactor = async (shape, options = {}) => {
|
|
|
722
792
|
unmatched: "gtd land: refactor-feedback: the review feedback changed files but wrote no .gtd/REFACTOR.md — a refactor cannot act on it; revert the change, or `gtd abandon` and restart",
|
|
723
793
|
dropped: refactorDroppedRefusal
|
|
724
794
|
};
|
|
795
|
+
const refactor = phase("refactor");
|
|
725
796
|
let collected;
|
|
726
797
|
for (;;) {
|
|
727
|
-
await refactorLap(p, guard, collected);
|
|
798
|
+
await refactorLap(p, guard, refactor, collected);
|
|
728
799
|
const outcome = await buildTail(entry, {
|
|
729
800
|
green: true,
|
|
730
801
|
guard,
|
|
@@ -835,12 +906,32 @@ const judgeSeam = (tip) => judgeDiffShape("judge", {
|
|
|
835
906
|
allow: (vars.seamAllow ?? defaults.seamAllow).split(",").map((glob) => glob.trim()).filter((glob) => glob !== ""),
|
|
836
907
|
exempt: tip.changes.filter((c) => c.status === "added").map((c) => c.path)
|
|
837
908
|
});
|
|
838
|
-
const naivePass = (retry, slice) => agentWithSkills("naive", naivePassPrompt(retry, sliceIds(slice)), {
|
|
839
|
-
label: retry === void 0 ? "Writing the naive pass" : "Rewriting the naive pass",
|
|
909
|
+
const naivePass = (retry, slice, from) => agentWithSkills("naive", naivePassPrompt(retry, sliceIds(slice), from), {
|
|
910
|
+
label: from !== void 0 ? "Continuing the naive pass" : retry === void 0 ? "Writing the naive pass" : "Rewriting the naive pass",
|
|
840
911
|
keep: true,
|
|
841
912
|
model: coder(),
|
|
842
913
|
system: builderSystem()
|
|
843
914
|
});
|
|
915
|
+
const handoffOf = (tip, slice) => {
|
|
916
|
+
const note = tip.changes.find((c) => c.path === ".gtd/HANDOFF.md" && c.after !== void 0);
|
|
917
|
+
if (note === void 0) return void 0;
|
|
918
|
+
return {
|
|
919
|
+
snapshot: tip.hash,
|
|
920
|
+
note: note.after.trim(),
|
|
921
|
+
open: unnamed(idsOf(REQUIREMENTS, slice), acceptanceTests(tip.changes))
|
|
922
|
+
};
|
|
923
|
+
};
|
|
924
|
+
/** A naive pass, continued until a pass ends without a handoff note: the snapshot is its kept tip. */
|
|
925
|
+
const naiveContinued = (retry, slice, naive) => continuing(naive, async (from, fresh) => {
|
|
926
|
+
const tip = await fresh(async () => {
|
|
927
|
+
await naivePass(retry, slice, from);
|
|
928
|
+
return kept("naive");
|
|
929
|
+
});
|
|
930
|
+
return {
|
|
931
|
+
result: tip,
|
|
932
|
+
handoff: handoffOf(tip, slice)
|
|
933
|
+
};
|
|
934
|
+
});
|
|
844
935
|
const IMPORTED = /(?:\bfrom|\bimport|\brequire\s*\(|\bmock\s*\()\s*\(?\s*(["'`])([^"'`\n]+)\1/g;
|
|
845
936
|
const EXTENSION = /\.[\w-]+$/;
|
|
846
937
|
const ALIAS = /^(?:[@~]\/|#)/;
|
|
@@ -968,6 +1059,32 @@ const applied = async (tip) => {
|
|
|
968
1059
|
await run("applying", applyScript(tip, FEEDBACK, naiveApplyFailure(tip), [".gtd"]), { label: "Applying the naive pass" });
|
|
969
1060
|
return !wrote(".gtd/FEEDBACK.md") && codeChanges().length > 0;
|
|
970
1061
|
};
|
|
1062
|
+
/** `carried` limited to the criteria `.gtd/REQUIREMENTS.md` lists now; a file listing none narrows nothing. */
|
|
1063
|
+
const settled = (carried, slice) => {
|
|
1064
|
+
const listed = idsOf(REQUIREMENTS, slice);
|
|
1065
|
+
if (carried === void 0) return listed;
|
|
1066
|
+
return listed.length === 0 ? carried : carried.filter((id) => listed.includes(id));
|
|
1067
|
+
};
|
|
1068
|
+
const build = (options) => continuing(phase("build", requireCriteriaIfEdited), async (from, fresh) => {
|
|
1069
|
+
await fresh(() => agentWithSkills("building", implementBuildingPrompt(options.reference, options.tier, options.amend, options.afterRefactor, flagModeOn(), options.rebuild, sliceIds(options.slice), from), {
|
|
1070
|
+
label: from === void 0 ? "Implementing" : "Continuing the implementation",
|
|
1071
|
+
model: coder(),
|
|
1072
|
+
system: builderSystem(),
|
|
1073
|
+
...options.afterRefactor === true ? { allowEmpty: true } : {}
|
|
1074
|
+
}));
|
|
1075
|
+
requireCriteriaFrozen(REQUIREMENTS);
|
|
1076
|
+
const note = read(HANDOFF);
|
|
1077
|
+
if (note === void 0) return { result: void 0 };
|
|
1078
|
+
const ids = settled(options.rebuild?.acceptance?.ids, options.slice);
|
|
1079
|
+
return {
|
|
1080
|
+
result: void 0,
|
|
1081
|
+
handoff: {
|
|
1082
|
+
snapshot: head(),
|
|
1083
|
+
note: note.trim(),
|
|
1084
|
+
open: unnamed(ids, acceptanceTests(changesSince(start())))
|
|
1085
|
+
}
|
|
1086
|
+
};
|
|
1087
|
+
});
|
|
971
1088
|
function implement(first, tier, amend) {
|
|
972
1089
|
const options = typeof first === "object" && first !== null ? first : {
|
|
973
1090
|
reference: first,
|
|
@@ -978,14 +1095,12 @@ function implement(first, tier, amend) {
|
|
|
978
1095
|
const since = head();
|
|
979
1096
|
const acceptance = options.rebuild?.acceptance;
|
|
980
1097
|
const built = options.naive === void 0 || !await applied(options.naive);
|
|
981
|
-
if (built) await
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
});
|
|
987
|
-
requireCriteriaFrozen(REQUIREMENTS);
|
|
988
|
-
if (built && acceptance !== void 0) requireAcceptance(acceptance, since);
|
|
1098
|
+
if (built) await build(options);
|
|
1099
|
+
else requireCriteriaFrozen(REQUIREMENTS);
|
|
1100
|
+
if (built && acceptance !== void 0) requireAcceptance({
|
|
1101
|
+
...acceptance,
|
|
1102
|
+
ids: settled(acceptance.ids, options.slice)
|
|
1103
|
+
}, since);
|
|
989
1104
|
await green(built && acceptance !== void 0 ? () => requireAcceptanceKept(acceptance) : void 0);
|
|
990
1105
|
await requireCoverage(options.base, options.slice);
|
|
991
1106
|
await closing(options.more === true);
|
|
@@ -994,10 +1109,11 @@ function implement(first, tier, amend) {
|
|
|
994
1109
|
/** The last slice's closing, for a last slice a steer left with no criterion to build. */
|
|
995
1110
|
const closeOut = () => scope("implement", () => closing(false));
|
|
996
1111
|
/** A slice with `more` after it keeps the criteria and the slicing for the next one. */
|
|
997
|
-
const closing = (more) => run("closing", removeScript(more ? [REFACTOR_NOTE] : [
|
|
1112
|
+
const closing = (more) => run("closing", removeScript(more ? [REFACTOR_NOTE, HANDOFF] : [
|
|
998
1113
|
REQUIREMENTS,
|
|
999
1114
|
REFACTOR_NOTE,
|
|
1000
|
-
SLICES
|
|
1115
|
+
SLICES,
|
|
1116
|
+
HANDOFF
|
|
1001
1117
|
]), { label: "Closing out the implementation" });
|
|
1002
1118
|
/** Resolves `true` when the human steered (edited), `false` on a clean overrule. */
|
|
1003
1119
|
const steer = async (retry) => {
|
|
@@ -1069,10 +1185,10 @@ const decide = (slice) => scope("seam", async () => {
|
|
|
1069
1185
|
again: budget(),
|
|
1070
1186
|
waived: false
|
|
1071
1187
|
};
|
|
1188
|
+
const naive = phase("naive pass", requireCriteriaIfEdited);
|
|
1072
1189
|
let retry;
|
|
1073
1190
|
for (;;) {
|
|
1074
|
-
await
|
|
1075
|
-
const tip = kept("naive");
|
|
1191
|
+
const tip = await naiveContinued(retry, slice, naive);
|
|
1076
1192
|
const outcome = await vetted(tip, vetting, slice) ?? (flagModeOn() ? await ruled(tip, vetting.again) : {
|
|
1077
1193
|
reference: tip.hash,
|
|
1078
1194
|
tip
|
|
@@ -1328,4 +1444,4 @@ const feature = shipped(ordinaryStart);
|
|
|
1328
1444
|
//#region src/workflows/feature/index.ts
|
|
1329
1445
|
var feature_default = feature;
|
|
1330
1446
|
//#endregion
|
|
1331
|
-
export { COMMENT, REFACTOR_PACKAGE, acceptanceFault, access, afterTail, answerProductQuestions, answerReviewQuestions, buildFeature, buildTail, closeOut, collecting, criteriaOf, criterionIds, feature_default as default, defaults, deferNotes, design, envDefaults, feature, fixNits, holdsCallSites, implement, isTestFile, judgeSeam, naiveAcceptance, naivePass, ordinaryStart, planAndBuild, reUnwind, refactorCollecting, refactorFirst, refactorNote, refactorStrays, requireAcceptance, requireAcceptanceKept, requireCriteria, requireCriteriaFrozen, requireNoNewFlags, requireNoTestFiles, requireSlices, requireTestCallSitesOnly, requireWithin, reviewedRefactor, seamBuild, skills, skipDesign, sliceCap, sliceCriteria, sliceIds, slicesOf, slicing, statedCriteria, steering, summary, triage, unwind };
|
|
1447
|
+
export { COMMENT, REFACTOR_PACKAGE, acceptanceFault, access, afterTail, answerProductQuestions, answerReviewQuestions, buildFeature, buildTail, closeOut, collecting, criteriaOf, criterionIds, feature_default as default, defaults, deferNotes, design, envDefaults, feature, fixNits, holdsCallSites, implement, isTestFile, judgeSeam, naiveAcceptance, naivePass, ordinaryStart, planAndBuild, reUnwind, refactorCollecting, refactorFirst, refactorNote, refactorStrays, requireAcceptance, requireAcceptanceKept, requireCriteria, requireCriteriaFrozen, requireCriteriaIfEdited, requireNoNewFlags, requireNoTestFiles, requireSlices, requireTestCallSitesOnly, requireWithin, reviewedRefactor, seamBuild, skills, skipDesign, sliceCap, sliceCriteria, sliceIds, slicesOf, slicing, statedCriteria, steering, summary, triage, unwind };
|
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 {
|
|
4
|
-
import { r as handOffTail, t as REVIEW_ORIG } from "../chunks/tail-
|
|
3
|
+
import { A as agentWithSkills, J as fixReviewNotesPrompt, S as coder, St as envDefaults, c as baseline, i as skills, n as summary, q as finisherSystem, r as access, s as shipped, t as steering, xt as defaults, y as REVIEW } from "../chunks/reserved-CfQ8eurM.mjs";
|
|
4
|
+
import { r as handOffTail, t as REVIEW_ORIG } from "../chunks/tail-C7yaWvaS.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 {
|
|
3
|
-
import { a as refusePendingHandOff, r as handOffTail } from "../chunks/tail-
|
|
2
|
+
import { St as envDefaults, dt as reviewGateBlockedMessage, i as skills, n as summary, r as access, s as shipped, t as steering, u as gate, xt as defaults } from "../chunks/reserved-CfQ8eurM.mjs";
|
|
3
|
+
import { a as refusePendingHandOff, r as handOffTail } from "../chunks/tail-C7yaWvaS.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 { Et as requireFlag,
|
|
2
|
+
import { Et as flipProblems, Ot as requireFlag, S as coder, St as envDefaults, i as skills, n as summary, o as flagShipped, p as FEEDBACK, r as access, t as steering, u as gate, wt as flagMentions, xt as defaults } from "../chunks/reserved-CfQ8eurM.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.";
|