@pmelab/gtd 50.0.0 → 51.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +32 -24
- package/dist/chunks/{reserved-CdOzKFVX.mjs → reserved-CUkk9XgL.mjs} +93 -4
- package/dist/chunks/{review-BChXEl2Y.mjs → review-BaCXlIT2.mjs} +2 -2
- package/dist/chunks/{tail-DRM2eC1z.mjs → tail-CX6Pdsql.mjs} +1 -1
- package/dist/gtd.bundle.mjs +26 -25
- package/dist/testkit.mjs +26 -25
- package/dist/workflows/cleanup.mjs +2 -2
- package/dist/workflows/feature.mjs +144 -11
- package/dist/workflows/fix.mjs +2 -2
- package/dist/workflows/review.mjs +3 -3
- package/dist/workflows/rollout.mjs +1 -1
- package/dist/workflows.mjs +234 -12
- package/package.json +1 -1
- package/src/edge/Edge.ts +1 -30
- package/src/replay/Replay.test.ts +4 -8
- package/src/replay/Replay.ts +35 -3
- package/src/replay/index.ts +7 -1
- package/src/workflows/feature/coverage.feature +1 -0
- package/src/workflows/feature/fast-path.feature +1 -0
- package/src/workflows/feature/feature.ts +4 -1
- package/src/workflows/feature/flag-mode.feature +1 -1
- package/src/workflows/feature/lens-models.feature +1 -0
- package/src/workflows/feature/lens-review.feature +1 -0
- package/src/workflows/feature/one-step-land.feature +1 -0
- package/src/workflows/feature/prototype-rounds.feature +152 -0
- package/src/workflows/feature/prototype.feature +419 -0
- package/src/workflows/feature/prototype.test.ts +43 -0
- package/src/workflows/feature/prototype.ts +181 -0
- package/src/workflows/feature/refactor-absorbs.feature +9 -1
- package/src/workflows/feature/refactor-first.feature +13 -3
- package/src/workflows/feature/refactor-rebuild.feature +29 -5
- package/src/workflows/feature/refactor-review.feature +111 -13
- package/src/workflows/feature/refactor.test.ts +14 -4
- package/src/workflows/feature/refactor.ts +2 -0
- package/src/workflows/feature/review-answers.feature +1 -0
- package/src/workflows/feature/review-gate.feature +1 -0
- package/src/workflows/feature/reviewer-walkthrough.feature +1 -0
- package/src/workflows/feature/seam-rejection.feature +1 -0
- package/src/workflows/feature/seam.feature +1 -0
- package/src/workflows/feature/seam.test.ts +3 -2
- package/src/workflows/feature/seam.ts +19 -5
- package/src/workflows/feature/severity-budget.feature +1 -0
- package/src/workflows/feature/severity-sorted-review.feature +1 -0
- package/src/workflows/feature/slice-findings.feature +1 -0
- package/src/workflows/feature/slicing-cap.feature +9 -0
- package/src/workflows/feature/slicing.feature +1 -0
- package/src/workflows/feature/standards.feature +1 -0
- package/src/workflows/shared/options.ts +1 -0
- package/src/workflows/shared/prose.ts +6 -0
- package/src/workflows/shared/skills.test.ts +4 -0
- package/src/workflows/shared/skills.ts +5 -0
- package/src/workflows/shared/steps.ts +1 -0
- package/src/workflows/shared/text.ts +104 -3
- package/src/workflows/shared/vars.ts +3 -0
package/README.md
CHANGED
|
@@ -545,30 +545,31 @@ noted in steps 3 and 4 below.
|
|
|
545
545
|
each led by its tier and reason (`_critical: security, one-way door_`) — the
|
|
546
546
|
phone shows it on the chunk's card. A chunk the judge is unsure of, or whose
|
|
547
547
|
evidence the budget cut, is `critical`. On `refactor-first` the refactor
|
|
548
|
-
slice gets a
|
|
549
|
-
before the feature is built; see
|
|
550
|
-
note needs exactly one tick before
|
|
551
|
-
(`answer-completeness`; an open `- H:` thread
|
|
552
|
-
exception). Fix as suggested joins the nit
|
|
553
|
-
drops the note and records it as
|
|
554
|
-
commit; your own answer is judged
|
|
555
|
-
out of the fresh review after a nit
|
|
556
|
-
nothing else changed to approve, or
|
|
557
|
-
fix or a drop means writing a note
|
|
558
|
-
(at the refactor review, it moves on
|
|
559
|
-
by note, each as `edit`, `question`,
|
|
560
|
-
process back to step 2 for re-derived
|
|
561
|
-
their IDs (reworded in place when
|
|
562
|
-
gets new ones — then the
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
planning lap may redo nit
|
|
548
|
+
slice gets a walkthrough of its own first, covering the whole refactor on
|
|
549
|
+
every round, before the feature is built; see
|
|
550
|
+
[the naive pass](#the-naive-pass). **Every note needs exactly one tick before
|
|
551
|
+
`gtd land` accepts the review** (`answer-completeness`; an open `- H:` thread
|
|
552
|
+
waiting on the agent is the one exception). Fix as suggested joins the nit
|
|
553
|
+
batch below, unjudged; won't fix drops the note and records it as
|
|
554
|
+
`Gtd-Mark: wontfix=<title>` on the gate's commit; your own answer is judged
|
|
555
|
+
like a note. A note you answered is left out of the fresh review after a nit
|
|
556
|
+
fix. Land with every note answered and nothing else changed to approve, or
|
|
557
|
+
write what is wrong — disagreeing with a fix or a drop means writing a note
|
|
558
|
+
of your own. Approving ends the process (at the refactor review, it moves on
|
|
559
|
+
to the feature); feedback is judged note by note, each as `edit`, `question`,
|
|
560
|
+
`nit` or `praise`. An `edit` sends the process back to step 2 for re-derived
|
|
561
|
+
requirements — the built criteria keep their IDs (reworded in place when
|
|
562
|
+
their behaviour changes) and new behaviour gets new ones — then the
|
|
563
|
+
implementation is amended to meet them, with no new naive pass or seam judge,
|
|
564
|
+
every criterion's coverage is judged again, the quality lap runs, and you
|
|
565
|
+
review again. At the refactor review an `edit` re-derives the refactor
|
|
566
|
+
instead. A `question` is answered inline under your note and the process
|
|
567
|
+
stops at the review again — no new plan. A `nit` is fixed in one batch, the
|
|
568
|
+
suite must go green (a red one gets fix turns first), then a fresh review of
|
|
569
|
+
the change stops at the review again. `praise` is dropped; a round of only
|
|
570
|
+
praise signs off. When a round mixes them, questions are answered and nits
|
|
571
|
+
fixed first, then the edits are planned — risk: the planning lap may redo nit
|
|
572
|
+
fixes it touches.
|
|
572
573
|
|
|
573
574
|
Each `edit` note also gets a severity tier from four judge questions
|
|
574
575
|
(security, reversibility, blast radius, new concept). Every tier is
|
|
@@ -692,6 +693,13 @@ an uncovered one goes back to the agent (twice, then to you) instead of ending
|
|
|
692
693
|
the feature, and each covered ID is recorded as a `Gtd-Mark: covers=<id>`
|
|
693
694
|
trailer. See
|
|
694
695
|
[Acceptance-criteria coverage](docs/configuration.md#acceptance-criteria-coverage).
|
|
696
|
+
Then an agent uses the slice by hand — the real program in a scratch directory,
|
|
697
|
+
the real page, guided by a project skill or a manual testing section in
|
|
698
|
+
`AGENTS.md`, `CLAUDE.md` or `README.md` — and writes `.gtd/PROTOTYPE.md`: per
|
|
699
|
+
criterion pass, fail or blocked, with the steps run and what it saw. Failures
|
|
700
|
+
are fixed and re-tested before the quality lap, up to `prototypeRounds` (3) fix
|
|
701
|
+
rounds; past them, with only blocked items, or with no way to test found, it
|
|
702
|
+
rests for you. See [The hands-on test](docs/configuration.md#the-hands-on-test).
|
|
695
703
|
Feedback at the feature review re-runs design and the implementation, never the
|
|
696
704
|
naive pass; feedback at the refactor review re-runs the refactor, never design;
|
|
697
705
|
a refactor-review change the refactor cannot build is refused, and the only way
|
|
@@ -243,6 +243,7 @@ const defaults = {
|
|
|
243
243
|
qualityReviews: "correctness, owasp-security, ponytail-review, test-audit, conventions, spec-challenge",
|
|
244
244
|
refactorQualityReviews: "correctness, ponytail-review, conventions",
|
|
245
245
|
continuations: "3",
|
|
246
|
+
prototypeRounds: "3",
|
|
246
247
|
continuationStall: "2"
|
|
247
248
|
};
|
|
248
249
|
/** Environment settings. */
|
|
@@ -320,6 +321,11 @@ task in front of you end to end, tests first, and come back to fix
|
|
|
320
321
|
things when redirected — a failing check, or reviewer feedback. Stay
|
|
321
322
|
strictly inside that task; never touch code outside it. Treat feedback as the
|
|
322
323
|
diagnosis to act on; discard it, with reason, only when simply wrong.`;
|
|
324
|
+
const testerPersona = `You are the hands-on tester in gtd's build pipeline: use what was just
|
|
325
|
+
built the way a person would — run the real program, open the real
|
|
326
|
+
page, call the real endpoint — and report exactly what you did and
|
|
327
|
+
what you saw. Never fix anything yourself, and never pass a criterion
|
|
328
|
+
you did not watch hold.`;
|
|
323
329
|
const finisherPersona = `You are the closing identity in gtd's build pipeline — the last coder
|
|
324
330
|
before it closes. Fix a late-breaking failing check after sign-off,
|
|
325
331
|
focused and minimal. Every turn lands its own commit — nothing here
|
|
@@ -745,8 +751,11 @@ const acceptanceCriteriaBlock = `
|
|
|
745
751
|
Whichever lap this is, \`.gtd/REQUIREMENTS.md\` carries a
|
|
746
752
|
\`## Acceptance Criteria\` section: one \`- AC-<n>: <criterion>\` line
|
|
747
753
|
per criterion, numbered from \`AC-1\`. They bind every later step —
|
|
748
|
-
the build is done when each one holds — so each must be
|
|
749
|
-
test
|
|
754
|
+
the build is done when each one holds — so each must be behaviour a
|
|
755
|
+
test can pin: one that fails when it does not hold. A green suite, a
|
|
756
|
+
passing typecheck or lint, a generator or build that runs — the health
|
|
757
|
+
check enforces those on every lap, so none is a criterion; fold what it
|
|
758
|
+
must produce into a behaviour a test can observe. A later lap keeps every ID:
|
|
750
759
|
reword a criterion in place, append a new one with the next unused
|
|
751
760
|
number, delete a dropped one — never renumber, never reuse an ID. When
|
|
752
761
|
the file holds no list (a review loop-back rewrites it), recover the
|
|
@@ -854,7 +863,7 @@ const clearCriteriaQuestion = {
|
|
|
854
863
|
id: "clear",
|
|
855
864
|
primitive: "noul",
|
|
856
865
|
instructions: "state.criteria lists the acceptance criteria the human's sketch (state.sketch) stated, as gtd numbered them. Decide whether they can stand as the binding definition of done, with no design conversation.",
|
|
857
|
-
criteria: "yes: every criterion is clear
|
|
866
|
+
criteria: "yes: every criterion is clear behaviour a test can pin — a test would fail if it did not hold — and together they say what to build. no: any one criterion is vague, subjective or untestable, only a command can check it (a suite, typecheck, lint, build or generator run that passes), or the sketch leaves an open product question. Unsure means no."
|
|
858
867
|
};
|
|
859
868
|
const clearCriteriaMessage = () => `The sketch stated its own acceptance criteria. Run \`gtd judge answer\` and
|
|
860
869
|
pipe \`yes\` when every one is clear and checkable, so design is skipped and
|
|
@@ -1773,6 +1782,80 @@ Two ways forward (then run \`gtd land\`):
|
|
|
1773
1782
|
- **Overrule** — land a clean tree to finish without them. The slice records
|
|
1774
1783
|
the IDs it covers and, as \`uncovered\`, the ones it does not
|
|
1775
1784
|
`;
|
|
1785
|
+
const testerSystem = () => `${testerPersona}
|
|
1786
|
+
|
|
1787
|
+
${agentConduct}`;
|
|
1788
|
+
const PROTOTYPE_FORMAT = `- Write \`.gtd/PROTOTYPE.md\`, replacing any earlier report: one \`## \` chunk
|
|
1789
|
+
per criterion, headed \`## AC-<n>: pass\`, \`## AC-<n>: fail\` or
|
|
1790
|
+
\`## AC-<n>: blocked\`, then one chunk per problem you found outside any
|
|
1791
|
+
criterion, headed \`## Problem <short title>: fail\` (\`: pass\` once a
|
|
1792
|
+
re-test shows it fixed). Under each: the exact steps you ran, what you
|
|
1793
|
+
observed (output, a screenshot path, the error), and for a failure what
|
|
1794
|
+
you expected instead
|
|
1795
|
+
- \`blocked\` is for a criterion you could not exercise, or one whose
|
|
1796
|
+
expected behaviour itself looks wrong — say which and why: a person
|
|
1797
|
+
decides it, never a fixer`;
|
|
1798
|
+
const prototypeTestingPrompt = (slice, retest) => `${stateFileRules}
|
|
1799
|
+
- Read \`.gtd/REQUIREMENTS.md\`: the settled requirements for this change
|
|
1800
|
+
${sliceLine(slice)}- The change is built and its suite is green. Now test it by hand: use
|
|
1801
|
+
every acceptance criterion the way a person would and watch what
|
|
1802
|
+
happens. Running the test suite is not this — it already ran
|
|
1803
|
+
- Find how this project is exercised for real, in this order: a project
|
|
1804
|
+
skill that launches or drives it (e.g. \`.claude/skills/*\`); a manual
|
|
1805
|
+
testing or running section in \`AGENTS.md\`, \`CLAUDE.md\` or \`README.md\`;
|
|
1806
|
+
failing those, the project's shape — a browser or Playwright for a web
|
|
1807
|
+
project, the built CLI in a scratch directory for a CLI, a request client
|
|
1808
|
+
for an API
|
|
1809
|
+
- Found none and recognised no shape: write only a chunk headed
|
|
1810
|
+
\`## No testing instructions\` saying what you looked for, and finish —
|
|
1811
|
+
a person is asked; never guess
|
|
1812
|
+
- Test in a disposable place only — a scratch directory outside this
|
|
1813
|
+
repository, a throwaway repository, a dev server on a free port — never
|
|
1814
|
+
against the user's real data or this working tree. Point every tool's
|
|
1815
|
+
output (screenshots, traces, test results) outside the repository too
|
|
1816
|
+
${retest ? `- This is a re-test: \`.gtd/PROTOTYPE.md\` holds the last round's report and
|
|
1817
|
+
a fix turn or a person has changed the code since. Re-test every failed or blocked criterion and
|
|
1818
|
+
every problem it lists in full, then re-run the passed ones quickly
|
|
1819
|
+
` : ""}${PROTOTYPE_FORMAT}
|
|
1820
|
+
- Change nothing but \`.gtd/PROTOTYPE.md\` — a turn that does is refused
|
|
1821
|
+
- Leave everything uncommitted and finish your turn — do not commit
|
|
1822
|
+
`;
|
|
1823
|
+
const prototypeFixingPrompt = (slice) => `${stateFileRules}
|
|
1824
|
+
- Read \`.gtd/REQUIREMENTS.md\`: the settled requirements for this change
|
|
1825
|
+
${sliceLine(slice)}${criteriaBinding(true)}
|
|
1826
|
+
- Read \`.gtd/PROTOTYPE.md\`: a hands-on test of the change. Fix every
|
|
1827
|
+
\`fail\` chunk of this change's criteria${slice === void 0 ? "" : " (this slice's only)"} or a problem found
|
|
1828
|
+
beside them, at its cause, with a test that shows it; leave \`blocked\`
|
|
1829
|
+
ones to the person
|
|
1830
|
+
- A \`fail\` the code does not explain (the tester misread what it saw) has
|
|
1831
|
+
nothing to fix: leave it and change nothing for it — the next round re-tests
|
|
1832
|
+
- Leave \`.gtd/PROTOTYPE.md\` as it is: the next round re-tests from it
|
|
1833
|
+
- Run \`${env.testCommand}\` and finish only once it is green
|
|
1834
|
+
- Leave everything uncommitted and finish your turn — do not commit
|
|
1835
|
+
`;
|
|
1836
|
+
const openItems = (items) => items.map((item) => `- ${item.subject}: ${item.verdict}`).join("\n");
|
|
1837
|
+
const prototypeOpenMessage = (items, rounds) => `The hands-on test of this slice still has open items${rounds > 0 ? ` after ${rounds} fix round${rounds === 1 ? "" : "s"}` : ", and none a fixer can take"}:
|
|
1838
|
+
${openItems(items)}
|
|
1839
|
+
|
|
1840
|
+
\`.gtd/PROTOTYPE.md\` holds the last report: the steps run and what was seen.
|
|
1841
|
+
|
|
1842
|
+
Two ways forward (then run \`gtd land\`):
|
|
1843
|
+
- **Fix** — change the code, or the testing instructions, yourself (the
|
|
1844
|
+
criteria are settled: an edit to them is refused); the suite runs and the
|
|
1845
|
+
slice is tested again, with a fresh round budget
|
|
1846
|
+
- **Overrule** — land a clean tree to go on to the quality lap with these
|
|
1847
|
+
items open
|
|
1848
|
+
`;
|
|
1849
|
+
const prototypeUnguidedMessage = () => `The hands-on test found no way to exercise this project for real — no
|
|
1850
|
+
project skill, no manual testing section in \`AGENTS.md\`, \`CLAUDE.md\` or
|
|
1851
|
+
\`README.md\`, and no project shape it recognised. \`.gtd/PROTOTYPE.md\` says
|
|
1852
|
+
what it looked for.
|
|
1853
|
+
|
|
1854
|
+
Two ways forward (then run \`gtd land\`):
|
|
1855
|
+
- **Instruct** — add testing instructions (a project skill, or a manual
|
|
1856
|
+
testing section); the slice is tested again
|
|
1857
|
+
- **Skip** — land a clean tree to go on to the quality lap untested
|
|
1858
|
+
`;
|
|
1776
1859
|
//#endregion
|
|
1777
1860
|
//#region src/workflows/shared/steps.ts
|
|
1778
1861
|
const FEEDBACK = ".gtd/FEEDBACK.md";
|
|
@@ -1784,6 +1867,7 @@ const REFACTOR_NOTE = ".gtd/REFACTOR-NOTE.md";
|
|
|
1784
1867
|
const QUALITY = ".gtd/QUALITY.md";
|
|
1785
1868
|
const SLICES = ".gtd/SLICES.md";
|
|
1786
1869
|
const HANDOFF = ".gtd/HANDOFF.md";
|
|
1870
|
+
const PROTOTYPE = ".gtd/PROTOTYPE.md";
|
|
1787
1871
|
const planner = () => env.plannerModel ?? "";
|
|
1788
1872
|
const coder = () => env.coderModel ?? "";
|
|
1789
1873
|
const fixCheck = (rules) => agentWithSkills("fix", buildFixPrompt(rules), {
|
|
@@ -2028,6 +2112,7 @@ const ShippedOptions = Struct({
|
|
|
2028
2112
|
qualityReviews: setting,
|
|
2029
2113
|
refactorQualityReviews: setting,
|
|
2030
2114
|
continuations: setting,
|
|
2115
|
+
prototypeRounds: setting,
|
|
2031
2116
|
continuationStall: setting,
|
|
2032
2117
|
testCommand: setting,
|
|
2033
2118
|
plannerModel: setting,
|
|
@@ -2107,6 +2192,10 @@ const skills = (vars) => {
|
|
|
2107
2192
|
seam: ["incremental-implementation"],
|
|
2108
2193
|
implement: ["test-driven-development", "incremental-implementation"],
|
|
2109
2194
|
"implement.fix.suite": ["debugging-and-error-recovery"],
|
|
2195
|
+
"implement.prototype": [],
|
|
2196
|
+
"implement.prototype.fix": ["test-driven-development", "incremental-implementation"],
|
|
2197
|
+
"implement.prototype.fix.suite": ["debugging-and-error-recovery"],
|
|
2198
|
+
"implement.prototype.health": ["debugging-and-error-recovery"],
|
|
2110
2199
|
"implement.health": ["debugging-and-error-recovery"],
|
|
2111
2200
|
...lensScopes("build.quality", lensesOf(vars.qualityReviews ?? ""), (lens) => builtInLenses[lens]?.skills ?? [lens]),
|
|
2112
2201
|
...lensScopes("refactor.build.quality", lensesOf(vars.refactorQualityReviews ?? ""), (lens) => builtInLenses[lens]?.skills ?? [lens])
|
|
@@ -2131,4 +2220,4 @@ const steering = {
|
|
|
2131
2220
|
[REVIEW]: "review"
|
|
2132
2221
|
};
|
|
2133
2222
|
//#endregion
|
|
2134
|
-
export {
|
|
2223
|
+
export { implementFixPrompt as $, reviewMissing as A, unranked as At, composedReview as B, conflictBody as Bt, coder as C, seamByHandMessage as Ct, fixQuality as D, testerSystem as Dt, fixNits as E, startGateBlockedMessage as Et, buildReviewTriageMessage as F, withWalkthrough as Ft, designGateAnswerMessage as G, parseStandards as Gt, coverageQuestion as H, conflictTitle as Ht, builderSystem as I, defaults as It, finisherSystem as J, flagMentions as Jt, designSystem as K, renderStandards as Kt, chunkTexts as L, envDefaults as Lt, reviewing as M, unwindFailure as Mt, agentWithSkills as N, walkthroughBlock as Nt, fixRisks as O, titledNotes as Ot, buildReviewCollectingPrompt as P, withLapFindings as Pt, implementBuildingPrompt as Q, requireFlag as Qt, clearCriteriaMessage as R, testFileGlobs as Rt, awaitReview as S, reviewerSystem as St, fixCheck as T, slicingPrompt as Tt, coveringPrompt as U, isConflictTitle as Ut, coverageMessage as V, conflictFor as Vt, criterionLine as W, oneLine as Wt, handOffAwaitReviewMessage as X, flipProblems as Xt, fixReviewNotesPrompt as Y, flagReferences as Yt, idleMessage as Z, registryEntry as Zt, REFACTOR_NOTE as _, reviewEditsCapture as _t, flagModeOn as a, prototypeOpenMessage as at, SLICES as b, reviewNotesCapture as bt, baseline as c, qualityFindingsFile as ct, healthy as d, refactorBuildingPrompt as dt, naiveApplyFailure as et, FEEDBACK as f, refactorDroppedRefusal as ft, REFACTOR as g, reviewEditNotesCapture as gt, QUALITY as h, refactorRules as ht, skills as i, prototypeFixingPrompt as it, reviewQuality as j, unwindFailedMessage as jt, planner as k, uncoveredMessage as kt, gate as l, qualityTriageMessage as lt, PROTOTYPE as m, refactorNotePrompt as mt, summary as n, normaliseCriteriaScript as nt, flagShipped as o, prototypeTestingPrompt as ot, HANDOFF as p, refactorFixPrompt as pt, designTriagePrompt as q, standardKey as qt, access as r, oversizedMessage as rt, shipped as s, prototypeUnguidedMessage as st, steering as t, naivePassPrompt as tt, guarded as u, rankedReview as ut, REQUIREMENTS as v, reviewFeedbackFixPrompt as vt, collecting as w, seamSteerMessage as wt, answerReviewQuestions as x, reviewRankingMessage as xt, REVIEW as y, reviewGateBlockedMessage as yt, clearCriteriaQuestion as z, STANDARDS as zt };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { answered, changesSince, head, judge, numeric, read, refuse, requireRevert, restoreScript, run, showScript, vars, writeScript } from "../flows.mjs";
|
|
2
2
|
import { _ as reviewRisks, m as reviewChunks } from "./steering-DtUVUz9l.mjs";
|
|
3
3
|
import { removedAssertions, review } from "../workflow-kit.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import { i as isOptionalObject, n as closeReview, o as tail, s as NO_FINDINGS } from "./tail-
|
|
4
|
+
import { A as reviewMissing, At as unranked, B as composedReview, Bt as conflictBody, E as fixNits, F as buildReviewTriageMessage, Ft as withWalkthrough, Gt as parseStandards, Ht as conflictTitle, Kt as renderStandards, L as chunkTexts, M as reviewing, Nt as walkthroughBlock, O as fixRisks, Ot as titledNotes, S as awaitReview, T as fixCheck, Ut as isConflictTitle, Vt as conflictFor, Wt as oneLine, _t as reviewEditsCapture, bt as reviewNotesCapture, d as healthy, gt as reviewEditNotesCapture, qt as standardKey, u as guarded, ut as rankedReview, w as collecting, x as answerReviewQuestions, xt as reviewRankingMessage, y as REVIEW, zt as STANDARDS } from "./reserved-CUkk9XgL.mjs";
|
|
5
|
+
import { i as isOptionalObject, n as closeReview, o as tail, s as NO_FINDINGS } from "./tail-CX6Pdsql.mjs";
|
|
6
6
|
//#region src/workflows/shared/learn.ts
|
|
7
7
|
const SUMMARY_MAX = 200;
|
|
8
8
|
const BANNER = /^_(?:The fixer left this unresolved\.|A fix turn removed this while renaming another finding — check whether it was fixed\.|No detail given\.)_\s*/;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { answered, head, judge, mark, numeric, read, refuse, removeScript, run, scope, sectionBodies, showScript, vars, writeScript } from "../flows.mjs";
|
|
2
2
|
import { lensEntriesOf, lensOf, qualityLap, reviewToHandOff } from "../workflow-kit.mjs";
|
|
3
|
-
import { A as
|
|
3
|
+
import { A as reviewMissing, D as fixQuality, M as reviewing, O as fixRisks, Pt as withLapFindings, S as awaitReview, T as fixCheck, X as handOffAwaitReviewMessage, ct as qualityFindingsFile, d as healthy, h as QUALITY, j as reviewQuality, lt as qualityTriageMessage, u as guarded, y as REVIEW } from "./reserved-CUkk9XgL.mjs";
|
|
4
4
|
//#region src/workflows/shared/lenses.ts
|
|
5
5
|
const NO_FINDINGS = {
|
|
6
6
|
notes: [],
|
package/dist/gtd.bundle.mjs
CHANGED
|
@@ -38078,6 +38078,28 @@ const memoryScopeOf = (name) => {
|
|
|
38078
38078
|
const dot = name.lastIndexOf(".");
|
|
38079
38079
|
return dot === -1 ? "" : name.slice(0, dot);
|
|
38080
38080
|
};
|
|
38081
|
+
/** Is `name` inside `scope`'s subtree? The root scope `""` holds everything. */
|
|
38082
|
+
const inScope = (name, scope) => scope === "" || name === scope || name.startsWith(`${scope}.`);
|
|
38083
|
+
/**
|
|
38084
|
+
* Where the current unbroken run of rests inside `scope`'s subtree began —
|
|
38085
|
+
* a dip into a descendant scope does not break it, a sibling or ancestor
|
|
38086
|
+
* does, and so does a fresh `scope()` call of the same scope.
|
|
38087
|
+
*/
|
|
38088
|
+
const scopeRunStart = (trace, scope) => {
|
|
38089
|
+
let start = -1;
|
|
38090
|
+
for (let k = 0; k < trace.length; k++) {
|
|
38091
|
+
if (!inScope(trace[k].memoryScope, scope)) continue;
|
|
38092
|
+
const previous = trace[k - 1];
|
|
38093
|
+
if (!(previous !== void 0 && inScope(previous.memoryScope, scope) && scopeCallOf(previous, scope) === scopeCallOf(trace[k], scope))) start = k;
|
|
38094
|
+
}
|
|
38095
|
+
return start;
|
|
38096
|
+
};
|
|
38097
|
+
/** The innermost `scope()` call enclosing `scope` at `step` — a new call is a new conversation. */
|
|
38098
|
+
const scopeCallOf = (step, scope) => {
|
|
38099
|
+
let call;
|
|
38100
|
+
for (const entry of step.scopeCalls) if (inScope(scope, entry.prefix)) call = entry.call;
|
|
38101
|
+
return call;
|
|
38102
|
+
};
|
|
38081
38103
|
var Stop = class extends Error {};
|
|
38082
38104
|
const short = (hash) => hash.slice(0, 7);
|
|
38083
38105
|
/** One step's changes; content is read only when a flow asks for it. */
|
|
@@ -38337,12 +38359,13 @@ const replay = async (input) => {
|
|
|
38337
38359
|
skills: step.skills,
|
|
38338
38360
|
access: unfoldedAccess.get(step)
|
|
38339
38361
|
};
|
|
38340
|
-
const
|
|
38362
|
+
const conversation = `${step.memoryScope}#${scopeRunStart(trace, step.memoryScope)}`;
|
|
38363
|
+
const seen = personas.get(conversation);
|
|
38341
38364
|
if (seen === void 0) {
|
|
38342
|
-
personas.set(
|
|
38365
|
+
personas.set(conversation, identity);
|
|
38343
38366
|
return;
|
|
38344
38367
|
}
|
|
38345
|
-
return samePersona(seen, identity) ? void 0 : `gtd: "${step.name}" runs with a different model, system prompt, skills or file access than an earlier agent step in memory scope "${step.memoryScope || "root"}" —
|
|
38368
|
+
return samePersona(seen, identity) ? void 0 : `gtd: "${step.name}" runs with a different model, system prompt, skills or file access than an earlier agent step in its conversation in memory scope "${step.memoryScope || "root"}" — a conversation has one identity`;
|
|
38346
38369
|
};
|
|
38347
38370
|
const DIVERGED = "the workflow changed under this process; run `gtd abandon` to start over";
|
|
38348
38371
|
const blockerAt = (step) => {
|
|
@@ -40110,28 +40133,6 @@ const stepDefOf = (step) => {
|
|
|
40110
40133
|
case "human": return messageDef(common, request, step);
|
|
40111
40134
|
}
|
|
40112
40135
|
};
|
|
40113
|
-
/** Is `name` inside `scope`'s subtree? The root scope `""` holds everything. */
|
|
40114
|
-
const inScope = (name, scope) => scope === "" || name === scope || name.startsWith(`${scope}.`);
|
|
40115
|
-
/**
|
|
40116
|
-
* Where the current unbroken run of rests inside `scope`'s subtree began —
|
|
40117
|
-
* a dip into a descendant scope does not break it, a sibling or ancestor
|
|
40118
|
-
* does, and so does a fresh `scope()` call of the same scope.
|
|
40119
|
-
*/
|
|
40120
|
-
const scopeRunStart = (trace, scope) => {
|
|
40121
|
-
let start = -1;
|
|
40122
|
-
for (let k = 0; k < trace.length; k++) {
|
|
40123
|
-
if (!inScope(trace[k].memoryScope, scope)) continue;
|
|
40124
|
-
const previous = trace[k - 1];
|
|
40125
|
-
if (!(previous !== void 0 && inScope(previous.memoryScope, scope) && scopeCallOf(previous, scope) === scopeCallOf(trace[k], scope))) start = k;
|
|
40126
|
-
}
|
|
40127
|
-
return start;
|
|
40128
|
-
};
|
|
40129
|
-
/** The innermost `scope()` call enclosing `scope` at `step` — a new call is a new conversation. */
|
|
40130
|
-
const scopeCallOf = (step, scope) => {
|
|
40131
|
-
let call;
|
|
40132
|
-
for (const entry of step.scopeCalls) if (inScope(scope, entry.prefix)) call = entry.call;
|
|
40133
|
-
return call;
|
|
40134
|
-
};
|
|
40135
40136
|
const ROOT_MEMORY_SCOPE_NAME = "root";
|
|
40136
40137
|
/**
|
|
40137
40138
|
* An agent rest's memory key, `<scope>#<hash7>`: the hash is the commit the
|
package/dist/testkit.mjs
CHANGED
|
@@ -7124,6 +7124,28 @@ const memoryScopeOf = (name) => {
|
|
|
7124
7124
|
const dot = name.lastIndexOf(".");
|
|
7125
7125
|
return dot === -1 ? "" : name.slice(0, dot);
|
|
7126
7126
|
};
|
|
7127
|
+
/** Is `name` inside `scope`'s subtree? The root scope `""` holds everything. */
|
|
7128
|
+
const inScope = (name, scope) => scope === "" || name === scope || name.startsWith(`${scope}.`);
|
|
7129
|
+
/**
|
|
7130
|
+
* Where the current unbroken run of rests inside `scope`'s subtree began —
|
|
7131
|
+
* a dip into a descendant scope does not break it, a sibling or ancestor
|
|
7132
|
+
* does, and so does a fresh `scope()` call of the same scope.
|
|
7133
|
+
*/
|
|
7134
|
+
const scopeRunStart = (trace, scope) => {
|
|
7135
|
+
let start = -1;
|
|
7136
|
+
for (let k = 0; k < trace.length; k++) {
|
|
7137
|
+
if (!inScope(trace[k].memoryScope, scope)) continue;
|
|
7138
|
+
const previous = trace[k - 1];
|
|
7139
|
+
if (!(previous !== void 0 && inScope(previous.memoryScope, scope) && scopeCallOf(previous, scope) === scopeCallOf(trace[k], scope))) start = k;
|
|
7140
|
+
}
|
|
7141
|
+
return start;
|
|
7142
|
+
};
|
|
7143
|
+
/** The innermost `scope()` call enclosing `scope` at `step` — a new call is a new conversation. */
|
|
7144
|
+
const scopeCallOf = (step, scope) => {
|
|
7145
|
+
let call;
|
|
7146
|
+
for (const entry of step.scopeCalls) if (inScope(scope, entry.prefix)) call = entry.call;
|
|
7147
|
+
return call;
|
|
7148
|
+
};
|
|
7127
7149
|
var Stop = class extends Error {};
|
|
7128
7150
|
const short = (hash) => hash.slice(0, 7);
|
|
7129
7151
|
/** One step's changes; content is read only when a flow asks for it. */
|
|
@@ -7383,12 +7405,13 @@ const replay = async (input) => {
|
|
|
7383
7405
|
skills: step.skills,
|
|
7384
7406
|
access: unfoldedAccess.get(step)
|
|
7385
7407
|
};
|
|
7386
|
-
const
|
|
7408
|
+
const conversation = `${step.memoryScope}#${scopeRunStart(trace, step.memoryScope)}`;
|
|
7409
|
+
const seen = personas.get(conversation);
|
|
7387
7410
|
if (seen === void 0) {
|
|
7388
|
-
personas.set(
|
|
7411
|
+
personas.set(conversation, identity);
|
|
7389
7412
|
return;
|
|
7390
7413
|
}
|
|
7391
|
-
return samePersona(seen, identity) ? void 0 : `gtd: "${step.name}" runs with a different model, system prompt, skills or file access than an earlier agent step in memory scope "${step.memoryScope || "root"}" —
|
|
7414
|
+
return samePersona(seen, identity) ? void 0 : `gtd: "${step.name}" runs with a different model, system prompt, skills or file access than an earlier agent step in its conversation in memory scope "${step.memoryScope || "root"}" — a conversation has one identity`;
|
|
7392
7415
|
};
|
|
7393
7416
|
const DIVERGED = "the workflow changed under this process; run `gtd abandon` to start over";
|
|
7394
7417
|
const blockerAt = (step) => {
|
|
@@ -9145,28 +9168,6 @@ const stepDefOf = (step) => {
|
|
|
9145
9168
|
case "human": return messageDef(common, request, step);
|
|
9146
9169
|
}
|
|
9147
9170
|
};
|
|
9148
|
-
/** Is `name` inside `scope`'s subtree? The root scope `""` holds everything. */
|
|
9149
|
-
const inScope = (name, scope) => scope === "" || name === scope || name.startsWith(`${scope}.`);
|
|
9150
|
-
/**
|
|
9151
|
-
* Where the current unbroken run of rests inside `scope`'s subtree began —
|
|
9152
|
-
* a dip into a descendant scope does not break it, a sibling or ancestor
|
|
9153
|
-
* does, and so does a fresh `scope()` call of the same scope.
|
|
9154
|
-
*/
|
|
9155
|
-
const scopeRunStart = (trace, scope) => {
|
|
9156
|
-
let start = -1;
|
|
9157
|
-
for (let k = 0; k < trace.length; k++) {
|
|
9158
|
-
if (!inScope(trace[k].memoryScope, scope)) continue;
|
|
9159
|
-
const previous = trace[k - 1];
|
|
9160
|
-
if (!(previous !== void 0 && inScope(previous.memoryScope, scope) && scopeCallOf(previous, scope) === scopeCallOf(trace[k], scope))) start = k;
|
|
9161
|
-
}
|
|
9162
|
-
return start;
|
|
9163
|
-
};
|
|
9164
|
-
/** The innermost `scope()` call enclosing `scope` at `step` — a new call is a new conversation. */
|
|
9165
|
-
const scopeCallOf = (step, scope) => {
|
|
9166
|
-
let call;
|
|
9167
|
-
for (const entry of step.scopeCalls) if (inScope(scope, entry.prefix)) call = entry.call;
|
|
9168
|
-
return call;
|
|
9169
|
-
};
|
|
9170
9171
|
const ROOT_MEMORY_SCOPE_NAME = "root";
|
|
9171
9172
|
/**
|
|
9172
9173
|
* An agent rest's memory key, `<scope>#<hash7>`: the hash is the commit the
|
|
@@ -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 { C as coder, It as defaults, Lt as envDefaults, Qt as requireFlag, Yt as flagReferences, Zt as registryEntry, i as skills, n as summary, o as flagShipped, r as access, t as steering } from "../chunks/reserved-CUkk9XgL.mjs";
|
|
3
|
+
import { a as refusePendingHandOff, r as handOffTail } from "../chunks/tail-CX6Pdsql.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 () => {
|