The run_case_capture helper was being called in command substitution
(out=$(run_case_capture ...)), which runs it in a subshell. This caused
the ok/bad updates to the pass/fail counters to be discarded.
Fix by having the helper write output to a caller-provided file parameter,
then reading from that file in the caller. This keeps the helper in the
parent shell where counter updates are preserved.
Addresses Codex P2 review on commit ec30c8a7.
Co-authored-by: Ed Langley <fiddlerwoaroof@users.noreply.github.com>
1. Shebang (Codex P2): scripts/agent-bootstrap.sh and .claude/hooks/session-start.sh
now use #!/usr/bin/env bash instead of #!/bin/bash, matching repo convention
enforced by checkers.sh.
2. Fail-closed bd pin (Codex P2): .claude/hooks/session-start.sh local path now
exits 2 with a warning when pinned or running version cannot be parsed,
instead of silently succeeding. An unparseable version is not a pass.
3. pr-reviews failure (Codex P2): scripts/pr-watch no longer uses '|| true' to
swallow pr-reviews failures. If pr-reviews fails (fetch error, malformed
response), pr-watch now exits 6 with a warning. Empty successful fetch
(no reviews) is still exit 0.
- Added exit 6 to usage text and skill documentation
- Added test case 'pr-reviews failure exits 6' using malformed JSON fixture
- All 57 pr-watch tests pass
Co-authored-by: Ed Langley <fiddlerwoaroof@users.noreply.github.com>
Every GitHub write (PR, comment, review reply) must include an attribution line
identifying the AI agent. Posts go out under the repository owner's account, so
an unattributed post reads as the human's words.
Format: _Posted by <Agent Stack> (<model>)_
Examples:
- _Posted by Claude (Opus 4.5)_
- _Posted by Cursor Agent (claude-sonnet-5)_
AGENTS.md:
- Added 'GitHub Attribution (Hard Rule)' section in multi-stack docs
- Concrete format and examples
- Clarified that a thread is not 'answered' until the reply has attribution
.agents/skills/pr-watch/SKILL.md:
- Added 'GitHub Attribution (Hard Rule)' subsection
- Updated 'Answer substantive feedback with attribution' in obligations
- Cross-references AGENTS.md for full rule
context/cloud-agents.md:
- Added 'GitHub Attribution (Hard Rule)' section
- Same format and examples as AGENTS.md
This ensures any agent reading the shared docs (Cursor, Claude, etc.) knows to
attribute every GitHub write to the specific AI agent.
Co-authored-by: Ed Langley <fiddlerwoaroof@users.noreply.github.com>
The pr-watch skill and script now cover reviews/comments, not just CI checks.
An agent reading only the pr-watch skill now knows to track both.
.agents/skills/pr-watch/SKILL.md:
- Reframed: 'watching a PR' means checks AND reviews
- Added 'Reviews and Comments' section with the three surfaces table
- Added 'Review Obligations' subsection (answer feedback, identity line, etc.)
- Documented --reviews (default) and --no-reviews flags
- Cross-references AGENTS.md for full workflow details
scripts/pr-watch:
- Added --reviews (default) and --no-reviews flags
- After exit 0 (green/mergeable), calls scripts/pr-reviews to show all
reviews and comments. Does not change exit code — answering is agent's job.
- Updated usage text to document the new behavior
- Composes with existing pr-reviews (fixture mode passes through)
scripts/pr-watch-test.sh:
- Added mk_reviews_empty() and mk_reviews_with_review() helpers
- Added review fixtures to all cases that exit 0 (pr-reviews needs them)
- Added tests: 'green with reviews shows review output' and
'--no-reviews skips review output'
- All 56 tests pass
AGENTS.md / context/cloud-agents.md:
- Updated cross-references to point to pr-watch skill as agent-facing recipe
- Simplified text now that pr-watch handles reviews automatically
Co-authored-by: Ed Langley <fiddlerwoaroof@users.noreply.github.com>
Multi-stack agents (especially Cursor cloud) may focus on pr-watch (CI checks
only) and miss review feedback. This makes the obligation explicit.
AGENTS.md - new 'PR Tracking: Checks AND Reviews' subsection:
- Fetch reviews AND comments (reviews are separate API surface)
- Codex/ChatGPT reviews arrive as reviews, not comments
- Use ./scripts/pr-reviews <n> to see all feedback together
- Answer substantive feedback with identity line before done/merge
- Re-check after push that reviews target current head SHA
- Don't wait indefinitely on Copilot/Codex (quota-limited)
- Points to existing wave essay for full workflow
context/cloud-agents.md - new 'PR Tracking' section:
- Brief summary of the obligation
- Points to pr-watch skill for CI, scripts/pr-reviews for reviews
- Cross-references AGENTS.md for full details
Co-authored-by: Ed Langley <fiddlerwoaroof@users.noreply.github.com>
User ruling: agents must work inside nix develop (or direnv) for this repo.
Bare system cargo that fails edition2024 is a misconfigured session.
Changes:
1. scripts/agent-bootstrap.sh:
- Added section 0: seed nix flake inputs automatically
- Cargo warm now runs inside 'nix develop --command'
- Added --skip-nix-seed flag for environments that don't need it
- Updated environment notes to emphasize nix-first
2. .cursor/environment.json:
- Removed --skip-cargo-warm (full nix-backed warm now default)
3. AGENTS.md:
- Added 'Toolchain' row to multi-stack table (nix develop required)
- Added 'Toolchain Requirement' subsection with usage examples
- Updated local agents guidance to use 'direnv allow'
4. context/cloud-agents.md:
- Bootstrap now lists nix-seed as step 1
- 'What does not work' table updated: bare system cargo now listed as
failing; nix develop works after bootstrap
- Updated nix section to reflect automatic seeding
Previous soft gap: nix-seed was a manual footnote; now it runs in bootstrap.
Co-authored-by: Ed Langley <fiddlerwoaroof@users.noreply.github.com>
This commit implements the download flow for SaveAs and ExportCsv per the
USER RULING on improvise-2mqz. The correct shape is:
- A request frame asks the host for BYTES
- ServerFrame returns the bytes (or Rejected)
- Browser triggers downloads via Blob + <a download>
Key changes:
Protocol layer (improvise-protocol):
- Add Request::DownloadDocument and Request::DownloadCsv variants
- Add ClientFrame::DownloadDocument and ClientFrame::DownloadCsv
- Add ServerFrame::DocumentBytes and ServerFrame::CsvBytes
- Add KeyOutcome::LocalThenRequest variant for operations that need
both local fold (mode change, buffer clear) AND a server request
- Update stranding() to unstrand SavePrompt and ExportPrompt modes
- Update keymap to use rebind() instead of commit() for commit-save
and commit-export (because LocalThenRequest can't be in a Sequence)
Host layer (improvise-command):
- Handle new ClientFrames in host.rs returning bytes or Rejected
- Add Rejection::ExportFailed variant for CSV export failures
- Update CommitSave and CommitExport to clear their buffers
- Make render_csv() public in improvise-io for host use
WASM client layer (improvise-wasm-client):
- Add PendingDownload type with filename, bytes, and kind
- Store pending downloads for JavaScript retrieval via take_pending_download()
Browser layer (web/app.js):
- Add triggerDownload() function using Blob + <a download>
- Poll for pending downloads after frame handling
This unstrands SavePrompt and ExportPrompt which were previously refused
by stranding() due to missing wire forms.
Refs: improvise-2mqz
Co-authored-by: Ed Langley <fiddlerwoaroof@users.noreply.github.com>
- `Category`, `Item` and `View` each gain a private `display` that starts equal
to the key and changes only through `set_display` / `set_item_display`.
- `CategoryRow`, `TileEntry` and `ViewSummary` carry `display` beside their key
field. The key stays what commands are composed from.
- The category-panel headers, the tile bar and the view list paint the display
in the TUI and the browser. The active-view marker still compares keys.
- No production code sets a display yet, so behaviour is unchanged.
- This is the first slice of ADR 007 step 2. The grid, page bar, records labels,
item rows and CSV export are improvise-cq1q.12; messages and the view title
are improvise-cq1q.13.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
Unifies coding-agent setup across Claude Code and Cursor so both stacks get:
- Pin-matched bd from flake.nix
- Fresh Dolt beads tracker sync (not stale JSONL export)
- Same skills via symlinks to .agents/skills/
Key changes:
1. scripts/agent-bootstrap.sh: stack-agnostic bootstrap that handles bd
installation, tracker sync, and optional cargo warming. Works for any
agent stack (Claude, Cursor, or manual).
2. .claude/hooks/session-start.sh: now a thin wrapper that calls the
shared bootstrap for cloud sessions, keeping only the local pin-check
inline.
3. .cursor/environment.json: configures Cursor cloud agents to run the
bootstrap via 'install'.
4. .cursor/skills/: symlinks to .agents/skills/* so Cursor agents
discover the same skills Claude has.
5. AGENTS.md: adds Multi-Stack Agent Support section; clarifies that
scripts/kb is the KB interface (Prolog MCP is not required and not
available in all stacks).
6. context/cloud-agents.md: updated for multi-stack support; added KB
section emphasizing scripts/kb over Prolog MCP.
The canonical skill source remains .agents/skills/. Both .claude/skills/
and .cursor/skills/ are symlinks to it, so there is one truth that both
stacks read.
Co-authored-by: Ed Langley <fiddlerwoaroof@users.noreply.github.com>
IdAllocator::suffixed recursed once per taken candidate, and the call was not
in tail position. A document claiming item-1 through item-N aborted the process
on a stack overflow at N of about 11,000 in debug. This answers the Codex P2 on
PR #318. The loop still advances the counter on every candidate it tries.
Three tests are added:
- a long claimed run (20,000), which aborted before the fix;
- claim refusing lookalike virtual ids (_indexer, _measure-1), which the
review's prefix-match rival passed before;
- a display with leading spaces that must not slug into the reserved `_` space.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
Regenerated with `crate2nix generate` (0.15.0, from the dev shell). The new
file adds the unicase 2.9.0 crate and the improvise-core edge to it. It also
picks up the test-support feature edges that main's Cargo.lock already had
and Cargo.nix was missing.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze