Skip to content

feat: back link specs to their pull request#75

Merged
satyaborg merged 1 commit into
mainfrom
feat/spec-pr-backlink
Jun 23, 2026
Merged

feat: back link specs to their pull request#75
satyaborg merged 1 commit into
mainfrom
feat/spec-pr-backlink

Conversation

@satyaborg

Copy link
Copy Markdown
Owner

Backlink specs to their pull request

Problem

Every spec carries a pr: null frontmatter slot, and devloop already opens a draft PR and captures its URL in $PULL_REQUEST (devloop:2267), yet nothing ever writes that URL back into the spec. So pr: null stays null forever and there is no link from a spec to the PR that implemented it. The moment it hurts: revisiting a spec weeks later with no idea which PR (if any) shipped it, forcing a dig through devloop reports or gh pr list to reconnect the two.

Outcome

After a successful devloop <spec> run, the source spec file's frontmatter pr: field holds the full PR URL (e.g. pr: https://github.com/owner/repo/pull/123) instead of pr: null, and every other byte of the spec is unchanged.

Acceptance Criteria

AC1: After a --create-pr run that opens PR URL U, the source spec's frontmatter pr: value equals U (full URL) and no other line in the spec changes.
AC2: Calling the helper when pr: already equals U leaves the file byte-for-byte identical (idempotent).
AC3: A spec whose frontmatter lacks a pr: line gains a pr: U line inside the frontmatter block; a spec with no closing frontmatter delimiter is left unchanged.
AC4: A run invoked without --create-pr leaves the spec's pr: field unchanged.
AC5: A failed backlink write (e.g. unwritable spec) does not change the run's exit status or final STATUS.
AC6: bash scripts/devloop_test.sh passes, including a new test that covers the helper.

Review Trail

Review rounds and the final report are posted as PR comments below.


Spec: .devloop/specs/2026-06-18-spec-pr-backlink.md

Generated by devloop.sh

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 22, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
devloop 3829f00 Commit Preview URL

Branch Preview URL
Jun 22 2026, 01:36 PM

@satyaborg

Copy link
Copy Markdown
Owner Author

Devloop Review Round 1

  • Verdict: ACCEPT

Review 1

Verdict: ACCEPT

Acceptance matrix

Criterion Status Implementation evidence Test evidence
AC1 PASS Call site sync_spec_pr "$spec" "$PULL_REQUEST" (devloop:2353) inside the create_pr success branch; awk replaces the in-frontmatter pr: line and leaves all other lines via { print } (devloop:2883-2893). devloop_test.sh:502-506: cmp -s against an expected file that differs only in the pr: line, with a decoy body line Body mentions pr: leave me alone. proving body pr: mentions are untouched.
AC2 PASS Early return on idempotency: frontmatter_value pr compared to $urlreturn 0 with zero writes (devloop:2868-2870). frontmatter_value strips only the first colon (sub(/^[^:]*:.../, devloop:2845) so the full URL compares correctly. devloop_test.sh:508-510: snapshot then second call, cmp -s confirms byte-for-byte identity.
AC3 PASS Insert pr: <url> before the closing --- when no pr: line was seen (if (!replaced), devloop:2877-2882); END { if (!closed) exit 1 } (devloop:2894) makes a spec with no closing delimiter skip mv (devloop:2895), leaving the file untouched. Verified live: empty/closing-only frontmatter inserts correctly. devloop_test.sh:512-517 (insert, cmp against expected) and :519-523 (malformed: asserts non-zero return + cmp unchanged).
AC4 PASS sync_spec_pr is the sole writer of pr: (grep: defined devloop:2860, called only devloop:2353), and the call is nested in if [ "$create_pr" = true ] && [ -n "$PASS_COMMIT" ] (devloop:2348) → the writer is unreachable without --create-pr. No executable run-level test; verified by sole-call-site inspection. This path's behavior is unchanged by the diff (the change only adds a call inside the create_pr branch), and the spec test plan is helper-scoped. See Notes.
AC5 PASS Caller wraps as if ! sync_spec_pr ...; then event_log ... with no STATUS mutation and no break (devloop:2353-2355); helper never references STATUS and returns 1 on write failure (devloop:2898-2899). devloop_test.sh:525-542: read-only dir forces mv failure (root-guarded), asserts non-zero return, STATUS stays running, and spec is unchanged.
AC6 PASS New helper + unit test added. bash scripts/devloop_test.sh rerun: exit 0, 54 ok / 0 not ok, including ok - sync_spec_pr and ok - 100% project function coverage (the coverage gate forces the helper to be exercised).

Engineering quality matrix

Area Status Evidence
Correctness PASS Single-pass awk handles replace, insert, malformed-skip, and idempotent paths; body lines (including a body --- and pr: decoys) pass through untouched, verified by live run. set -e/-u/pipefail safe: every control-flow failure sits in an if/|| context. URL passed via awk -v and string-concatenated, never interpolated into a regex/replacement.
Test quality PASS Byte-level cmp assertions (not just value checks), a decoy body line, a true write-failure case via read-only dir with STATUS preservation, root-guarded. Red reproduced independently (sync_spec_pr: command not found, rc 127 → || fail); green confirmed.
Maintainability PASS ~40-line helper placed directly after frontmatter_value, mirrors its name/style and reuses it for the idempotency read; self-documenting awk.
Architecture boundaries PASS Pure file operation plus one guarded call site in the pass loop; no feature logic leaks into shared modules; reuses the canonical reader.
Simplicity PASS One awk pass covers all cases; no wrappers, casts, flags, or nullable modes; 91 insertions, 0 deletions.
Security PASS URL via awk -v (no regex/shell injection), spec path quoted, mktemp for the temp file; PR URL originates from gh/git (trusted).
Operational safety PASS Atomic mv over the source spec (same filesystem), best-effort and non-fatal, failure surfaced via event_log without touching STATUS. Cross-device TMPDIR would degrade mv to non-atomic copy+unlink but stays functionally correct (see Notes).

Review flags

  • Silent decision: absent - The mode→0600 flip (from mktemp+mv), silent-on-success, and trailing-newline normalization are all recorded in the track's Design tradeoffs / Residual risk, and the awk-to-temp-then-mv approach was mandated by the spec.
  • Scope drift: absent - Exactly the helper + one call site + a unit test; no deletions, no unrelated edits. README.md left unchanged is justified (the only --create-pr mention is a one-line command-table entry that stays accurate).
  • Missing test: absent - All behavior the diff changes (the helper's replace/idempotent/insert/malformed/write-failure paths) has targeted tests. AC4 concerns behavior the diff does not change.

Findings

None.

Missing tests

  • None. (AC4 has no run-level test, but it asserts unchanged behavior on a path the diff does not touch and is structurally guaranteed by the sole guarded call site; the spec's test plan is deliberately helper-scoped. Noted as transparency, not a blocking gap.)

Fix instructions

None.

Notes

  • Verdict rationale: all six acceptance criteria pass with concrete code and test evidence, every engineering row passes, red/green is independently reproduced, the full suite is green (54/0) with the 100% function-coverage gate satisfied, and shellcheck is clean. The change is tightly scoped and should ship.
  • AC4 is verified by inspection rather than an executable test. This is defensible here: sync_spec_pr is the only writer of pr: (grep-confirmed) and its single call site is inside the create_pr guard, so a non---create-pr run has no path to the writer. The diff adds no new behavior to that path, so there is no changed behavior left underverified.
  • Documented, genuinely-minor residual risks (acknowledged in the track): mv from a mktemp temp resets the spec's mode to 0600 — spec-sanctioned since portable mode preservation (chmod --reference) is GNU-only; and a spec saved without a trailing newline gains one on first backlink, idempotent thereafter.
  • Optional future polish (non-blocking, not required by the spec): creating the temp file in the spec's own directory rather than ${TMPDIR:-/tmp} would guarantee an atomic same-filesystem rename; the read-only-dir failure path (AC5) would still behave identically.

@satyaborg

Copy link
Copy Markdown
Owner Author

Devloop Final Report

Field Value
Final status accepted
Pass count 1 / 5
Final verdict ACCEPT
PR URL #75
Branch feat/spec-pr-backlink

Acceptance Matrix Summary

Acceptance matrix

Criterion Status Implementation evidence Test evidence
AC1 PASS Call site sync_spec_pr "$spec" "$PULL_REQUEST" (devloop:2353) inside the create_pr success branch; awk replaces the in-frontmatter pr: line and leaves all other lines via { print } (devloop:2883-2893). devloop_test.sh:502-506: cmp -s against an expected file that differs only in the pr: line, with a decoy body line Body mentions pr: leave me alone. proving body pr: mentions are untouched.
AC2 PASS Early return on idempotency: frontmatter_value pr compared to $urlreturn 0 with zero writes (devloop:2868-2870). frontmatter_value strips only the first colon (sub(/^[^:]*:.../, devloop:2845) so the full URL compares correctly. devloop_test.sh:508-510: snapshot then second call, cmp -s confirms byte-for-byte identity.
AC3 PASS Insert pr: <url> before the closing --- when no pr: line was seen (if (!replaced), devloop:2877-2882); END { if (!closed) exit 1 } (devloop:2894) makes a spec with no closing delimiter skip mv (devloop:2895), leaving the file untouched. Verified live: empty/closing-only frontmatter inserts correctly. devloop_test.sh:512-517 (insert, cmp against expected) and :519-523 (malformed: asserts non-zero return + cmp unchanged).
AC4 PASS sync_spec_pr is the sole writer of pr: (grep: defined devloop:2860, called only devloop:2353), and the call is nested in if [ "$create_pr" = true ] && [ -n "$PASS_COMMIT" ] (devloop:2348) → the writer is unreachable without --create-pr. No executable run-level test; verified by sole-call-site inspection. This path's behavior is unchanged by the diff (the change only adds a call inside the create_pr branch), and the spec test plan is helper-scoped. See Notes.
AC5 PASS Caller wraps as if ! sync_spec_pr ...; then event_log ... with no STATUS mutation and no break (devloop:2353-2355); helper never references STATUS and returns 1 on write failure (devloop:2898-2899). devloop_test.sh:525-542: read-only dir forces mv failure (root-guarded), asserts non-zero return, STATUS stays running, and spec is unchanged.
AC6 PASS New helper + unit test added. bash scripts/devloop_test.sh rerun: exit 0, 54 ok / 0 not ok, including ok - sync_spec_pr and ok - 100% project function coverage (the coverage gate forces the helper to be exercised).

Engineering Quality Summary

Engineering quality matrix

Area Status Evidence
Correctness PASS Single-pass awk handles replace, insert, malformed-skip, and idempotent paths; body lines (including a body --- and pr: decoys) pass through untouched, verified by live run. set -e/-u/pipefail safe: every control-flow failure sits in an if/|| context. URL passed via awk -v and string-concatenated, never interpolated into a regex/replacement.
Test quality PASS Byte-level cmp assertions (not just value checks), a decoy body line, a true write-failure case via read-only dir with STATUS preservation, root-guarded. Red reproduced independently (sync_spec_pr: command not found, rc 127 → || fail); green confirmed.
Maintainability PASS ~40-line helper placed directly after frontmatter_value, mirrors its name/style and reuses it for the idempotency read; self-documenting awk.
Architecture boundaries PASS Pure file operation plus one guarded call site in the pass loop; no feature logic leaks into shared modules; reuses the canonical reader.
Simplicity PASS One awk pass covers all cases; no wrappers, casts, flags, or nullable modes; 91 insertions, 0 deletions.
Security PASS URL via awk -v (no regex/shell injection), spec path quoted, mktemp for the temp file; PR URL originates from gh/git (trusted).
Operational safety PASS Atomic mv over the source spec (same filesystem), best-effort and non-fatal, failure surfaced via event_log without touching STATUS. Cross-device TMPDIR would degrade mv to non-atomic copy+unlink but stays functionally correct (see Notes).

Implementation Summary

  • Final branch: feat/spec-pr-backlink
  • Final commit: 3829f00
  • Commit message: feat: spec-pr-backlink

Commit References

  • pass 1 3829f00 feat: spec-pr-backlink (devloop, scripts/devloop_test.sh)

Tests Run

  • Verification hook log: not configured
  • Review test evidence: see the acceptance matrix summary above.

Residual Risk

  • No blocking residual risk was recorded by the final review.

@satyaborg satyaborg changed the title feat: spec-pr-backlink feat: back link specs to their pull request Jun 23, 2026
@satyaborg satyaborg marked this pull request as ready for review June 23, 2026 06:29
@satyaborg satyaborg merged commit 9d3f1c7 into main Jun 23, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant