helpers: cwd-dependent forge-block resolution + unchecked exit codes read as empty data in caller glue #33
Labels
No labels
component:adapters
component:lifecycle
component:qa
component:setup
component:shared
component:worktrees
phase/accepted
phase/backlog
phase/deployed
phase/developing
phase/integrating
phase/planning
phase/qa
phase/requirements
phase/uat
priority:critical
priority:critical
priority:high
priority:high
priority:low
priority:low
priority:medium
priority:medium
type:bug
type:chore
type:docs
type:feature
type:infra
type:tech-debt
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
jbr870/devwork-skills#33
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Observation
Helpers walk up from
$PWDfor a project CLAUDE.md with aforge:block. Invoked from outside the project tree (typically the session scratchpad dir), they die correctly —helper: no project CLAUDE.md with a forge: block found from /tmp/claude-1000/... upwardon stderr, non-zero exit, nothing on stdout (_lib.sh_die, verified at HEAD) — but the calling glue routinely swallows that:X="$(helper ...)"with the error unexamined, thenjqover the empty string yieldsnull, which reads exactly like "no such comment/decision".Observed in three of the five 2026-08-12 verity transcripts (slot1 ×1, slot3 ×3, slot6 ×1), and reported first-hand by the verity-release session the same week: "a bare
nullon stdout — which reads exactly like 'no such decision' if you're only parsing stdout. I hit this earlier today."Recurrence
4 sessions (3 transcript-confirmed + 1 first-hand). The helper behaves correctly; the gap is caller-side: no canonical rule says helper invocations must run with cwd inside the project (or set
DEVWORK_PROJECT_ROOT) and must check the exit code before parsing stdout.Hypothesis
One rule in the canonical helper-invocation text (
phase-outcome.mdpreamble, where "invoke the shims, never inline adapter mechanics" already lives): runbin/*helpers with the project as cwd — after anycdaway (scratchpad work),cdback or setDEVWORK_PROJECT_ROOT; and never parse a helper's stdout without its exit status (out="$(helper ...)" || { …fail loudly… }). Emitted-glue examples in skills should model the rc check.Suggested lane
meta-amend (one canonical-doc rule + example shape).
Filed by /meta-retrospective 2026-08-13 (transcript sweep over tailscale SSH).
Outcome — amended (commit
e3a5369)Added the third invocation rule to phase-outcome.md's preamble blockquote (the canonical home of "never inline adapter mechanics" and "jq only"): run helpers with the project as cwd (cd back or export DEVWORK_PROJECT_ROOT after any scratchpad excursion), and never trust an empty/
nullstdout without rc 0 — with the capture-and-check fence as the required shape.Gate: lint clean. Desk-check vs originating scenario: slot3's three scratchpad-cwd failures produced stderr dies that caller glue read as empty results; with this rule the capture-and-check shape turns each into a loud rc≠0 stop naming stderr. Validates on the next dogfood runs.
tea apiexits 0 on HTTP errors and prefixes NOTE: lines to stdout — audit every helper that pipes it into jq #260