Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/issue-dev-loop-evidence.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ jobs:
docker run --rm --network none \
--mount "type=volume,src=${candidate_volume},dst=/work" \
"${image}" \
pnpm verify 2>&1 | tee "${RUNNER_TEMP}/issue-dev-evidence/pnpm-verify.log"
sh -ceu 'git config --global --add safe.directory /work; pnpm verify' \
2>&1 | tee "${RUNNER_TEMP}/issue-dev-evidence/pnpm-verify.log"
candidate_exit_code="${PIPESTATUS[0]}"
set -e
baseline_status=blocked
Expand All @@ -158,7 +159,8 @@ jobs:
docker run --rm --network none \
--mount "type=volume,src=${baseline_volume},dst=/work" \
"${image}" \
pnpm test 2>&1 | tee "${RUNNER_TEMP}/issue-dev-evidence/owner-merged-baseline-tests.log"
sh -ceu 'git config --global --add safe.directory /work; pnpm test' \
2>&1 | tee "${RUNNER_TEMP}/issue-dev-evidence/owner-merged-baseline-tests.log"
baseline_exit_code="${PIPESTATUS[0]}"
set -e
if [[ "${baseline_exit_code}" == "0" ]]; then
Expand Down
4 changes: 2 additions & 2 deletions loops/issue-dev-loop/LOOP.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,11 @@ The recorded implementation commit is the product-code boundary. Later commits m

### 5. Verify before publication

Run relevant checks and `pnpm verify`. For UI behavior, capture before/after screenshots under `screen-shots/<run-id>` at meaningful desktop and mobile viewports and include interaction or accessibility evidence where applicable. Bind `before` to the frozen base and `after` to the latest `$implement` commit; never put the containing commit's not-yet-known hash inside its own files. Commit sanitized screenshots and run metadata to the issue branch. The low-privilege `pull_request` evidence workflow checks out the exact candidate head, resolves its frozen run base, proves that base remains an ancestor of live `dev`, and separately checks out the immutable owner-merged base without persisted credentials. It installs candidate and baseline dependencies with lifecycle scripts disabled into distinct Docker volumes. Candidate `pnpm verify` and the actual frozen owner-merged baseline `pnpm test` run in separate no-network containers that receive no GitHub token and cannot mount any host checkout. Before accepting the artifact, the installed control plane independently rejects any exact-head change to the workflow or trusted control/verification plane. The manifest binds candidate head, workflow-run SHA, frozen owner-merged base SHA, and the live PR base SHA that selected the workflow.
Run relevant checks and `pnpm verify`. For UI behavior, capture before/after screenshots under `screen-shots/<run-id>` at meaningful desktop and mobile viewports and include interaction or accessibility evidence where applicable. Bind `before` to the frozen base and `after` to the latest `$implement` commit; never put the containing commit's not-yet-known hash inside its own files. Commit sanitized screenshots and run metadata to the issue branch. The Draft PR body must render at least one representative before/after pair with Markdown image syntax, using `raw.githubusercontent.com` URLs pinned to the exact recorded head; links to an index or manifest alone are not UI evidence. The low-privilege `pull_request` evidence workflow checks out the exact candidate head, resolves its frozen run base, proves that base remains an ancestor of live `dev`, and separately checks out the immutable owner-merged base without persisted credentials. It installs candidate and baseline dependencies with lifecycle scripts disabled into distinct Docker volumes. Candidate `pnpm verify` and the actual frozen owner-merged baseline `pnpm test` run in separate no-network containers that receive no GitHub token and cannot mount any host checkout. Before accepting the artifact, the installed control plane independently rejects any exact-head change to the workflow or trusted control/verification plane. The manifest binds candidate head, workflow-run SHA, frozen owner-merged base SHA, and the live PR base SHA that selected the workflow.

### 6. Create the draft PR

Push the issue branch and create a draft PR targeting `dev`. Immediately bind it to the run with `record-pr`; later evidence and review gates accept only that PR and head. The PR must include the issue, run ID, base/head SHAs, risk, changes, evidence links, screenshots, known limitations, and explicit owner-only merge language. In `Verification`, bind every manifest check to its own result using the exact line `- \`<exact command>\`: passed (exit code 0)`; a summary-level pass statement is not sufficient.
Push the issue branch and create a draft PR targeting `dev`. Immediately bind it to the run with `record-pr`; later evidence and review gates accept only that PR and head. The PR must include the issue, run ID, base/head SHAs, risk, changes, evidence links, rendered before/after screenshots for UI work, known limitations, and explicit owner-only merge language. In `Verification`, bind every manifest check to its own result using the exact line `- \`<exact command>\`: passed (exit code 0)`; a summary-level pass statement is not sufficient.

