@pmelab/gtd 36.0.0 → 37.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 +21 -9
- package/claude/hooks/context.ts +66 -0
- package/claude/hooks/drive.ts +3 -0
- package/claude/hooks/register.tsx +69 -6
- package/dist/chunks/{reserved-BAv71I4i.mjs → reserved-zAfoJtR7.mjs} +53 -16
- package/dist/chunks/{tail-kar1zhOb.mjs → tail-BRC4DGdV.mjs} +1 -1
- package/dist/chunks/{wire-D3Rc5r22.mjs → wire-CSsa3Wxd.mjs} +117 -2
- package/dist/gtd.bundle.mjs +498 -56
- package/dist/testkit.mjs +115 -3
- package/dist/wire.mjs +2 -2
- package/dist/workflows/cleanup.mjs +2 -2
- package/dist/workflows/feature.mjs +126 -33
- 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 +174 -44
- package/package.json +1 -1
- package/src/cli/Cli.test.ts +10 -3
- package/src/cli/Cli.ts +76 -1
- package/src/cli/Program.test.ts +1 -0
- package/src/cli/Program.ts +28 -0
- package/src/cli/ToolCommands.ts +3 -0
- package/src/edge/Edge.ts +11 -0
- package/src/flows/runtime.ts +11 -0
- package/src/replay/Replay.ts +51 -2
- package/src/testkit/Layers.ts +1 -0
- package/src/wire/BeatDocument.ts +12 -2
- package/src/wire/BeatStatus.ts +3 -0
- package/src/wire/ContextLimit.fixture.ts +30 -0
- package/src/wire/ContextLimit.test.ts +96 -0
- package/src/wire/ContextLimit.ts +169 -0
- package/src/wire/index.ts +1 -0
- package/src/wire/types.ts +7 -0
- package/src/workflow/Workflow.ts +9 -1
- package/src/workflows/feature/context-limit.feature +37 -0
- package/src/workflows/feature/coverage.ts +8 -2
- package/src/workflows/feature/feature.ts +6 -2
- package/src/workflows/feature/refactor-absorbs.feature +12 -5
- package/src/workflows/feature/refactor-first.feature +11 -2
- package/src/workflows/feature/refactor-lens-models.feature +4 -0
- package/src/workflows/feature/refactor-rebuild.feature +269 -0
- package/src/workflows/feature/refactor-review.feature +45 -1
- package/src/workflows/feature/refactor.ts +9 -3
- package/src/workflows/feature/seam.test.ts +108 -3
- package/src/workflows/feature/seam.ts +120 -19
- package/src/workflows/shared/options.test.ts +11 -2
- package/src/workflows/shared/options.ts +18 -4
- package/src/workflows/shared/steps.ts +1 -0
- package/src/workflows/shared/text.ts +80 -14
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 {
|
|
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-CSsa3Wxd.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";
|
|
@@ -7128,6 +7128,15 @@ const budgeted = (evidence, budgetBytes) => {
|
|
|
7128
7128
|
truncated
|
|
7129
7129
|
};
|
|
7130
7130
|
};
|
|
7131
|
+
const scopeLabel = (chain) => {
|
|
7132
|
+
const path = chain.flatMap((o) => o.name === void 0 ? [] : [o.name]).join(".");
|
|
7133
|
+
if (chain.at(-1)?.name !== void 0) return `scope "${path}"`;
|
|
7134
|
+
return path === "" ? "an unnamed scope" : `an unnamed scope inside "${path}"`;
|
|
7135
|
+
};
|
|
7136
|
+
const inheritedContext = (layers) => layers.reduce((merged, layer) => layer === void 0 ? merged : {
|
|
7137
|
+
...merged,
|
|
7138
|
+
...Object.fromEntries(Object.entries(layer).filter(([, value]) => value !== void 0))
|
|
7139
|
+
}, void 0);
|
|
7131
7140
|
const sameSkills = (a, b) => (a?.length ?? 0) === (b?.length ?? 0) && (a ?? []).every((skill, i) => skill === b?.[i]);
|
|
7132
7141
|
const samePersona = (a, b) => a.model === b.model && a.system === b.system && sameSkills(a.skills, b.skills) && sameAccess(a.access, b.access);
|
|
7133
7142
|
/**
|
|
@@ -7147,6 +7156,7 @@ const KNOWN_OPTIONS = {
|
|
|
7147
7156
|
...STEERING_OPTIONS,
|
|
7148
7157
|
"model",
|
|
7149
7158
|
"system",
|
|
7159
|
+
"context",
|
|
7150
7160
|
"allowEmpty",
|
|
7151
7161
|
"keep"
|
|
7152
7162
|
]),
|
|
@@ -7261,11 +7271,13 @@ const replay = async (input) => {
|
|
|
7261
7271
|
if (s.model !== void 0) persona.model = s.model;
|
|
7262
7272
|
if (s.system !== void 0) persona.system = s.system;
|
|
7263
7273
|
}
|
|
7274
|
+
const context = inheritedContext([...scopes.map((s) => s.context), request.options.context]);
|
|
7264
7275
|
return {
|
|
7265
7276
|
...request,
|
|
7266
7277
|
options: {
|
|
7267
7278
|
...persona,
|
|
7268
|
-
...request.options
|
|
7279
|
+
...request.options,
|
|
7280
|
+
...context === void 0 ? {} : { context }
|
|
7269
7281
|
}
|
|
7270
7282
|
};
|
|
7271
7283
|
}
|
|
@@ -7403,10 +7415,26 @@ const replay = async (input) => {
|
|
|
7403
7415
|
});
|
|
7404
7416
|
return landPending(step, input.pending);
|
|
7405
7417
|
};
|
|
7418
|
+
const scopeContextFault = () => {
|
|
7419
|
+
for (const [i, s] of scopes.entries()) {
|
|
7420
|
+
const fault = s.context === void 0 ? void 0 : contextShapeFault(s.context);
|
|
7421
|
+
if (fault !== void 0) return `the context of ${scopeLabel(scopes.slice(0, i + 1))}: ${fault}`;
|
|
7422
|
+
}
|
|
7423
|
+
};
|
|
7424
|
+
const resolvedContextFault = (request) => {
|
|
7425
|
+
const own = request.options.context;
|
|
7426
|
+
const layered = scopeContextFault() ?? (own === void 0 ? void 0 : contextShapeFault(own));
|
|
7427
|
+
if (layered !== void 0) return layered;
|
|
7428
|
+
const resolved = resolve(request);
|
|
7429
|
+
const context = resolved.kind === "agent" ? resolved.options.context : void 0;
|
|
7430
|
+
return context === void 0 ? void 0 : contextLimitFault(context);
|
|
7431
|
+
};
|
|
7406
7432
|
const requestFault = (request) => {
|
|
7407
7433
|
if (request.kind === "run" && typeof request.body !== "string") return `gtd: step "${scoped(request.name)}": a run() body is a shell script string — decide in flow code, then render the script (see checkScript and friends)`;
|
|
7408
7434
|
if (request.kind !== "agent") return void 0;
|
|
7409
7435
|
const name = scoped(request.name);
|
|
7436
|
+
const contextFault = resolvedContextFault(request);
|
|
7437
|
+
if (contextFault !== void 0) return `gtd: step "${name}": ${contextFault}`;
|
|
7410
7438
|
if (request.options.keep === true) {
|
|
7411
7439
|
if (request.options.allowEmpty === true) return `gtd: step "${name}": keep: true cannot be combined with allowEmpty — a turn that changes nothing has nothing to keep`;
|
|
7412
7440
|
const refFault = name.includes("/") ? "it contains \"/\"" : refNameFault(name);
|
|
@@ -9016,6 +9044,10 @@ const commonOf = (step) => {
|
|
|
9016
9044
|
...optional("mode", options.mode)
|
|
9017
9045
|
};
|
|
9018
9046
|
};
|
|
9047
|
+
const stepContext = (context) => context === void 0 ? void 0 : {
|
|
9048
|
+
...optional("soft", context.soft),
|
|
9049
|
+
...optional("hard", context.hard)
|
|
9050
|
+
};
|
|
9019
9051
|
const promptDef = (common, request, skills, access) => ({
|
|
9020
9052
|
...common,
|
|
9021
9053
|
kind: "prompt",
|
|
@@ -9024,6 +9056,7 @@ const promptDef = (common, request, skills, access) => ({
|
|
|
9024
9056
|
...optional("system", request.options.system),
|
|
9025
9057
|
...optional("allowEmpty", request.options.allowEmpty),
|
|
9026
9058
|
...optional("keep", request.options.keep),
|
|
9059
|
+
...optional("context", stepContext(request.options.context)),
|
|
9027
9060
|
...optional("skills", skills),
|
|
9028
9061
|
...optional("access", access)
|
|
9029
9062
|
});
|
|
@@ -9109,7 +9142,8 @@ const hintsOf = (def) => ({
|
|
|
9109
9142
|
...optional("system", def.system),
|
|
9110
9143
|
...optional("mode", def.mode),
|
|
9111
9144
|
...optional("skills", def.skills),
|
|
9112
|
-
...optional("access", def.access)
|
|
9145
|
+
...optional("access", def.access),
|
|
9146
|
+
...optional("context", def.context)
|
|
9113
9147
|
});
|
|
9114
9148
|
const normalizeStatus = (raw) => raw === "A" ? "A" : raw === "D" ? "D" : "M";
|
|
9115
9149
|
/** Per-model token totals, highest-cost first (ties broken by model name). */
|
|
@@ -10390,6 +10424,17 @@ const readStdin = () => tryPromise({
|
|
|
10390
10424
|
},
|
|
10391
10425
|
catch: (e) => e instanceof Error ? e : new Error(String(e))
|
|
10392
10426
|
});
|
|
10427
|
+
/** Stdout is written once: a hook reads one JSON document, or none. */
|
|
10428
|
+
const runContextHookCommand = (command, out) => gen(function* () {
|
|
10429
|
+
const tools = yield* ToolCommands;
|
|
10430
|
+
const input = yield* readStdin();
|
|
10431
|
+
out.write(yield* tools.contextHook({
|
|
10432
|
+
input,
|
|
10433
|
+
...command.soft !== void 0 ? { soft: command.soft } : {},
|
|
10434
|
+
...command.hard !== void 0 ? { hard: command.hard } : {},
|
|
10435
|
+
...command.window !== void 0 ? { window: command.window } : {}
|
|
10436
|
+
}));
|
|
10437
|
+
});
|
|
10393
10438
|
/** Stdout is written once, after the answerer resolves — a rejection leaves it empty. */
|
|
10394
10439
|
const runJudgeRunCommand = (command, out) => gen(function* () {
|
|
10395
10440
|
const host = yield* Host;
|
|
@@ -10846,6 +10891,7 @@ const needsOf = (kind) => {
|
|
|
10846
10891
|
case "lsp":
|
|
10847
10892
|
case "install":
|
|
10848
10893
|
case "loop":
|
|
10894
|
+
case "contextHook":
|
|
10849
10895
|
case "judgeRun":
|
|
10850
10896
|
case "strays": return "none";
|
|
10851
10897
|
case "check":
|
|
@@ -10885,6 +10931,7 @@ const dispatchVoidCommand = (command, json, out) => {
|
|
|
10885
10931
|
case "uncheck": return runUncheckCommand(command.file);
|
|
10886
10932
|
case "install": return runInstallCommand(out);
|
|
10887
10933
|
case "loop": return runLoopCommand();
|
|
10934
|
+
case "contextHook": return runContextHookCommand(command, out);
|
|
10888
10935
|
case "summary": return runSummaryCommand(out, command.slice);
|
|
10889
10936
|
case "base": return runBaseCommand(out);
|
|
10890
10937
|
case "judge": return runJudgeCommand(json, out);
|
|
@@ -10926,6 +10973,10 @@ const nonNegativeNumber = (raw, flag) => {
|
|
|
10926
10973
|
if (raw.trim() === "" || !Number.isFinite(n) || n < 0) return left(`gtd: ${flag} must be a non-negative number — got "${raw}"`);
|
|
10927
10974
|
return right(n);
|
|
10928
10975
|
};
|
|
10976
|
+
const share = (raw, flag) => {
|
|
10977
|
+
const n = Number(raw);
|
|
10978
|
+
return raw.trim() !== "" && n > 0 && n <= 1 ? right(n) : left(`gtd: ${flag} must be a share of the context window in (0, 1] — got "${raw}"`);
|
|
10979
|
+
};
|
|
10929
10980
|
const FLAGS = [
|
|
10930
10981
|
{
|
|
10931
10982
|
name: "--json",
|
|
@@ -11053,6 +11104,39 @@ const FLAGS = [
|
|
|
11053
11104
|
"GTD_JUDGE_MODEL, then judge.json, then sonnet"
|
|
11054
11105
|
]
|
|
11055
11106
|
},
|
|
11107
|
+
{
|
|
11108
|
+
name: "--soft",
|
|
11109
|
+
arity: 1,
|
|
11110
|
+
repeatable: false,
|
|
11111
|
+
scope: (kind) => kind === "contextHook",
|
|
11112
|
+
decode: ([raw]) => share(raw ?? "", "--soft"),
|
|
11113
|
+
scopeError: "gtd: --soft is only valid for `gtd context-hook`",
|
|
11114
|
+
valueHint: "<share>",
|
|
11115
|
+
help: ["(gtd context-hook only) the soft limit; default 0.6"]
|
|
11116
|
+
},
|
|
11117
|
+
{
|
|
11118
|
+
name: "--hard",
|
|
11119
|
+
arity: 1,
|
|
11120
|
+
repeatable: false,
|
|
11121
|
+
scope: (kind) => kind === "contextHook",
|
|
11122
|
+
decode: ([raw]) => share(raw ?? "", "--hard"),
|
|
11123
|
+
scopeError: "gtd: --hard is only valid for `gtd context-hook`",
|
|
11124
|
+
valueHint: "<share>",
|
|
11125
|
+
help: ["(gtd context-hook only) the hard limit; default 0.7"]
|
|
11126
|
+
},
|
|
11127
|
+
{
|
|
11128
|
+
name: "--window",
|
|
11129
|
+
arity: 1,
|
|
11130
|
+
repeatable: false,
|
|
11131
|
+
scope: (kind) => kind === "contextHook",
|
|
11132
|
+
decode: ([raw]) => {
|
|
11133
|
+
const window = parseContextWindow(raw);
|
|
11134
|
+
return window !== void 0 ? right(window) : left(`gtd: --window must be a positive integer — got "${raw ?? ""}"`);
|
|
11135
|
+
},
|
|
11136
|
+
scopeError: "gtd: --window is only valid for `gtd context-hook`",
|
|
11137
|
+
valueHint: "<tokens>",
|
|
11138
|
+
help: ["(gtd context-hook only) the model's context window in", "tokens; default 200000"]
|
|
11139
|
+
},
|
|
11056
11140
|
{
|
|
11057
11141
|
name: "--slice",
|
|
11058
11142
|
arity: 1,
|
|
@@ -11359,6 +11443,22 @@ const COMMAND_ROWS = [
|
|
|
11359
11443
|
"~/.config/gtd/loop.json); see docs/driver.md"
|
|
11360
11444
|
]
|
|
11361
11445
|
},
|
|
11446
|
+
{
|
|
11447
|
+
token: "context-hook",
|
|
11448
|
+
kind: "contextHook",
|
|
11449
|
+
arity: "none",
|
|
11450
|
+
details: [
|
|
11451
|
+
"A Claude Code PostToolUse and PreCompact hook that stops an",
|
|
11452
|
+
"agent turn at a share of its context window. Reads the",
|
|
11453
|
+
"hook's input on stdin and the context the transcript's",
|
|
11454
|
+
"latest assistant message used. Past --soft it blocks with a",
|
|
11455
|
+
"request to end the turn with a handoff note; past --hard,",
|
|
11456
|
+
"or at PreCompact, it stops the turn with a stopReason",
|
|
11457
|
+
"starting \"gtd: context limit\". Prints nothing otherwise,",
|
|
11458
|
+
"and for a subagent's tool call. Always exits 0 on valid",
|
|
11459
|
+
"input; see docs/driver.md"
|
|
11460
|
+
]
|
|
11461
|
+
},
|
|
11362
11462
|
{
|
|
11363
11463
|
token: "summary",
|
|
11364
11464
|
kind: "summary",
|
|
@@ -11837,6 +11937,17 @@ const parseArgv = (argv) => {
|
|
|
11837
11937
|
verbose
|
|
11838
11938
|
};
|
|
11839
11939
|
}
|
|
11940
|
+
if (kind === "contextHook") return {
|
|
11941
|
+
kind: "command",
|
|
11942
|
+
command: {
|
|
11943
|
+
kind: "contextHook",
|
|
11944
|
+
...bag["--soft"] !== void 0 ? { soft: bag["--soft"] } : {},
|
|
11945
|
+
...bag["--hard"] !== void 0 ? { hard: bag["--hard"] } : {},
|
|
11946
|
+
...bag["--window"] !== void 0 ? { window: bag["--window"] } : {}
|
|
11947
|
+
},
|
|
11948
|
+
json,
|
|
11949
|
+
verbose
|
|
11950
|
+
};
|
|
11840
11951
|
if (kind === "summary") return {
|
|
11841
11952
|
kind: "command",
|
|
11842
11953
|
command: {
|
|
@@ -12615,6 +12726,7 @@ const missingToolCommands = {
|
|
|
12615
12726
|
ui: missingTool("ui"),
|
|
12616
12727
|
lsp: missingTool("lsp"),
|
|
12617
12728
|
loop: missingTool("loop"),
|
|
12729
|
+
contextHook: missingTool("context-hook"),
|
|
12618
12730
|
judge: () => Promise.reject(/* @__PURE__ */ new Error("gtd judge run: ToolCommands has no test double wired into testLayers()"))
|
|
12619
12731
|
};
|
|
12620
12732
|
/** The fine-grained `GitService` layer alone — for unit tests that need only git. */
|
package/dist/wire.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
export { ACCESS_REFUSAL, BEAT_KINDS, 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, demandOf, globMatches, judgeJson, landFields, landProseText, noopText, renderBeatJson, renderBeatPlain, renderFormat, renderLandJson, renderLandPlain, renderSlicesJson, resolveSession, selectPath, slicesDocument, stallDiagnosis, statusOf };
|
|
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-CSsa3Wxd.mjs";
|
|
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 { Ct as registryEntry, _t as defaults, b as coder, i as skills, n as summary, o as flagShipped, r as access, t as steering, vt as envDefaults, wt as requireFlag, xt as flagReferences } from "../chunks/reserved-zAfoJtR7.mjs";
|
|
3
|
+
import { a as refusePendingHandOff, r as handOffTail } from "../chunks/tail-BRC4DGdV.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
|
-
import { 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";
|
|
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 normaliseCriteriaScript, A as buildReviewAwaitAfterDeferMessage, B as criterionLine, C as fixRisks, D as reviewing, F as clearCriteriaMessage, H as designGateAnswerMessage, I as clearCriteriaQuestion, J as idleMessage, L as coverageMessage, M as buildReviewFixNitsPrompt, N as buildReviewTriageMessage, O as agentWithSkills, P as builderSystem, Q as naivePassPrompt, R as coverageQuestion, T as reviewMissing, U as designSystem, V as deferNotesScript, W as designTriagePrompt, X as implementFixPrompt, Y as implementBuildingPrompt, Z as naiveApplyFailure, _ as REQUIREMENTS, _t as defaults, a as flagModeOn, at as refactorRules, b as coder, d as guarded, dt as seamByHandMessage, et as qualityUnresolvedMessage, f as healthy, ft as seamSteerMessage, g as REFACTOR_NOTE, gt as unwindFailure, h as REFACTOR, ht as unwindFailedMessage, i as skills, it as refactorNotePrompt, j as buildReviewCollectingPrompt, k as buildReviewAnswerQuestionsPrompt, lt as reviewNotesCapture, m as QUALITY, mt as uncoveredMessage, n as summary, nt as refactorDroppedRefusal, ot as reviewEditNotesCapture, p as FEEDBACK, pt as startGateBlockedMessage, r as access, rt as refactorFixPrompt, s as shipped, st as reviewEditsCapture, t as steering, tt as refactorBuildingPrompt, u as gate, ut as reviewerSystem, v as REVIEW, vt as envDefaults, w as planner, x as fixCheck, y as awaitReview, yt as testFileGlobs, z as coveringPrompt } from "../chunks/reserved-zAfoJtR7.mjs";
|
|
4
|
+
import { a as refusePendingHandOff, i as isOptionalObject, n as closeReview, o as tail } from "../chunks/tail-BRC4DGdV.mjs";
|
|
5
5
|
import { posix } from "node:path";
|
|
6
6
|
//#region src/workflows/shared/fences.ts
|
|
7
7
|
const markFenced = (text) => {
|
|
@@ -623,7 +623,8 @@ const plan = (shape, options) => {
|
|
|
623
623
|
return {
|
|
624
624
|
pattern,
|
|
625
625
|
strays,
|
|
626
|
-
reference: options.reference?.trim() ? options.reference : void 0
|
|
626
|
+
reference: options.reference?.trim() ? options.reference : void 0,
|
|
627
|
+
note: options.note?.trim() ? options.note : void 0
|
|
627
628
|
};
|
|
628
629
|
};
|
|
629
630
|
const guardOf = ({ pattern, strays }, entry) => () => {
|
|
@@ -632,13 +633,22 @@ const guardOf = ({ pattern, strays }, entry) => () => {
|
|
|
632
633
|
};
|
|
633
634
|
/** Derive, build, check and close one refactor lap; `feedback` is the collected review text of the lap before. */
|
|
634
635
|
const refactorLap = async (p, guard, feedback) => {
|
|
635
|
-
const { pattern, strays, reference } = p;
|
|
636
|
-
await run("deriving", deriveScript([
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
636
|
+
const { pattern, strays, reference, note } = p;
|
|
637
|
+
await run("deriving", deriveScript([
|
|
638
|
+
...packageLines(strays, pattern, reference),
|
|
639
|
+
...note === void 0 ? [] : [
|
|
640
|
+
"## Refactor note",
|
|
641
|
+
"",
|
|
642
|
+
...demoteHeadings(note),
|
|
643
|
+
""
|
|
644
|
+
],
|
|
645
|
+
...feedback === void 0 ? [] : [
|
|
646
|
+
"## Review feedback",
|
|
647
|
+
"",
|
|
648
|
+
...demoteHeadings(feedback),
|
|
649
|
+
""
|
|
650
|
+
]
|
|
651
|
+
]), {
|
|
642
652
|
label: "Deriving the refactor package",
|
|
643
653
|
file: REFACTOR_PACKAGE
|
|
644
654
|
});
|
|
@@ -647,7 +657,8 @@ const refactorLap = async (p, guard, feedback) => {
|
|
|
647
657
|
strays,
|
|
648
658
|
pattern,
|
|
649
659
|
reference,
|
|
650
|
-
feedback: feedback !== void 0
|
|
660
|
+
feedback: feedback !== void 0,
|
|
661
|
+
note: note !== void 0
|
|
651
662
|
}), {
|
|
652
663
|
label: "Refactoring",
|
|
653
664
|
model: coder(),
|
|
@@ -733,13 +744,16 @@ const COVERED_MIN_P = .7;
|
|
|
733
744
|
/** Covering turns before the process rests at `uncovered`; a human edit there refills them. */
|
|
734
745
|
const COVERING_RETRIES = 2;
|
|
735
746
|
const frozen = () => requireCriteriaFrozen(REQUIREMENTS);
|
|
736
|
-
const green = () => healthy(() => agentWithSkills("fix.suite.fixing", implementFixPrompt(), {
|
|
747
|
+
const green = (guard) => healthy(() => agentWithSkills("fix.suite.fixing", implementFixPrompt(), {
|
|
737
748
|
label: "Fixing the check",
|
|
738
749
|
file: FEEDBACK,
|
|
739
750
|
model: coder(),
|
|
740
751
|
system: builderSystem()
|
|
741
752
|
}), {
|
|
742
|
-
guard:
|
|
753
|
+
guard: () => {
|
|
754
|
+
frozen();
|
|
755
|
+
guard?.();
|
|
756
|
+
},
|
|
743
757
|
guardRests: false
|
|
744
758
|
});
|
|
745
759
|
const testsSince = (base) => changesSince(base).filter((c) => c.after !== void 0 && isCode$1(c.path) && isTestFile(c.path)).sort((a, b) => Number(/\bAC-\d/.test(a.after)) - Number(/\bAC-\d/.test(b.after))).map((c) => `=== ${c.path} (${c.status})\n${c.after}`).join("\n");
|
|
@@ -853,16 +867,20 @@ const addedLines = (change) => {
|
|
|
853
867
|
const before = new Set((change.before ?? "").split("\n"));
|
|
854
868
|
return change.after.split("\n").filter((line) => !before.has(line)).join("\n");
|
|
855
869
|
};
|
|
870
|
+
const acceptanceTests = (changes) => changes.filter((c) => c.after !== void 0 && isCode$1(c.path) && isTestFile(c.path));
|
|
871
|
+
const idsOf = (file) => (criteriaOf(read(file) ?? "") ?? []).map((c) => c.id).filter((id) => id !== "");
|
|
872
|
+
const unnamed = (ids, tests) => {
|
|
873
|
+
const lines = tests.map(addedLines);
|
|
874
|
+
return ids.filter((id) => !lines.some((text) => named(id, text)));
|
|
875
|
+
};
|
|
856
876
|
/**
|
|
857
877
|
* Why `tip`'s tests fall short, or `undefined`: a criterion ID of `file` no
|
|
858
878
|
* test line of the pass names, or a test importing a file the pass added —
|
|
859
879
|
* naive structure a reset and refactor replaces, which the tests must survive.
|
|
860
880
|
*/
|
|
861
881
|
const acceptanceFault = (file, tip) => {
|
|
862
|
-
const
|
|
863
|
-
const
|
|
864
|
-
const lines = tests.map(addedLines);
|
|
865
|
-
const untested = ids.filter((id) => !lines.some((text) => named(id, text)));
|
|
882
|
+
const tests = acceptanceTests(tip.changes);
|
|
883
|
+
const untested = unnamed(idsOf(file), tests);
|
|
866
884
|
if (untested.length > 0) return `acceptance-tests: no test of the naive pass names ${untested.join(", ")} — write a behaviour-level test for each criterion with its ID in the test or scenario name, e.g. "[${untested[0]}] …"`;
|
|
867
885
|
const added = tip.changes.filter((c) => c.status === "added" && isCode$1(c.path) && !isTestFile(c.path)).map((c) => c.path);
|
|
868
886
|
const reaching = tests.filter((test) => holdsCallSites(test.path)).flatMap((test) => {
|
|
@@ -871,6 +889,41 @@ const acceptanceFault = (file, tip) => {
|
|
|
871
889
|
});
|
|
872
890
|
if (reaching.length > 0) return `acceptance-internals: these tests import files the naive pass added — test through code that existed before it (a public entry point, an existing module's exports):\n${reaching.join("\n")}`;
|
|
873
891
|
};
|
|
892
|
+
/** What a rebuild carries over from the naive pass `tip`: the IDs its tests name, and those test files. */
|
|
893
|
+
const naiveAcceptance = (tip) => {
|
|
894
|
+
const ids = idsOf(REQUIREMENTS);
|
|
895
|
+
const perTest = acceptanceTests(tip.changes).map((c) => {
|
|
896
|
+
const lines = addedLines(c);
|
|
897
|
+
return {
|
|
898
|
+
path: c.path,
|
|
899
|
+
ids: ids.filter((id) => named(id, lines))
|
|
900
|
+
};
|
|
901
|
+
});
|
|
902
|
+
return {
|
|
903
|
+
hash: tip.hash,
|
|
904
|
+
tests: perTest.filter((c) => c.ids.length > 0).map((c) => c.path),
|
|
905
|
+
ids: ids.filter((id) => perTest.some((c) => c.ids.includes(id)))
|
|
906
|
+
};
|
|
907
|
+
};
|
|
908
|
+
/**
|
|
909
|
+
* Refuse a rebuild whose test changes since `since` leave out an ID the naive
|
|
910
|
+
* pass's tests named. A skipped test still counts: the gate reads text, never runs it.
|
|
911
|
+
*/
|
|
912
|
+
const requireAcceptance = (acceptance, since) => {
|
|
913
|
+
const missing = unnamed(acceptance.ids, acceptanceTests(changesSince(since)));
|
|
914
|
+
if (missing.length === 0) return;
|
|
915
|
+
refuse(`gtd land: rebuild-acceptance: the rebuild's tests leave out ${missing.join(", ")} — carry over the naive pass's acceptance tests (\`git show ${acceptance.hash} -- ${acceptance.tests.map(quote).join(" ")}\`), each with its ID in the test or scenario name`);
|
|
916
|
+
};
|
|
917
|
+
/**
|
|
918
|
+
* Refuse a fix turn that, on its own, drops an ID the naive pass's tests named
|
|
919
|
+
* from a test file. Turn-local, so a person's edit at an escalation rest never
|
|
920
|
+
* wedges later fix turns.
|
|
921
|
+
*/
|
|
922
|
+
const requireAcceptanceKept = (acceptance) => {
|
|
923
|
+
const dropped = acceptance.ids.filter((id) => changes().filter((c) => isCode$1(c.path) && isTestFile(c.path)).some((c) => named(id, c.before ?? "") && !named(id, c.after ?? "")));
|
|
924
|
+
if (dropped.length === 0) return;
|
|
925
|
+
refuse(`gtd land: rebuild-acceptance: this turn drops ${dropped.join(", ")} from the tests — the naive pass's acceptance tests stay; fix the code, not them`);
|
|
926
|
+
};
|
|
874
927
|
const restore = (path) => `if git cat-file -e ${quote(`HEAD:${path}`)} 2>/dev/null; then git checkout -q HEAD -- ${quote(path)}; else rm -f -- ${quote(path)}; fi`;
|
|
875
928
|
/**
|
|
876
929
|
* Run the suite with `tip`'s diff applied, then take it out again; resolves
|
|
@@ -914,16 +967,20 @@ function implement(first, tier, amend) {
|
|
|
914
967
|
amend
|
|
915
968
|
};
|
|
916
969
|
return scope("implement", async () => {
|
|
917
|
-
|
|
970
|
+
const since = head();
|
|
971
|
+
const acceptance = options.rebuild?.acceptance;
|
|
972
|
+
const built = options.naive === void 0 || !await applied(options.naive);
|
|
973
|
+
if (built) await agentWithSkills("building", implementBuildingPrompt(options.reference, options.tier, options.amend, options.afterRefactor, flagModeOn(), options.rebuild), {
|
|
918
974
|
label: "Implementing",
|
|
919
975
|
model: coder(),
|
|
920
976
|
system: builderSystem(),
|
|
921
977
|
...options.afterRefactor === true ? { allowEmpty: true } : {}
|
|
922
978
|
});
|
|
923
979
|
requireCriteriaFrozen(REQUIREMENTS);
|
|
924
|
-
|
|
980
|
+
if (built && acceptance !== void 0) requireAcceptance(acceptance, since);
|
|
981
|
+
await green(built && acceptance !== void 0 ? () => requireAcceptanceKept(acceptance) : void 0);
|
|
925
982
|
await requireCoverage();
|
|
926
|
-
await run("closing", removeScript([REQUIREMENTS]), { label: "Closing out the implementation" });
|
|
983
|
+
await run("closing", removeScript([REQUIREMENTS, REFACTOR_NOTE]), { label: "Closing out the implementation" });
|
|
927
984
|
});
|
|
928
985
|
}
|
|
929
986
|
/** Resolves `true` when the human steered (edited), `false` on a clean overrule. */
|
|
@@ -973,16 +1030,23 @@ const vetted = async (tip, vetting) => {
|
|
|
973
1030
|
/** The judge's ruling on a vetted pass: the decision, or the next attempt's verdict. */
|
|
974
1031
|
const ruled = async (tip, again) => {
|
|
975
1032
|
const shape = await judgeSeam(tip);
|
|
976
|
-
if (shape.choice === "land") return {
|
|
1033
|
+
if (shape.choice === "land") return {
|
|
1034
|
+
reference: tip.hash,
|
|
1035
|
+
tip
|
|
1036
|
+
};
|
|
977
1037
|
if (shape.choice === "refactor-first") return {
|
|
978
1038
|
reference: tip.hash,
|
|
1039
|
+
tip,
|
|
979
1040
|
shape
|
|
980
1041
|
};
|
|
981
1042
|
const next = await again({
|
|
982
1043
|
strays: shape.strays,
|
|
983
1044
|
p: shape.judgment?.answers.shape?.p ?? 0
|
|
984
1045
|
});
|
|
985
|
-
return next.kind === "overruled" ? {
|
|
1046
|
+
return next.kind === "overruled" ? {
|
|
1047
|
+
reference: tip.hash,
|
|
1048
|
+
tip
|
|
1049
|
+
} : next;
|
|
986
1050
|
};
|
|
987
1051
|
const decide = () => scope("seam", async () => {
|
|
988
1052
|
const vetting = {
|
|
@@ -993,13 +1057,29 @@ const decide = () => scope("seam", async () => {
|
|
|
993
1057
|
for (;;) {
|
|
994
1058
|
await naivePass(retry);
|
|
995
1059
|
const tip = kept("naive");
|
|
996
|
-
const outcome = await vetted(tip, vetting) ?? (flagModeOn() ? await ruled(tip, vetting.again) : {
|
|
1060
|
+
const outcome = await vetted(tip, vetting) ?? (flagModeOn() ? await ruled(tip, vetting.again) : {
|
|
1061
|
+
reference: tip.hash,
|
|
1062
|
+
tip
|
|
1063
|
+
});
|
|
997
1064
|
if (!("kind" in outcome)) return outcome;
|
|
998
1065
|
retry = outcome.kind === "retry" ? outcome.retry : void 0;
|
|
999
1066
|
}
|
|
1000
1067
|
});
|
|
1068
|
+
/** Write the refactor note from the whole naive pass; a turn that changes anything else is refused. */
|
|
1069
|
+
const refactorNote = async (reference, strays) => {
|
|
1070
|
+
await agent("note", refactorNotePrompt(reference, strays), {
|
|
1071
|
+
label: "Writing the refactor note",
|
|
1072
|
+
file: REFACTOR_NOTE,
|
|
1073
|
+
model: coder(),
|
|
1074
|
+
system: builderSystem()
|
|
1075
|
+
});
|
|
1076
|
+
const others = changes().map((c) => c.path).filter((path) => path !== REFACTOR_NOTE);
|
|
1077
|
+
const note = read(".gtd/REFACTOR-NOTE.md") ?? "";
|
|
1078
|
+
if (others.length > 0 || note.trim() === "") refuse(`gtd land: refactor-note: write ${REFACTOR_NOTE} and change nothing else${others.length > 0 ? ` — revert these:\n${others.map((path) => ` - ${path}`).join("\n")}` : ""}`);
|
|
1079
|
+
return note;
|
|
1080
|
+
};
|
|
1001
1081
|
const seamBuild = async (base) => {
|
|
1002
|
-
const { reference, shape } = await decide();
|
|
1082
|
+
const { reference, tip, shape } = await decide();
|
|
1003
1083
|
if (shape === void 0) return {
|
|
1004
1084
|
reference,
|
|
1005
1085
|
base,
|
|
@@ -1013,18 +1093,29 @@ const seamBuild = async (base) => {
|
|
|
1013
1093
|
}));
|
|
1014
1094
|
return {
|
|
1015
1095
|
reference,
|
|
1016
|
-
base
|
|
1096
|
+
base,
|
|
1097
|
+
rebuild: { acceptance: naiveAcceptance(tip) }
|
|
1017
1098
|
};
|
|
1018
1099
|
}
|
|
1019
|
-
|
|
1100
|
+
const strays = refactorStrays(shape);
|
|
1101
|
+
if (strays.length === 0) return {
|
|
1020
1102
|
reference,
|
|
1021
|
-
base
|
|
1103
|
+
base,
|
|
1104
|
+
rebuild: { acceptance: naiveAcceptance(tip) }
|
|
1022
1105
|
};
|
|
1023
|
-
const
|
|
1106
|
+
const note = await scope("seam", () => refactorNote(reference, strays));
|
|
1107
|
+
const refactored = await slice("refactor", () => reviewedRefactor(shape, {
|
|
1108
|
+
reference,
|
|
1109
|
+
note
|
|
1110
|
+
}));
|
|
1024
1111
|
return {
|
|
1025
1112
|
reference,
|
|
1026
1113
|
base: head(),
|
|
1027
|
-
refactored
|
|
1114
|
+
refactored,
|
|
1115
|
+
rebuild: {
|
|
1116
|
+
note,
|
|
1117
|
+
acceptance: naiveAcceptance(tip)
|
|
1118
|
+
}
|
|
1028
1119
|
};
|
|
1029
1120
|
};
|
|
1030
1121
|
//#endregion
|
|
@@ -1043,9 +1134,11 @@ const buildFeature = async (firstBase) => {
|
|
|
1043
1134
|
reference: seam.reference,
|
|
1044
1135
|
tier,
|
|
1045
1136
|
afterRefactor: seam.refactored,
|
|
1046
|
-
naive: seam.land === true ? seam.reference : void 0
|
|
1137
|
+
naive: seam.land === true ? seam.reference : void 0,
|
|
1138
|
+
rebuild: seam.rebuild
|
|
1047
1139
|
});
|
|
1048
|
-
const
|
|
1140
|
+
const carried = seam.rebuild?.acceptance?.tests ?? [];
|
|
1141
|
+
const base = seam.refactored === true && !changesSince(seam.base).some((c) => isCode$1(c.path) && !carried.includes(c.path)) ? firstBase : seam.base;
|
|
1049
1142
|
await tail(settleQuality, {
|
|
1050
1143
|
green: true,
|
|
1051
1144
|
lensBase: base
|
|
@@ -1109,4 +1202,4 @@ const feature = shipped(ordinaryStart);
|
|
|
1109
1202
|
//#region src/workflows/feature/index.ts
|
|
1110
1203
|
var feature_default = feature;
|
|
1111
1204
|
//#endregion
|
|
1112
|
-
export { COMMENT, REFACTOR_PACKAGE, acceptanceFault, access, afterTail, answerProductQuestions, answerReviewQuestions, buildFeature, buildTail, collecting, criteriaOf, feature_default as default, defaults, deferNotes, design, envDefaults, feature, fixNits, holdsCallSites, implement, isTestFile, judgeSeam, naivePass, ordinaryStart, planAndBuild, reUnwind, refactorCollecting, refactorFirst, refactorStrays, requireCriteria, requireCriteriaFrozen, requireNoNewFlags, requireNoTestFiles, requireTestCallSitesOnly, requireWithin, reviewedRefactor, seamBuild, skills, skipDesign, statedCriteria, steering, summary, triage, unwind };
|
|
1205
|
+
export { COMMENT, REFACTOR_PACKAGE, acceptanceFault, access, afterTail, answerProductQuestions, answerReviewQuestions, buildFeature, buildTail, collecting, criteriaOf, 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, requireTestCallSitesOnly, requireWithin, reviewedRefactor, seamBuild, skills, skipDesign, 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 { G as finisherSystem, K as fixReviewNotesPrompt, O as agentWithSkills, _t as defaults, b as coder, c as baseline, i as skills, n as summary, r as access, s as shipped, t as steering, v as REVIEW, vt as envDefaults } from "../chunks/reserved-zAfoJtR7.mjs";
|
|
4
|
+
import { r as handOffTail, t as REVIEW_ORIG } from "../chunks/tail-BRC4DGdV.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 { _t as defaults, ct as reviewGateBlockedMessage, i as skills, n as summary, r as access, s as shipped, t as steering, u as gate, vt as envDefaults } from "../chunks/reserved-zAfoJtR7.mjs";
|
|
3
|
+
import { a as refusePendingHandOff, r as handOffTail } from "../chunks/tail-BRC4DGdV.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 { St as
|
|
2
|
+
import { St as flipProblems, _t as defaults, b as coder, bt as flagMentions, i as skills, n as summary, o as flagShipped, p as FEEDBACK, r as access, t as steering, u as gate, vt as envDefaults, wt as requireFlag } from "../chunks/reserved-zAfoJtR7.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.";
|