@yagni-app/code-staging 1.2.7-staging.2059.1 → 1.2.7-staging.2069.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/dist/extension/pipeline/continuation.d.ts +12 -1
- package/dist/extension/pipeline/continuation.js +20 -4
- package/dist/extension/pipeline/headlessGo.js +18 -2
- package/dist/extension/pipeline/personas.d.ts +5 -4
- package/dist/extension/pipeline/personas.js +21 -7
- package/dist/extension/pipeline/types.d.ts +6 -0
- package/package.json +2 -2
|
@@ -29,11 +29,22 @@ export interface ContinuationInputs {
|
|
|
29
29
|
reviewRoundsDone: number;
|
|
30
30
|
/** The host's short code for why the earlier attempt stopped. */
|
|
31
31
|
priorStop: string;
|
|
32
|
+
/**
|
|
33
|
+
* The attempt's base commit, which the cloud lane's host names (YAG-1042): a
|
|
34
|
+
* cloud execution starts past the earlier executions' commits, so its
|
|
35
|
+
* reviewer diffs the whole change from here. Absent from an older host's
|
|
36
|
+
* file, or when the value is not a commit id.
|
|
37
|
+
*/
|
|
38
|
+
baseSha?: string;
|
|
32
39
|
}
|
|
33
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* Parse and validate the continue file's text; a reason when it cannot be
|
|
42
|
+
* used. `ignored` says what a usable file carried that was dropped.
|
|
43
|
+
*/
|
|
34
44
|
export declare function parseContinuation(raw: string): {
|
|
35
45
|
ok: true;
|
|
36
46
|
value: ContinuationInputs;
|
|
47
|
+
ignored?: string;
|
|
37
48
|
} | {
|
|
38
49
|
ok: false;
|
|
39
50
|
reason: string;
|
|
@@ -20,7 +20,11 @@
|
|
|
20
20
|
import { missionDesignContext } from "./mission.js";
|
|
21
21
|
import { MAX_REVIEW_ROUNDS } from "./types.js";
|
|
22
22
|
const CONTINUATION_STAGES = ["implement", "review", "fix", "verify"];
|
|
23
|
-
|
|
23
|
+
const COMMIT_SHA = /^[0-9a-f]{40}$/;
|
|
24
|
+
/**
|
|
25
|
+
* Parse and validate the continue file's text; a reason when it cannot be
|
|
26
|
+
* used. `ignored` says what a usable file carried that was dropped.
|
|
27
|
+
*/
|
|
24
28
|
export function parseContinuation(raw) {
|
|
25
29
|
let data;
|
|
26
30
|
try {
|
|
@@ -48,9 +52,17 @@ export function parseContinuation(raw) {
|
|
|
48
52
|
};
|
|
49
53
|
}
|
|
50
54
|
const priorStop = typeof obj.priorStop === "string" ? obj.priorStop.trim() : "";
|
|
55
|
+
// It reaches a shell command and a prompt, so only a commit id is read.
|
|
56
|
+
const baseSha = typeof obj.baseSha === "string" && COMMIT_SHA.test(obj.baseSha) ? obj.baseSha : undefined;
|
|
51
57
|
return {
|
|
52
58
|
ok: true,
|
|
53
|
-
value: {
|
|
59
|
+
value: {
|
|
60
|
+
stageAtStop: stage,
|
|
61
|
+
reviewRoundsDone: rounds,
|
|
62
|
+
priorStop,
|
|
63
|
+
...(baseSha ? { baseSha } : {}),
|
|
64
|
+
},
|
|
65
|
+
...("baseSha" in obj && !baseSha ? { ignored: "its baseSha is not a commit id" } : {}),
|
|
54
66
|
};
|
|
55
67
|
}
|
|
56
68
|
/** True when the earlier attempt got past implement, so the run re-enters the review loop. */
|
|
@@ -69,10 +81,14 @@ export function continuationReviewInput(continuation, mission, committed = false
|
|
|
69
81
|
const stopped = `this build continues an earlier attempt that stopped during its ${continuation.stageAtStop ?? "unknown"} stage${why}. `;
|
|
70
82
|
// A cloud execution starts from the attempt's pushed branch: the earlier
|
|
71
83
|
// work is in its commits, not in the working tree.
|
|
84
|
+
const base = continuation.baseSha;
|
|
72
85
|
const summary = committed
|
|
73
86
|
? `No implement summary: ${stopped}` +
|
|
74
|
-
|
|
75
|
-
|
|
87
|
+
(base
|
|
88
|
+
? `That attempt's change is committed on this branch, past the attempt's base commit ${base}. Review the whole change against it ` +
|
|
89
|
+
`(\`git diff ${base}\`, committed or not; \`git log ${base}..HEAD\` lists the commits), plus any new files \`git status\` lists.`
|
|
90
|
+
: "That attempt's change is committed on this branch. Review the whole change against the base commit the ticket names " +
|
|
91
|
+
"(`git diff <base>...HEAD`), plus anything `git status` lists.")
|
|
76
92
|
: `No implement summary: ${stopped}` +
|
|
77
93
|
"That attempt's change is already in the working tree as uncommitted edits on top of HEAD. " +
|
|
78
94
|
"Review the whole change against HEAD (`git diff HEAD`, plus any untracked files `git status` lists).";
|
|
@@ -354,8 +354,12 @@ export async function runHeadlessGo(argv, deps = {}) {
|
|
|
354
354
|
else if (args.continueFile) {
|
|
355
355
|
const raw = read(args.continueFile, "continue file");
|
|
356
356
|
const parsed = typeof raw === "string" ? parseContinuation(raw) : undefined;
|
|
357
|
-
if (parsed?.ok)
|
|
357
|
+
if (parsed?.ok) {
|
|
358
358
|
continuation = parsed.value;
|
|
359
|
+
if (parsed.ignored) {
|
|
360
|
+
writeErr(`Ignoring part of --continue-file ${args.continueFile}: ${parsed.ignored}, so the reviewer reads the change with a bare \`git diff\`.`);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
359
363
|
else if (typeof raw !== "string")
|
|
360
364
|
writeErr(`${raw.error}. Running as a normal mission.`);
|
|
361
365
|
else if (parsed)
|
|
@@ -557,6 +561,18 @@ export async function runHeadlessGo(argv, deps = {}) {
|
|
|
557
561
|
const baseSha = startTree?.head ?? "";
|
|
558
562
|
const preRunDirt = startTree ? parseChangedPaths(startTree.status) : [];
|
|
559
563
|
const onBase = baseSha ? { base: baseSha } : {};
|
|
564
|
+
// Its reviewer reads the change from that commit too (YAG-1041). A
|
|
565
|
+
// continuation starts past the attempt's earlier commits, so its start is
|
|
566
|
+
// not where the change begins: its reviewer reads from the attempt's base
|
|
567
|
+
// that `continue.json` names (YAG-1042), and an older host's file, which
|
|
568
|
+
// names none, keeps the bare `git diff`.
|
|
569
|
+
const diffBase = continuation ? continuation.baseSha : baseSha;
|
|
570
|
+
const reviewLane = lane && diffBase
|
|
571
|
+
? {
|
|
572
|
+
...lane,
|
|
573
|
+
stages: lane.stages.map((s) => (s.id === "review" ? { ...s, diffBase } : s)),
|
|
574
|
+
}
|
|
575
|
+
: lane;
|
|
560
576
|
let gate;
|
|
561
577
|
let lastVerify;
|
|
562
578
|
// A cloud session's gate also runs the host's secret and binary scans on
|
|
@@ -606,7 +622,7 @@ export async function runHeadlessGo(argv, deps = {}) {
|
|
|
606
622
|
...(budget ? { budget } : {}),
|
|
607
623
|
...(deps.stages ? { stages: deps.stages } : {}),
|
|
608
624
|
grounded: deps.grounded ?? grounding,
|
|
609
|
-
...(
|
|
625
|
+
...(reviewLane ? { lane: reviewLane } : {}),
|
|
610
626
|
...(mission ? { mission } : {}),
|
|
611
627
|
...(runVerify ? { runVerify } : {}),
|
|
612
628
|
...(baseline ? { runWorkstreamCheck: makeWorkstreamCheck({ baseline }) } : {}),
|
|
@@ -50,10 +50,11 @@ export declare function builderPersonaClause(workstream?: PartitionWorkstream, s
|
|
|
50
50
|
* Resolve the system-prompt body for a stage. For non-review stages this is the
|
|
51
51
|
* role body; for the review stage it appends the lens-specific clause (or, with
|
|
52
52
|
* no lens, the one-reviewer clause covering all three) and the required
|
|
53
|
-
* findings output contract so the reviewer's output parses. A
|
|
54
|
-
* `
|
|
55
|
-
* carrying a `
|
|
56
|
-
*
|
|
53
|
+
* findings output contract so the reviewer's output parses. A review carrying
|
|
54
|
+
* a `diffBase` (a cloud session's) diffs from that commit in its first step. A
|
|
55
|
+
* stage carrying a `personaClause` (the fan-out builders) gets it appended
|
|
56
|
+
* last, and one carrying a `persona` (the cloud plan stage's host persona)
|
|
57
|
+
* runs with that in place of its agent's body.
|
|
57
58
|
*
|
|
58
59
|
* `grounded` defaults true (every real /go stage). The M6 eval passes
|
|
59
60
|
* `grounded: false` to select the grounding-free bodies + lens clauses for the
|
|
@@ -86,12 +86,22 @@ What was done.
|
|
|
86
86
|
Any record_decision calls you made, and why.
|
|
87
87
|
## Notes
|
|
88
88
|
Anything the reviewer should know (exact file paths, key functions touched).`;
|
|
89
|
+
/** The reviewer's first step, which a stage's `diffBase` rewrites (see `personaBody`). */
|
|
90
|
+
const REVIEWER_DIFF_STEP = "1. `git diff` to see the change.";
|
|
91
|
+
/**
|
|
92
|
+
* The reviewer's first step on a change read from `base`, the commit a cloud
|
|
93
|
+
* session started on: its model may have committed its work, which a bare
|
|
94
|
+
* `git diff` no longer shows (YAG-1041).
|
|
95
|
+
*/
|
|
96
|
+
function reviewerDiffStepFrom(base) {
|
|
97
|
+
return `1. \`git diff ${base}\` to see the change: everything this session changed since its base commit ${base}, committed or not (a bare \`git diff\` shows only what is not committed yet). \`git log ${base}..HEAD\` lists its commits, and \`git status\` lists new files git does not track yet.`;
|
|
98
|
+
}
|
|
89
99
|
const REVIEWER_BODY = `You are a senior, adversarial code reviewer. Analyze the change for real problems, not style nits. Bash is read-only here (\`git diff\`, \`git log\`, \`git show\`); do NOT modify files or run builds.
|
|
90
100
|
|
|
91
101
|
You are grounded in how THIS company works — that context is your edge over a repo-only reviewer.
|
|
92
102
|
|
|
93
103
|
Strategy:
|
|
94
|
-
|
|
104
|
+
${REVIEWER_DIFF_STEP}
|
|
95
105
|
2. Read the modified files and their surroundings.
|
|
96
106
|
3. Judge the change through your assigned lens (below).`;
|
|
97
107
|
const ADVISOR_BODY = `You are a senior advisor, brought in on ONE hard call by an agent that is already working the problem. You are the strongest model in this system and you are expensive, so you are consulted, not driven — the caller does the work, you supply the judgment.
|
|
@@ -300,7 +310,7 @@ Anything the reviewer should know (exact file paths, key functions touched).`;
|
|
|
300
310
|
const REVIEWER_BLIND = `You are a senior, adversarial code reviewer. Analyze the change for real problems, not style nits. Bash is read-only here (\`git diff\`, \`git log\`, \`git show\`); do NOT modify files or run builds.
|
|
301
311
|
|
|
302
312
|
Strategy:
|
|
303
|
-
|
|
313
|
+
${REVIEWER_DIFF_STEP}
|
|
304
314
|
2. Read the modified files and their surroundings.
|
|
305
315
|
3. Judge the change through your assigned lens (below).`;
|
|
306
316
|
const ADVISOR_BLIND = `You are a senior advisor, brought in on ONE hard call by an agent that is already working the problem. You are the strongest model in this system and you are expensive, so you are consulted, not driven — the caller does the work, you supply the judgment.
|
|
@@ -428,10 +438,11 @@ export function builderPersonaClause(workstream, siblings = []) {
|
|
|
428
438
|
* Resolve the system-prompt body for a stage. For non-review stages this is the
|
|
429
439
|
* role body; for the review stage it appends the lens-specific clause (or, with
|
|
430
440
|
* no lens, the one-reviewer clause covering all three) and the required
|
|
431
|
-
* findings output contract so the reviewer's output parses. A
|
|
432
|
-
* `
|
|
433
|
-
* carrying a `
|
|
434
|
-
*
|
|
441
|
+
* findings output contract so the reviewer's output parses. A review carrying
|
|
442
|
+
* a `diffBase` (a cloud session's) diffs from that commit in its first step. A
|
|
443
|
+
* stage carrying a `personaClause` (the fan-out builders) gets it appended
|
|
444
|
+
* last, and one carrying a `persona` (the cloud plan stage's host persona)
|
|
445
|
+
* runs with that in place of its agent's body.
|
|
435
446
|
*
|
|
436
447
|
* `grounded` defaults true (every real /go stage). The M6 eval passes
|
|
437
448
|
* `grounded: false` to select the grounding-free bodies + lens clauses for the
|
|
@@ -443,7 +454,10 @@ export function personaBody(stage, opts = {}) {
|
|
|
443
454
|
const base = stage.persona?.trim() || bodies[stage.agent];
|
|
444
455
|
if (!base)
|
|
445
456
|
throw new Error(`No persona body for agent "${stage.agent}"`);
|
|
446
|
-
const
|
|
457
|
+
const diffBase = stage.diffBase;
|
|
458
|
+
const parts = [
|
|
459
|
+
diffBase ? base.replace(REVIEWER_DIFF_STEP, () => reviewerDiffStepFrom(diffBase)) : base,
|
|
460
|
+
];
|
|
447
461
|
if (stage.id === "review") {
|
|
448
462
|
const clauses = grounded ? LENS_CLAUSES : BLIND_LENS_CLAUSES;
|
|
449
463
|
if (stage.lens)
|
|
@@ -72,6 +72,12 @@ export interface PipelineStage {
|
|
|
72
72
|
* plan stage takes the host's `plan-persona.md` (Reeve's persona) here.
|
|
73
73
|
*/
|
|
74
74
|
persona?: string;
|
|
75
|
+
/**
|
|
76
|
+
* The commit a review reads the change from (a cloud session's start,
|
|
77
|
+
* YAG-1041): its first step is `git diff <diffBase>`, since a model that
|
|
78
|
+
* commits its work leaves a bare `git diff` empty. Absent: `git diff`.
|
|
79
|
+
*/
|
|
80
|
+
diffBase?: string;
|
|
75
81
|
/**
|
|
76
82
|
* The stage's own clock, in milliseconds (`stageClock.ts`). Past it the
|
|
77
83
|
* child refuses every tool call, so the model writes its answer from what it
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yagni-app/code-staging",
|
|
3
|
-
"version": "1.2.7-staging.
|
|
3
|
+
"version": "1.2.7-staging.2069.1",
|
|
4
4
|
"description": "YAGNI Code: a terminal coding agent that already knows your company. One YAGNI login routes the model and grounds the agent in your team's context.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"author": "YAGNI, Inc. <jack@yagni.app> (https://yagni.app)",
|
|
@@ -58,5 +58,5 @@
|
|
|
58
58
|
"turndown": "^7.2.4",
|
|
59
59
|
"typebox": "^1.3.15"
|
|
60
60
|
},
|
|
61
|
-
"yagniSourceSha": "
|
|
61
|
+
"yagniSourceSha": "618a0d09ec56651efeb5669dc92e21a1ce8699ef"
|
|
62
62
|
}
|