### 7. Independent review

Expand Down
4 changes: 2 additions & 2 deletions loops/issue-dev-loop/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ Require `$implement` to write a unique `logs/runs/<run-id>/implementation-result

## Publish a draft PR

Push only the issue branch and create a **draft** PR targeting `dev` using `templates/pr-body.md`; preserve its machine-readable run marker and owner-only merge statement. Bind it immediately with `loopctl.mjs record-pr --run-id <id> --pr-url <url> --head-sha <full-sha>`. Include the issue, risk assessment, test results, evidence manifest, screenshots, known limitations, run ID, and exact head SHA. Never target `main` from an issue branch.
Push only the issue branch and create a **draft** PR targeting `dev` using `templates/pr-body.md`; preserve its machine-readable run marker and owner-only merge statement. Bind it immediately with `loopctl.mjs record-pr --run-id <id> --pr-url <url> --head-sha <full-sha>`. Include the issue, risk assessment, test results, evidence manifest, screenshots, known limitations, run ID, and exact head SHA. For UI work, render at least one representative before/after pair directly in the PR with Markdown images whose `raw.githubusercontent.com` URLs are pinned to that exact head; an index or manifest link alone is insufficient. Never target `main` from an issue branch.

## Run independent review

After the draft PR exists, spawn the project agent `echo_ui_pr_reviewer` with a fresh context. Give it only the issue snapshot, acceptance criteria, repository instructions, base SHA, head SHA, diff, CI results, and evidence manifest. Do not give it executor conversation history or rationale.

Publish every round through the installed wrapper with role `reviewer`; the executor identity may not author it. Every PR write must include `--repo codeacme17/echo-ui` (or use the full configured PR URL). Use `gh pr review --comment --body <body>` for a body-only review and include the exact run/cycle/round/head marker; the gate rejects body files, skipped rounds, duplicates, and publications outside the next durable cycle. When file/line findings require inline comments, use only the reviewer's gated `POST repos/codeacme17/echo-ui/pulls/<recorded-pr>/reviews` API shape with `event=COMMENT`, the exact durable head, and validated inline fields. Post findings verbatim as one review plus inline comments. Each finding needs a run-wide stable ID, severity, confidence, evidence, expected resolution, and the published GitHub inline comment ID or `null` for a body-only finding. Record the GitHub review URL for each round. Accepted repairs must start after that round was submitted, and executor replies must be posted through the automation wrapper after the corresponding `$implement` invocation finishes. One executor response comment may resolve only one finding. Follow `review/REVIEW.md` and `review/response-policy.md`.
Publish every round through the installed wrapper with role `reviewer`; the executor identity may not author it. Every PR write must include `--repo codeacme17/echo-ui` (or use the full configured PR URL). Use `gh pr review --comment --body <body>` for a body-only review and include the exact run/cycle/round/head marker; the gate rejects body files, skipped rounds, duplicates, and publications outside the next durable cycle. When file/line findings require inline comments, use the installed `publish-review.mjs` command through the reviewer wrapper. Give it the recorded PR number and head, cycle and round, inline body text, and one canonical JSON object per comment; the trusted publisher validates every field and submits one exact-head `COMMENT` review. Do not construct nested `gh api` fields directly. Post findings verbatim as one review plus inline comments. Each finding needs a run-wide stable ID, severity, confidence, evidence, expected resolution, and the published GitHub inline comment ID or `null` for a body-only finding. Record the GitHub review URL for each round. Accepted repairs must start after that round was submitted, and executor replies must be posted through the automation wrapper after the corresponding `$implement` invocation finishes. One executor response comment may resolve only one finding. Follow `review/REVIEW.md` and `review/response-policy.md`.

The executor must classify every finding as `accepted`, `rejected`, `needs-human`, `stale`, or `already-fixed`:

Expand Down
2 changes: 1 addition & 1 deletion loops/issue-dev-loop/references/github-operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Publish reviewer output only as a non-approving comment review:
"$ECHO_UI_LOOP_CONTROL_PLANE/scripts/with-github-identity" --loop-root "$ECHO_UI_LOOP_TARGET_ROOT" reviewer -- gh pr review <number> --repo codeacme17/echo-ui --comment --body <review-body>
```

