@pmelab/gtd 35.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 +45 -29
- 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-C8Fm3s72.mjs → reserved-zAfoJtR7.mjs} +62 -24
- package/dist/chunks/{tail-oaYewBN_.mjs → tail-BRC4DGdV.mjs} +1 -1
- package/dist/chunks/{wire-D3Rc5r22.mjs → wire-CSsa3Wxd.mjs} +117 -2
- package/dist/flows.mjs +15 -10
- package/dist/gtd.bundle.mjs +511 -64
- package/dist/testkit.mjs +158 -26
- package/dist/wire.mjs +2 -2
- package/dist/workflows/cleanup.mjs +2 -2
- package/dist/workflows/feature.mjs +138 -38
- 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 +208 -66
- package/package.json +1 -1
- package/skills/authoring/SKILL.md +3 -3
- 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/flows/scripts.ts +31 -9
- package/src/replay/Replay.ts +51 -2
- package/src/testkit/FlowScripts.test.ts +58 -0
- package/src/testkit/FlowScripts.ts +61 -24
- 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/acceptance-criteria.feature +5 -1
- package/src/workflows/feature/context-limit.feature +37 -0
- package/src/workflows/feature/coverage.feature +6 -3
- package/src/workflows/feature/coverage.ts +8 -2
- package/src/workflows/feature/fast-path.feature +11 -19
- package/src/workflows/feature/feature.test.ts +24 -4
- package/src/workflows/feature/feature.ts +14 -10
- package/src/workflows/feature/flag-mode.feature +17 -9
- package/src/workflows/feature/lens-models.feature +7 -1
- package/src/workflows/feature/naive-acceptance.feature +2 -2
- package/src/workflows/feature/one-step-land.feature +10 -12
- package/src/workflows/feature/quality-unresolved.feature +7 -1
- 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/risk-tier.feature +12 -4
- package/src/workflows/feature/seam-rejection.feature +4 -9
- package/src/workflows/feature/seam.feature +29 -26
- package/src/workflows/feature/seam.test.ts +117 -6
- package/src/workflows/feature/seam.ts +158 -39
- package/src/workflows/review/review-door.feature +12 -4
- 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.test.ts +8 -0
- package/src/workflows/shared/text.ts +91 -22
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { answered, changes, changesSince, check, 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 } 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
|
|
@@ -883,7 +936,7 @@ const naiveGreen = (tip) => {
|
|
|
883
936
|
return check("check", [
|
|
884
937
|
...paths,
|
|
885
938
|
"dirty=$(git -c core.quotePath=false ls-files -m -d -o --exclude-standard)",
|
|
886
|
-
`if ! git diff --binary ${quote(`${tip.hash}^`)} ${quote(tip.hash)} -- | git apply; then`,
|
|
939
|
+
`if ! git diff --binary --no-color --no-ext-diff --no-textconv --src-prefix=a/ --dst-prefix=b/ ${quote(`${tip.hash}^`)} ${quote(tip.hash)} -- | git apply --whitespace=nowarn; then`,
|
|
887
940
|
" echo 'gtd: the kept naive pass no longer applies to HEAD; no test ran'",
|
|
888
941
|
" exit 1",
|
|
889
942
|
"fi",
|
|
@@ -902,6 +955,11 @@ const naiveGreen = (tip) => {
|
|
|
902
955
|
label: "Running the naive pass's tests"
|
|
903
956
|
});
|
|
904
957
|
};
|
|
958
|
+
/** Resolves `false` when the tip no longer applies (the failure is in `.gtd/FEEDBACK.md`) or has nothing outside `.gtd/` to apply. */
|
|
959
|
+
const applied = async (tip) => {
|
|
960
|
+
await run("applying", applyScript(tip, FEEDBACK, naiveApplyFailure(tip), [".gtd"]), { label: "Applying the naive pass" });
|
|
961
|
+
return !wrote(".gtd/FEEDBACK.md") && codeChanges().length > 0;
|
|
962
|
+
};
|
|
905
963
|
function implement(first, tier, amend) {
|
|
906
964
|
const options = typeof first === "object" && first !== null ? first : {
|
|
907
965
|
reference: first,
|
|
@@ -909,22 +967,26 @@ function implement(first, tier, amend) {
|
|
|
909
967
|
amend
|
|
910
968
|
};
|
|
911
969
|
return scope("implement", async () => {
|
|
912
|
-
|
|
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), {
|
|
913
974
|
label: "Implementing",
|
|
914
975
|
model: coder(),
|
|
915
976
|
system: builderSystem(),
|
|
916
977
|
...options.afterRefactor === true ? { allowEmpty: true } : {}
|
|
917
978
|
});
|
|
918
979
|
requireCriteriaFrozen(REQUIREMENTS);
|
|
919
|
-
|
|
980
|
+
if (built && acceptance !== void 0) requireAcceptance(acceptance, since);
|
|
981
|
+
await green(built && acceptance !== void 0 ? () => requireAcceptanceKept(acceptance) : void 0);
|
|
920
982
|
await requireCoverage();
|
|
921
|
-
await run("closing", removeScript([REQUIREMENTS]), { label: "Closing out the implementation" });
|
|
983
|
+
await run("closing", removeScript([REQUIREMENTS, REFACTOR_NOTE]), { label: "Closing out the implementation" });
|
|
922
984
|
});
|
|
923
985
|
}
|
|
924
986
|
/** Resolves `true` when the human steered (edited), `false` on a clean overrule. */
|
|
925
987
|
const steer = async (retry) => {
|
|
926
988
|
await human("steer", {
|
|
927
|
-
message: seamSteerMessage(retry),
|
|
989
|
+
message: seamSteerMessage(retry, flagModeOn()),
|
|
928
990
|
label: "Steer or overrule the naive pass",
|
|
929
991
|
file: REQUIREMENTS,
|
|
930
992
|
acceptClean: true
|
|
@@ -968,16 +1030,23 @@ const vetted = async (tip, vetting) => {
|
|
|
968
1030
|
/** The judge's ruling on a vetted pass: the decision, or the next attempt's verdict. */
|
|
969
1031
|
const ruled = async (tip, again) => {
|
|
970
1032
|
const shape = await judgeSeam(tip);
|
|
971
|
-
if (shape.choice === "land") return {
|
|
1033
|
+
if (shape.choice === "land") return {
|
|
1034
|
+
reference: tip.hash,
|
|
1035
|
+
tip
|
|
1036
|
+
};
|
|
972
1037
|
if (shape.choice === "refactor-first") return {
|
|
973
1038
|
reference: tip.hash,
|
|
1039
|
+
tip,
|
|
974
1040
|
shape
|
|
975
1041
|
};
|
|
976
1042
|
const next = await again({
|
|
977
1043
|
strays: shape.strays,
|
|
978
1044
|
p: shape.judgment?.answers.shape?.p ?? 0
|
|
979
1045
|
});
|
|
980
|
-
return next.kind === "overruled" ? {
|
|
1046
|
+
return next.kind === "overruled" ? {
|
|
1047
|
+
reference: tip.hash,
|
|
1048
|
+
tip
|
|
1049
|
+
} : next;
|
|
981
1050
|
};
|
|
982
1051
|
const decide = () => scope("seam", async () => {
|
|
983
1052
|
const vetting = {
|
|
@@ -988,16 +1057,33 @@ const decide = () => scope("seam", async () => {
|
|
|
988
1057
|
for (;;) {
|
|
989
1058
|
await naivePass(retry);
|
|
990
1059
|
const tip = kept("naive");
|
|
991
|
-
const outcome = await vetted(tip, vetting) ?? 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
|
+
});
|
|
992
1064
|
if (!("kind" in outcome)) return outcome;
|
|
993
1065
|
retry = outcome.kind === "retry" ? outcome.retry : void 0;
|
|
994
1066
|
}
|
|
995
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
|
+
};
|
|
996
1081
|
const seamBuild = async (base) => {
|
|
997
|
-
const { reference, shape } = await decide();
|
|
1082
|
+
const { reference, tip, shape } = await decide();
|
|
998
1083
|
if (shape === void 0) return {
|
|
999
1084
|
reference,
|
|
1000
|
-
base
|
|
1085
|
+
base,
|
|
1086
|
+
land: true
|
|
1001
1087
|
};
|
|
1002
1088
|
if (shape.unreadable.length > 0) {
|
|
1003
1089
|
await scope("seam", () => human("by-hand", {
|
|
@@ -1007,18 +1093,29 @@ const seamBuild = async (base) => {
|
|
|
1007
1093
|
}));
|
|
1008
1094
|
return {
|
|
1009
1095
|
reference,
|
|
1010
|
-
base
|
|
1096
|
+
base,
|
|
1097
|
+
rebuild: { acceptance: naiveAcceptance(tip) }
|
|
1011
1098
|
};
|
|
1012
1099
|
}
|
|
1013
|
-
|
|
1100
|
+
const strays = refactorStrays(shape);
|
|
1101
|
+
if (strays.length === 0) return {
|
|
1014
1102
|
reference,
|
|
1015
|
-
base
|
|
1103
|
+
base,
|
|
1104
|
+
rebuild: { acceptance: naiveAcceptance(tip) }
|
|
1016
1105
|
};
|
|
1017
|
-
const
|
|
1106
|
+
const note = await scope("seam", () => refactorNote(reference, strays));
|
|
1107
|
+
const refactored = await slice("refactor", () => reviewedRefactor(shape, {
|
|
1108
|
+
reference,
|
|
1109
|
+
note
|
|
1110
|
+
}));
|
|
1018
1111
|
return {
|
|
1019
1112
|
reference,
|
|
1020
1113
|
base: head(),
|
|
1021
|
-
refactored
|
|
1114
|
+
refactored,
|
|
1115
|
+
rebuild: {
|
|
1116
|
+
note,
|
|
1117
|
+
acceptance: naiveAcceptance(tip)
|
|
1118
|
+
}
|
|
1022
1119
|
};
|
|
1023
1120
|
};
|
|
1024
1121
|
//#endregion
|
|
@@ -1028,17 +1125,20 @@ const unwind = () => {
|
|
|
1028
1125
|
const commit = head();
|
|
1029
1126
|
return run("unwind", revertScript(commit, FEEDBACK, unwindFailure(commit)), { label: "Unwinding your input" });
|
|
1030
1127
|
};
|
|
1031
|
-
/** A
|
|
1128
|
+
/** A naive pass (judged only with `flagMode` on), then implement and the quality lap; design must have run since `firstBase`. */
|
|
1032
1129
|
const buildFeature = async (firstBase) => {
|
|
1033
1130
|
const tier = riskTierOn() ? recordRisk() : void 0;
|
|
1034
|
-
const seam =
|
|
1131
|
+
const seam = await seamBuild(firstBase);
|
|
1035
1132
|
await slice("feature", async () => {
|
|
1036
1133
|
await implement({
|
|
1037
1134
|
reference: seam.reference,
|
|
1038
1135
|
tier,
|
|
1039
|
-
afterRefactor: seam.refactored
|
|
1136
|
+
afterRefactor: seam.refactored,
|
|
1137
|
+
naive: seam.land === true ? seam.reference : void 0,
|
|
1138
|
+
rebuild: seam.rebuild
|
|
1040
1139
|
});
|
|
1041
|
-
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;
|
|
1042
1142
|
await tail(settleQuality, {
|
|
1043
1143
|
green: true,
|
|
1044
1144
|
lensBase: base
|
|
@@ -1102,4 +1202,4 @@ const feature = shipped(ordinaryStart);
|
|
|
1102
1202
|
//#region src/workflows/feature/index.ts
|
|
1103
1203
|
var feature_default = feature;
|
|
1104
1204
|
//#endregion
|
|
1105
|
-
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 { _t 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.";
|