mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-05 00:03:15 +01:00
fix: pin review Step 3.5 rename, plan-path placeholder, mktemp template, per-stream evidence tail
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
89af575ba6
commit
d4b489ae09
6 files changed
+23
-15
No files matched your search
+13
-6
@@ -74,17 +74,24 @@ interface EvidenceRecord {
|
||||
/** Bytes of streamed output kept for the tests_ran parse (the 2MB log would truncate the summary). */
|
||||
const TAIL_MAX_BYTES = 64 * 1024;
|
||||
|
||||
/** Ring of the last TAIL_MAX_BYTES of combined child output, decoded per stream. */
|
||||
/**
|
||||
* Ring of the last TAIL_MAX_BYTES of each child stream, kept per stream: the
|
||||
* pumps interleave by arrival, so a stderr summary read while stdout still has
|
||||
* pipe-buffered bytes behind it would otherwise be pushed out of a shared ring.
|
||||
*/
|
||||
class OutputTail {
|
||||
private readonly decoders = { stdout: new TextDecoder("utf-8"), stderr: new TextDecoder("utf-8") };
|
||||
private text = "";
|
||||
private readonly text = { stdout: "", stderr: "" };
|
||||
push(chunk: Uint8Array, origin: "stdout" | "stderr"): void {
|
||||
this.text += this.decoders[origin].decode(chunk, { stream: true });
|
||||
if (this.text.length > TAIL_MAX_BYTES * 2) this.text = this.text.slice(-TAIL_MAX_BYTES);
|
||||
this.text[origin] += this.decoders[origin].decode(chunk, { stream: true });
|
||||
if (this.text[origin].length > TAIL_MAX_BYTES * 2) this.text[origin] = this.text[origin].slice(-TAIL_MAX_BYTES);
|
||||
}
|
||||
end(): string {
|
||||
this.text += this.decoders.stdout.decode() + this.decoders.stderr.decode();
|
||||
return this.text.length > TAIL_MAX_BYTES ? this.text.slice(-TAIL_MAX_BYTES) : this.text;
|
||||
const tails = (["stdout", "stderr"] as const).map((origin) => {
|
||||
const text = this.text[origin] + this.decoders[origin].decode();
|
||||
return text.length > TAIL_MAX_BYTES ? text.slice(-TAIL_MAX_BYTES) : text;
|
||||
});
|
||||
return tails.join("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
*
|
||||
* docs/designs/HONEST_WORK_GATE_INTEGRITY.md W7. Rendered into /spec's issue
|
||||
* body template (the archived spec is the prompt `/spec --execute` pipes to
|
||||
* `claude -p`, so the rules travel inside it) and into /ship Step 7's
|
||||
* test-generation child prompt, before its LAST-line JSON protocol. One
|
||||
* `claude -p`, so the rules travel inside it) and into the /ship Test Coverage
|
||||
* Audit (Step 7) test-generation child prompt, before its LAST-line JSON protocol. One
|
||||
* constant so the two cannot drift. The child's JSON contracts are untouched:
|
||||
* gate-edit disclosure uses the prose the protocols already permit before the
|
||||
* JSON line. test/dispatch-rules.test.ts pins the rendering sites.
|
||||
|
||||
@@ -241,14 +241,14 @@ function planAcceptanceEditedCheck(): string {
|
||||
return `### Acceptance edits (parent-computed)
|
||||
|
||||
Run this after the child's report and before Gate Logic, with the bound plan path
|
||||
substituted for \`<plan path>\`. It compares the plan's acceptance-bearing sections
|
||||
substituted for \`<plan-path>\`. It compares the plan's acceptance-bearing sections
|
||||
(headings matching acceptance, success criteria, verification, test plan, testing,
|
||||
done when, definition of done) as they stand in the working tree against a baseline:
|
||||
the \`origin/<base>\` version when the plan exists there, else its first commit on this
|
||||
branch, else \`baseline unavailable\` (plans outside the repository or not yet tracked).
|
||||
|
||||
\`\`\`bash
|
||||
PLAN_FILE="<plan path>"
|
||||
PLAN_FILE="<plan-path>"
|
||||
_REL=$(git ls-files --full-name --error-unmatch -- "$PLAN_FILE" 2>/dev/null | head -1)
|
||||
_BASE_REF=""; _BASE_KIND=""
|
||||
if [ -z "$_REL" ]; then
|
||||
@@ -262,7 +262,7 @@ else
|
||||
fi
|
||||
if [ -n "$_BASE_REF" ]; then
|
||||
echo "ACCEPTANCE_BASELINE: $_BASE_KIND"
|
||||
_ACC_TMP=$(mktemp -d) && trap 'rm -rf "$_ACC_TMP"' EXIT
|
||||
_ACC_TMP=$(mktemp -d "\${TMPDIR:-/tmp}/gstack-acceptance.XXXXXX") && trap 'rm -rf "$_ACC_TMP"' EXIT
|
||||
_acc_sections() { awk 'BEGIN{keep=0} /^#+ /{keep = (tolower($0) ~ /${ACCEPTANCE_HEADING_PATTERN}/)} keep{print}'; }
|
||||
git show "$_BASE_REF:$_REL" | _acc_sections > "$_ACC_TMP/base"
|
||||
_acc_sections < "$PLAN_FILE" > "$_ACC_TMP/wtree"
|
||||
|
||||
@@ -188,14 +188,14 @@ Counts map one-to-one to the classifications above and sum to total_items. No pl
|
||||
### Acceptance edits (parent-computed)
|
||||
|
||||
Run this after the child's report and before Gate Logic, with the bound plan path
|
||||
substituted for `<plan path>`. It compares the plan's acceptance-bearing sections
|
||||
substituted for `<plan-path>`. It compares the plan's acceptance-bearing sections
|
||||
(headings matching acceptance, success criteria, verification, test plan, testing,
|
||||
done when, definition of done) as they stand in the working tree against a baseline:
|
||||
the `origin/<base>` version when the plan exists there, else its first commit on this
|
||||
branch, else `baseline unavailable` (plans outside the repository or not yet tracked).
|
||||
|
||||
```bash
|
||||
PLAN_FILE="<plan path>"
|
||||
PLAN_FILE="<plan-path>"
|
||||
_REL=$(git ls-files --full-name --error-unmatch -- "$PLAN_FILE" 2>/dev/null | head -1)
|
||||
_BASE_REF=""; _BASE_KIND=""
|
||||
if [ -z "$_REL" ]; then
|
||||
@@ -209,7 +209,7 @@ else
|
||||
fi
|
||||
if [ -n "$_BASE_REF" ]; then
|
||||
echo "ACCEPTANCE_BASELINE: $_BASE_KIND"
|
||||
_ACC_TMP=$(mktemp -d) && trap 'rm -rf "$_ACC_TMP"' EXIT
|
||||
_ACC_TMP=$(mktemp -d "${TMPDIR:-/tmp}/gstack-acceptance.XXXXXX") && trap 'rm -rf "$_ACC_TMP"' EXIT
|
||||
_acc_sections() { awk 'BEGIN{keep=0} /^#+ /{keep = (tolower($0) ~ /^#+ *[0-9.]* *(testable )?(acceptance|success criteria|verification|test plan|testing|done when|definition of done)/)} keep{print}'; }
|
||||
git show "$_BASE_REF:$_REL" | _acc_sections > "$_ACC_TMP/base"
|
||||
_acc_sections < "$PLAN_FILE" > "$_ACC_TMP/wtree"
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@
|
||||
"## Step 2.5: Check for Greptile review comments",
|
||||
"## Step 3: Get the diff",
|
||||
"## Step 3.4: Workspace-aware queue status (advisory)",
|
||||
"## Step 3.5: Slop scan (advisory)",
|
||||
"## Step 3.5: Diff scans",
|
||||
"## Step 3.6: Gather review context",
|
||||
"## Step 4: Critical pass (core review)",
|
||||
"### Step 4.7: Exploratory QA (before Fix-First)",
|
||||
|
||||
@@ -128,6 +128,7 @@ export const IDENTIFIER_PLACEHOLDERS: Record<string, IdentifierGrammar> = {
|
||||
'<stagedDir>': { grammar: QUOTED, what: 'staged directory printed by an earlier block', quoted: true },
|
||||
'<outdir>': { grammar: PATH, what: 'output directory' },
|
||||
'<path>': { grammar: PATH, what: 'repository path from discovery' },
|
||||
'<plan-path>': { grammar: PATH, what: 'bound plan file path' },
|
||||
'<sketch-dir>': { grammar: PATH, what: 'sketch directory printed by an earlier block' },
|
||||
'<path-to-finalized.html>': { grammar: PATH, what: 'finalized HTML path' },
|
||||
'<finalized.html>': { grammar: PATH, what: 'finalized HTML path' },
|
||||
|
||||
Reference in new issue
Block a user