The shell launcher removes Node preload hooks before starting the router. The router then builds a strict child environment, rejects reviewer pushes and every reviewer mutation except a comment-only review on the recorded PR, and rejects approvals, change requests, merges, executor-authored reviews, GraphQL, and administration APIs. Reviewer publication requires the next run/cycle/round marker; the gate paginates existing reviews and rejects duplicates, skipped rounds, body files, or an omitted reviewer publication. A reviewer API write is permitted only for one exact-head `event=COMMENT` review with validated inline fields. Authenticated Git disables worktree hooks, fsmonitor, external diff, textconv, proxy environment variables, repository-local HTTP/proxy/cookie/header/SSL/URL rewrites, and the `ext` transport. Remote Git is restricted to exact origin push/fetch/issue-branch discovery shapes and executes against a canonical configured-repository HTTPS URL. Automation API mutations are limited to the current issue's exact claim label, the current issue/PR or journal comments, and current-PR review-comment replies. PR bodies and comments must be inline; body files, API input files, and typed `@file` expansion are rejected. PR creation requires the durably authorized issue or published evolve request branch, explicit `--repo codeacme17/echo-ui`, `--base dev`, and `--draft`; later PR writes require the same explicit repository (or full configured PR URL), the exact durable checkpoint, the recorded live PR branch/base/head, and the phase-specific Draft/evidence/review gates. `pr edit` is limited to title/body updates and requesting `codeacme17`; non-`--undo` `pr ready` is rejected because only the owner may mark a Draft Ready. Issue pushes derive `codex/issue-<number>` from the durable checkpoint, require a clean exact local issue branch whose post-`$implement` commits contain only the current run's evidence paths, and reject local branch overrides; evolve pushes require the automation-authored request publication. Every other push shape is rejected.
The shell launcher removes Node preload hooks before starting the router. The router then builds a strict child environment, rejects reviewer pushes and every reviewer mutation except a comment-only review on the recorded PR, and rejects approvals, change requests, merges, executor-authored reviews, GraphQL, and administration APIs. Reviewer publication requires the next run/cycle/round marker; the gate paginates existing reviews and rejects duplicates, skipped rounds, body files, or an omitted reviewer publication. Body-only reviews use the validated `gh pr review --comment` shape. Inline reviews must use the installed `publish-review.mjs`; it accepts only canonical comment JSON, validates the durable exact head and finding markers, and is the sole component allowed to stream a canonical `event=COMMENT` payload to GitHub. Authenticated Git disables worktree hooks, fsmonitor, external diff, textconv, proxy environment variables, repository-local HTTP/proxy/cookie/header/SSL/URL rewrites, and the `ext` transport. Remote Git is restricted to exact origin push/fetch/issue-branch discovery shapes and executes against a canonical configured-repository HTTPS URL. Automation API mutations are limited to the current issue's exact claim label, the current issue/PR or journal comments, and current-PR review-comment replies. PR bodies and comments must be inline; body files, arbitrary API input files, and typed `@file` expansion are rejected. PR creation requires the durably authorized issue or published evolve request branch, explicit `--repo codeacme17/echo-ui`, `--base dev`, and `--draft`; later PR writes require the same explicit repository (or full configured PR URL), the exact durable checkpoint, the recorded live PR branch/base/head, and the phase-specific Draft/evidence/review gates. `pr edit` is limited to title/body updates and requesting `codeacme17`; non-`--undo` `pr ready` is rejected because only the owner may mark a Draft Ready. Issue pushes derive `codex/issue-<number>` from the durable checkpoint, require a clean exact local issue branch whose post-`$implement` commits contain only the current run's evidence paths, and reject local branch overrides; evolve pushes require the automation-authored request publication. Every other push shape is rejected.

## Selection and claim

Expand Down
2 changes: 1 addition & 1 deletion loops/issue-dev-loop/review/REVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Do not emit formatter noise, personal style preferences, speculative concerns, u

## Publication

The fresh reviewer publishes each round verbatim through `reviewerGitHubLogin` as one non-approving GitHub review, adding `<!-- issue-dev-loop:<run-id>:<finding-id> -->` for deduplication and `<!-- issue-dev-loop:<run-id>:review-cycle:<cycle>:round:<round>:head:<sha> -->` to the round body. A body-only round uses the gated `gh pr review --comment --body <body>` command; body files are rejected so the identity gate can validate the marker before publication. Findings with a concrete file and line must be posted in one gated `POST repos/<configured-repo>/pulls/<recorded-pr>/reviews` call whose event is exactly `COMMENT`, commit ID is the durable recorded head, and inline path/line/side/body fields carry the finding markers; arbitrary input files and every other mutating API shape are rejected. Cross-cutting findings remain in the review body. The reviewer identity must differ from the executor and owner.
The fresh reviewer publishes each round verbatim through `reviewerGitHubLogin` as one non-approving GitHub review, adding `<!-- issue-dev-loop:<run-id>:<finding-id> -->` for deduplication and `<!-- issue-dev-loop:<run-id>:review-cycle:<cycle>:round:<round>:head:<sha> -->` to the round body. A body-only round uses the gated `gh pr review --comment --body <body>` command; body files are rejected so the identity gate can validate the marker before publication. Findings with a concrete file and line must be posted with the installed `publish-review.mjs` through the reviewer wrapper. Pass `--loop-root`, `--pr`, the durable `--head`, `--cycle`, `--round`, the inline `--body`, and one `--comment` canonical JSON object for each finding. Each comment object contains only `path`, `line`, `side`, and `body`; the trusted publisher validates exact-head state, markers, paths, lines, sides, ordering, and uniqueness before submitting one `COMMENT` review with a canonical JSON payload. Do not construct nested `gh api` fields or pass arbitrary input files. Cross-cutting findings remain in the review body. The reviewer identity must differ from the executor and owner.

Before the final round is published, write the complete cycle result with a temporary/unassigned final `reviewUrl` and run the installed `loopctl review-digest --result <path>`. Put its returned `<!-- issue-dev-loop:<run-id>:review-result-sha256:<digest> -->` marker in the final body. After GitHub assigns the review URL, replace the temporary value and rerun `review-digest`; it must be unchanged. This canonical publication digest replaces only review URLs with a fixed placeholder and therefore avoids a URL↔digest cycle. The later recorded full-file digest still protects the final URLs and every other byte. The reviewer must not downgrade severity or omit findings.

Expand Down
2 changes: 1 addition & 1 deletion loops/issue-dev-loop/review/reviewer-prompt.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Review the Echo UI PR diff between `<base-sha>` and `<head-sha>` as an independent, fresh-context reviewer for review cycle `<cycle>`. Use `$code-review`. Read only the supplied issue snapshot, acceptance criteria, repository instructions, diff, CI results, and evidence manifest. Follow `loops/issue-dev-loop/review/REVIEW.md`. Do not edit files or rely on executor conversation history. Publish a body-only non-approving review through `"$ECHO_UI_LOOP_CONTROL_PLANE/scripts/with-github-identity" --loop-root "$ECHO_UI_LOOP_TARGET_ROOT" reviewer -- gh pr review <number> --repo codeacme17/echo-ui --comment --body <review-body>` and include the exact run/cycle/round/head marker. Before a final round, use the installed `loopctl review-digest` procedure so the marker is computed before GitHub assigns the final review URL. If file/line findings require inline comments, use the same installed launcher with only the strict `gh api repos/codeacme17/echo-ui/pulls/<number>/reviews --method POST` COMMENT-review field shape documented by `REVIEW.md`. Never use the repository launcher for credentials, invoke the `.mjs` router directly, run raw `gh`, use `--body-file`, use `--input`, call any other mutating API, approve/request changes/merge, or alter global authentication. Return structured findings or `PASS` and the unique review URL.
Review the Echo UI PR diff between `<base-sha>` and `<head-sha>` as an independent, fresh-context reviewer for review cycle `<cycle>`. Use `$code-review`. Read only the supplied issue snapshot, acceptance criteria, repository instructions, diff, CI results, and evidence manifest. Follow `loops/issue-dev-loop/review/REVIEW.md`. Do not edit files or rely on executor conversation history. Publish a body-only non-approving review through `"$ECHO_UI_LOOP_CONTROL_PLANE/scripts/with-github-identity" --loop-root "$ECHO_UI_LOOP_TARGET_ROOT" reviewer -- gh pr review <number> --repo codeacme17/echo-ui --comment --body <review-body>` and include the exact run/cycle/round/head marker. Before a final round, use the installed `loopctl review-digest` procedure so the marker is computed before GitHub assigns the final review URL. If file/line findings require inline comments, use the same installed launcher to run `node "$ECHO_UI_LOOP_CONTROL_PLANE/scripts/publish-review.mjs"` with the exact arguments documented by `REVIEW.md`; provide each comment as canonical JSON. Never use the repository launcher for credentials, invoke the `.mjs` router directly, run raw `gh`, construct nested API fields, use `--body-file`, call any other mutating API, approve/request changes/merge, or alter global authentication. Return structured findings or `PASS` and the unique review URL.
Loading