Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
7772f65
fix(agents): resolve lib scripts via {skill-root}/lib
rawphp Aug 1, 2026
2558809
feat(ORI-238): resolve $SKILL_ROOT once in Load Config
rawphp Aug 1, 2026
e6fa74c
merge(ORI-238): Load Config resolve $SKILL_ROOT once
rawphp Aug 1, 2026
ccf7221
feat(ORI-239): split invoke vs catalog hard-rule; remove help §0b
rawphp Aug 1, 2026
d75ad5c
merge(ORI-239): split invoke vs catalog hard-rule
rawphp Aug 1, 2026
e67205a
feat(ORI-240): fix PR regressions on Files, prose, missing-script paths
rawphp Aug 1, 2026
e121700
feat(ORI-241): finish runtime bash call sites under {skill-root}
rawphp Aug 1, 2026
99e2dc1
merge(ORI-240): integrate worker
rawphp Aug 1, 2026
3063863
merge(ORI-241): integrate worker
rawphp Aug 1, 2026
dfcd5c5
feat(ORI-242): doc-lint bare runtime bash lib/ with allowlist
rawphp Aug 1, 2026
770480f
merge(ORI-242): doc-lint bare runtime bash lib guard
rawphp Aug 1, 2026
1e13cf5
feat(ORI-237): path-unit terminal verified
rawphp Aug 1, 2026
1f4c604
merge(ORI-237): path-unit terminal verified
rawphp Aug 1, 2026
c62b77b
feat(ORI-244): walk-up skill-root resolve in Load Config step 8
rawphp Aug 1, 2026
a2d4588
merge(ORI-244): walk-up skill-root resolve
rawphp Aug 1, 2026
3232157
feat(ORI-245): resolve skill-root before conformance in SKILL.md
rawphp Aug 1, 2026
7f0ad0b
merge(ORI-245): SKILL.md resolve before conformance
rawphp Aug 1, 2026
830ba00
feat(ORI-246): doc-lint cover SKILL.md bare runtime bash lib/
rawphp Aug 1, 2026
b3e142e
merge(ORI-246): doc-lint cover SKILL.md
rawphp Aug 1, 2026
8e84e05
feat(ORI-243): path-unit terminal verified
rawphp Aug 1, 2026
b92886f
merge(ORI-243): path-unit terminal verified
rawphp Aug 1, 2026
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
4 changes: 3 additions & 1 deletion CONTRIBUTING.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -295,7 +295,9 @@ bash lib/tests/doc-lint.test.sh # run its tests

It scans the live, normative docs only — `SKILL.md`, `README.md`, `docs/`, `agents/` — and **never** scans `.do-work/`, `CHANGELOG.md`, `.git/`, or `docs/superpowers/` (the dated spec/plan tree). Those locations legitimately preserve retired terminology; scanning them would reproduce the UR-029 over-broad find-and-replace failure.

**The rule: when you fix a doc conflict, add its pattern to the lint in the same commit.** A fix that doesn't also guard against regression is half a fix — the contradiction can drift back the next time someone edits an adjacent file. Add the new check to `scan_file` (or `scan_judgment_markers`) in `lib/doc-lint.sh` and a planted-violation case to `lib/tests/doc-lint.test.sh`, then confirm `bash lib/doc-lint.sh` is still clean against the repo. If a stale term is legitimately used inside an explicit retirement note, exclude that case narrowly (as the `same-branch` check skips lines that also say `retired`) rather than dropping the pattern.
**Path-scoped pattern — `bare-runtime-bash-lib` (ORI-242 / ORI-246):** under `SKILL.md`, `agents/`, and `references/`, bare runtime invocations of the form `bash lib/...` fail the scan. Runtime docs (including the skill entry) must use `bash {skill-root}/lib/...` after skill-root resolve / Load Config. **Allowlist (skill-dev regression gates only, under `agents/` / `references/`):** `bash lib/tests/...` and `bash lib/conformance-scan.sh` (tracker docs / CONTRIBUTING). **Not allowlisted on `SKILL.md`:** bare `bash lib/conformance-scan.sh` — entry conformance must use the skill-root form (a line that also says `never` is treated as a prohibition note documenting the anti-pattern). Catalog identity `lib/*.sh` without a leading `bash ` is not matched. This pass is separate from the default roots so `references/` is not pulled into unrelated patterns.

**The rule: when you fix a doc conflict, add its pattern to the lint in the same commit.** A fix that doesn't also guard against regression is half a fix — the contradiction can drift back the next time someone edits an adjacent file. Add the new check to `scan_file` (or `scan_judgment_markers` / a path-scoped helper) in `lib/doc-lint.sh` and a planted-violation case to `lib/tests/doc-lint.test.sh`, then confirm `bash lib/doc-lint.sh` is still clean against the repo. If a stale term is legitimately used inside an explicit retirement note, exclude that case narrowly (as the `same-branch` check skips lines that also say `retired`) rather than dropping the pattern. For skill-dev-only bare `bash lib/` lines under `agents/` or `references/`, extend the `bare-runtime-bash-lib` allowlist rather than dropping the pattern — do **not** allowlist bare entry form on `SKILL.md`.

## Questions?

Expand Down
35 changes: 32 additions & 3 deletions SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -98,7 +98,7 @@ Full multi-backend deep dive: [references/tracker.md](references/tracker.md).

**Load path** (every phase that touches work items): (1) [agents/config.md](agents/config.md), (2) resolve `tracker.backend` (default **markdown**), (3) [agents/tracker/port.md](agents/tracker/port.md), (4) `agents/tracker/<backend>.md`, (5) call only named port ops for storage.

**Hard-stop (no silent fallback):** when effective backend is `linear` and Linear is unusable (MCP missing/unauthenticated, team unresolved, missing `status_map` state) **or** `agents/tracker/linear.md` is missing/unreadable, agents **hard-stop** with setup instructions — they never fall through to markdown work-item paths. Canonical contract: `agents/tracker/port.md` + Load Config steps 6–7 in `agents/config.md`.
**Hard-stop (no silent fallback):** when effective backend is `linear` and Linear is unusable (MCP missing/unauthenticated, team unresolved, missing `status_map` state) **or** `agents/tracker/linear.md` is missing/unreadable, agents **hard-stop** with setup instructions — they never fall through to markdown work-item paths. Also hard-stop when skill-root cannot be resolved at entry (Project Root Detection) or later (Load Config step 8). Canonical contract: `agents/tracker/port.md` + Load Config steps 6–8 in `agents/config.md`.

**No dual-write.** With `tracker.backend: linear`, Linear is the **only** work-item store. Agents must not mirror URs/REQs into local markdown as a second source of truth, and must not fall back to markdown when Linear fails (hard-stop instead). After idle migration (`/do-work upgrade migrate`), historical `.do-work/user-requests/` and `archive/` trees remain on disk as **read-only history** — work-item ops ignore them.

Expand All@@ -123,12 +123,41 @@ git rev-parse --show-toplevel
If this fails (not a git repo), use the current working directory.
All references below use `{project}` to mean this resolved root.

### Skill-root resolve (before conformance)

Immediately after resolving `{project}` and **before** the conformance check, resolve `$SKILL_ROOT` / `{skill-root}` — the absolute path of the do-work skill install root (directory containing `lib/` **and** at least one skill marker: `SKILL.md` **or** `agents/`).

**Recipe:** same walk-up as Load Config step 8 in [agents/config.md](agents/config.md) — **not** a second folklore one-level `dirname/..`. Start from the absolute path of **this** file (`SKILL.md`); walk parents until markers match; hard-stop at filesystem root if none found. **No** env / hub / CWD fallback.

```bash
# Start at the directory of this SKILL.md; walk parents until
# markers match (lib/ AND (SKILL.md OR agents/)). Hard-stop at filesystem
# root if none found. No env/hub/CWD fallback.
d="$(cd "$(dirname "<absolute path of SKILL.md>")" && pwd)"
SKILL_ROOT=""
while true; do
if [ -d "$d/lib" ] && { [ -f "$d/SKILL.md" ] || [ -d "$d/agents" ]; }; then
SKILL_ROOT="$d"
break
fi
[ "$d" = "/" ] && break
d="$(dirname "$d")"
done
# non-empty $SKILL_ROOT required — else hard-stop (see below)
```

**Inherit for phase agents:** keep this resolved `$SKILL_ROOT` in context for the whole agent turn. Phase agents (and Load Config step 8) **inherit** it when it is still an absolute directory that satisfies the markers — they re-resolve only if missing, empty, non-absolute, or invalid. Do not invent a second resolve recipe in phase docs.

**Hard-stop when skill-root is unknown at entry.** If the harness did not provide an absolute path for this `SKILL.md` **and** walk-up cannot find a valid skill install root, **stop immediately** — do not run conformance, do not dispatch:

`skill-root unknown: cannot resolve $SKILL_ROOT (walk-up from loaded file; no env/hub/CWD fallback). Provide an absolute path to the loaded instruction file under the skill install root, or a valid pre-resolved $SKILL_ROOT that contains lib/ and (SKILL.md or agents/).`

### Conformance check

Immediately after resolving `{project}` and before executing any subcommand-specific instructions, run the conformance detectors:
Immediately after `$SKILL_ROOT` is resolved and before executing any subcommand-specific instructions, run the conformance detectors via the skill install root (**never** bare `bash lib/conformance-scan.sh` — that assumes CWD is the skill root and fails in consumer projects):

```bash
bash lib/conformance-scan.sh {project}
bash {skill-root}/lib/conformance-scan.sh "{project}"
```

The scanner is read-only and may exit `1` when drift is detected. Interpret each output line as `<row-id> <class> <detail>`:
Expand Down
2 changes: 1 addition & 1 deletion agents/audit.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -45,7 +45,7 @@ Work-item storage (URs, REQs, decisions, verify/close reports, run notes) goes *
**Hard rules:**
- **No silent fallback** from `linear` to `markdown`. If backend is `linear`, do not substitute UR/REQ markdown as the store.
- If backend resolves to **`linear`** but `agents/tracker/linear.md` is **missing or unreadable**, **hard-stop** with setup instructions (restore the Linear backend doc / connect Linear skill). Never fall through to markdown paths.
- Markdown backend: ops map to existing `lib/*.sh` + file flows in `markdown.md` — use those ops; do not re-implement store details here.
- Markdown backend: ops map — **invoke** coordination scripts as `bash {skill-root}/lib/...` after Load Config step 8 resolves `$SKILL_ROOT`; **catalog identity** remains `lib/*.sh` in `markdown.md` — use those ops; do not re-implement store details here.

### 1. Read ground truth

Expand Down
6 changes: 3 additions & 3 deletions agents/capture.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,7 +44,7 @@ Work-item storage (URs, REQs, decisions, verify/close reports, run notes) goes *
**Hard rules:**
- **No silent fallback** from `linear` to `markdown`. If backend is `linear`, do not substitute UR/REQ markdown as the store.
- If backend resolves to **`linear`** but `agents/tracker/linear.md` is **missing or unreadable**, **hard-stop** with setup instructions (restore the Linear backend doc / connect Linear skill). Never fall through to markdown paths.
- Markdown backend: ops map to existing `lib/*.sh` + file flows in `markdown.md` — use those ops; do not re-implement store details here.
- Markdown backend: ops map — **invoke** coordination scripts as `bash {skill-root}/lib/...` after Load Config step 8 resolves `$SKILL_ROOT`; **catalog identity** remains `lib/*.sh` in `markdown.md` — use those ops; do not re-implement store details here.

### Capture REQ store — backend branch (ORI-9)

Expand DownExpand Up@@ -606,7 +606,7 @@ Background about the rename...
After all REQ files are written (Steps 4, 4b, 4c, 4d complete), validate that the `**Depends on:**` graph is acyclic.

```bash
bash lib/cycle-check.sh UR-NNN
bash {skill-root}/lib/cycle-check.sh UR-NNN
```

Replace `UR-NNN` with the actual UR identifier. The script scans all REQs matching that UR across backlog, working, and archive, builds the dep graph, and runs DFS cycle detection.
Expand All@@ -619,7 +619,7 @@ Replace `UR-NNN` with the actual UR identifier. The script scans all REQs matchi
2. Build a fingerprint: `cap-cycle-UR-NNN` (replace UR-NNN with the actual id).
3. Call file-feedback to log the event:
```bash
bash lib/file-feedback.sh cap-cycle "cap-cycle-UR-NNN" \
bash {skill-root}/lib/file-feedback.sh cap-cycle "cap-cycle-UR-NNN" \
'{"ur":"UR-NNN","cycle":"'"$cycle_path"'"}' \
"cap-cycle: circular dependency in UR-NNN" \
"Cycle detected during capture of UR-NNN: $cycle_path"
Expand Down
2 changes: 1 addition & 1 deletion agents/close.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,7 +40,7 @@ Work-item storage (URs, REQs, decisions, verify/close reports, run notes) goes *
**Hard rules:**
- **No silent fallback** from `linear` to `markdown`. If backend is `linear`, do not substitute UR/REQ markdown as the store.
- If backend resolves to **`linear`** but `agents/tracker/linear.md` is **missing or unreadable**, **hard-stop** with setup instructions (restore the Linear backend doc / connect Linear skill). Never fall through to markdown paths.
- Markdown backend: ops map to existing `lib/*.sh` + file flows in `markdown.md` — use those ops; do not re-implement store details here.
- Markdown backend: ops map — **invoke** coordination scripts as `bash {skill-root}/lib/...` after Load Config step 8 resolves `$SKILL_ROOT`; **catalog identity** remains `lib/*.sh` in `markdown.md` — use those ops; do not re-implement store details here.

### Close report home — backend branch (REQ-296)

Expand Down
63 changes: 61 additions & 2 deletions agents/config.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -208,9 +208,68 @@ routing: []

When the effective backend is **`linear`**: load `agents/tracker/port.md` then `agents/tracker/linear.md` for work-item ops after the validations above pass. If `agents/tracker/linear.md` is **missing or unreadable**, **hard-stop** with setup instructions (restore the backend doc from the skill install / Linear skill setup) — **never** fall through to `markdown.md` or invent Linear tool sequences.

**Phase-agent contract:** every phase agent that touches work items follows the **Tracker load path** (config → resolve `tracker.backend` → `port.md` `agents/tracker/<backend>.md` → only named port ops). The shared load path is defined once here and in `agents/tracker/port.md`; each phase agent restates a short copy so a missing wire cannot cause split-brain storage.
8. **Resolve skill-root (`$SKILL_ROOT` / `{skill-root}`).** Once per agent turn, resolve the absolute path of the do-work skill install root — a directory that contains `lib/` **and** at least one skill marker (`SKILL.md` **or** `agents/`). **Token definition:** `{skill-root}` means this resolved absolute path for **all later steps in the same agent turn**. Keep `$SKILL_ROOT` in context; substitute it wherever docs or bash lines write `{skill-root}` (especially `{skill-root}/lib/...`).

**Never fail or stop because of a missing or incomplete config file** (steps 1–5). If config creation or migration fails for any reason, proceed with in-memory defaults (including `tracker.backend: markdown`). **Exception:** step 7 Linear validation (and missing `linear.md`) is a deliberate hard-stop when the operator has opted into `backend: linear` — that is not a config-file completeness problem.
**Single home:** this step is the only place that defines the resolve recipe. `references/run-loop.md` §2a and the run-worker **Skill root** input are thin consumers — they must not invent a second folklore recipe.

**Markers (valid skill install root):** a candidate directory is valid iff **both**:
1. it contains a `lib/` directory, **and**
2. it contains `SKILL.md` **or** an `agents/` directory (or both).

Requiring a co-marker with `lib/` avoids monorepo false roots that happen to have a bare `lib/` higher in the tree.

**Inherit rule:** If `$SKILL_ROOT` is already set in this agent turn's context (orchestrator-passed **Skill root**, or resolved earlier in the same turn) **and** that path is an absolute directory that satisfies the markers above, **keep it — do not re-resolve**. If missing, empty, non-absolute, or invalid (fails markers), clear it and run the walk-up recipe below. Nested agents inherit the entry-resolved root this way.

**Recipe (walk-up from loaded instruction file — no env / hub / CWD fallback):**

One-level `dirname/..` is **not** the algorithm — nested paths (e.g. `agents/tracker/linear.md`) and `SKILL.md` at the skill root need more than a single parent hop.

```bash
# Start at the directory of the loaded instruction file; walk parents until
# markers match (lib/ AND (SKILL.md OR agents/)). Hard-stop at filesystem
# root if none found. No env/hub/CWD fallback.
d="$(cd "$(dirname "<absolute path of the loaded agent or reference file>")" && pwd)"
SKILL_ROOT=""
while true; do
if [ -d "$d/lib" ] && { [ -f "$d/SKILL.md" ] || [ -d "$d/agents" ]; }; then
SKILL_ROOT="$d"
break
fi
[ "$d" = "/" ] && break
d="$(dirname "$d")"
done
# non-empty $SKILL_ROOT required — else hard-stop (see below)
```

**Examples** (all resolve to the skill install root):

| Loaded file | Walk starts at | Resolves to |
|-------------|----------------|-------------|
| `{skill}/agents/run.md` | `…/agents` | `{skill}` (parent has `lib/` + markers) |
| `{skill}/agents/tracker/linear.md` | `…/agents/tracker` | `{skill}` (walk past `tracker` → `agents` → skill root; one-level `..` would wrongly stop at `agents/`) |
| `{skill}/references/run-loop.md` | `…/references` | `{skill}` |
| `{skill}/SKILL.md` | `{skill}` itself | `{skill}` (start directory already matches markers) |

- Prefer the absolute path of the instruction file the agent is currently executing when walk-up is needed (e.g. `agents/run.md`, `agents/config.md`, `agents/run-worker.md`, `agents/tracker/linear.md`, a loaded `references/*.md`, or `SKILL.md`).
- Use the walk-up result as `$SKILL_ROOT` only when it satisfies the markers.
- When this project **is** the do-work skill itself, `$SKILL_ROOT` equals the project root and lib calls work directly. When the project is any other consumer repo, `$SKILL_ROOT` points at the skill clone where `lib/` actually lives — not at the consumer project root.
- Orchestrators that dispatch workers pass the same absolute `$SKILL_ROOT` as the worker **Skill root** input and substitute it into pasted `run-worker.md` instructions (see `agents/run-worker.md` When Invoked #5 and `references/run-loop.md` Step 2 dispatch). Workers and nested agents **inherit** that value when it still satisfies markers.

**Hard-stop when the path cannot be determined.** If any of the following is true, **stop immediately** with a clear operator message — do not guess:

- Inherit failed (missing/invalid `$SKILL_ROOT`) **and** the harness did not provide an absolute path for the loaded instruction file
- Walk-up from the loaded file reaches the filesystem root without finding a directory that satisfies the markers (`lib/` **and** (`SKILL.md` **or** `agents/`))
- The path is empty or otherwise unknown after the recipe

Operator message (example):

`skill-root unknown: cannot resolve $SKILL_ROOT (walk-up from loaded file; no env/hub/CWD fallback). Provide an absolute path to the loaded instruction file under the skill install root, or a valid pre-resolved $SKILL_ROOT that contains lib/ and (SKILL.md or agents/).`

**Do not** fall back to process CWD, hub paths (`~/.agents/skills/do-work`, `~/.claude/skills/do-work`), or invent a path from `DO_WORK_SKILL_ROOT` / other env vars when inherit markers fail. **Do** inherit a **valid** `$SKILL_ROOT` already set in this turn's context (see inherit rule above).

**Phase-agent contract:** every phase agent that touches work items follows the **Tracker load path** (config → resolve `tracker.backend` → `port.md` → `agents/tracker/<backend>.md` → only named port ops). The shared load path is defined once here and in `agents/tracker/port.md`; each phase agent restates a short copy so a missing wire cannot cause split-brain storage. Every phase agent that invokes skill `lib/` scripts also depends on step 8 (`$SKILL_ROOT` / `{skill-root}`) from this same Load Config block.

**Never fail or stop because of a missing or incomplete config file** (steps 1–5). If config creation or migration fails for any reason, proceed with in-memory defaults (including `tracker.backend: markdown`). **Exceptions (deliberate hard-stops, not config-file completeness problems):** step 7 Linear validation (and missing `linear.md`) when the operator has opted into `backend: linear`; step 8 skill-root resolve when walk-up (or inherit) cannot determine an absolute skill install root.

---

Expand Down
2 changes: 1 addition & 1 deletion agents/go.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -37,7 +37,7 @@ Work-item storage (URs, REQs, decisions, verify/close reports, run notes) goes *
**Hard rules:**
- **No silent fallback** from `linear` to `markdown`. If backend is `linear`, do not substitute UR/REQ markdown as the store.
- If backend resolves to **`linear`** but `agents/tracker/linear.md` is **missing or unreadable**, **hard-stop** with setup instructions (restore the Linear backend doc / connect Linear skill). Never fall through to markdown paths.
- Markdown backend: ops map to existing `lib/*.sh` + file flows in `markdown.md` — use those ops; do not re-implement store details here.
- Markdown backend: ops map — **invoke** coordination scripts as `bash {skill-root}/lib/...` after Load Config step 8 resolves `$SKILL_ROOT`; **catalog identity** remains `lib/*.sh` in `markdown.md` — use those ops; do not re-implement store details here.

### 0b. Validate UR exists

Expand Down
2 changes: 1 addition & 1 deletion agents/help.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,7 +28,7 @@ Work-item storage (URs, REQs, decisions, verify/close reports, run notes) goes *
**Hard rules:**
- **No silent fallback** from `linear` to `markdown`. If backend is `linear`, do not substitute UR/REQ markdown as the store.
- If backend resolves to **`linear`** but `agents/tracker/linear.md` is **missing or unreadable**, **hard-stop** with setup instructions (restore the Linear backend doc / connect Linear skill). Never fall through to markdown paths.
- Markdown backend: ops map to existing `lib/*.sh` + file flows in `markdown.md` — use those ops; do not re-implement store details here.
- Markdown backend: ops map — **invoke** coordination scripts as `bash {skill-root}/lib/...` after Load Config step 8 resolves `$SKILL_ROOT`; **catalog identity** remains `lib/*.sh` in `markdown.md` — use those ops; do not re-implement store details here.

### 1. Detect project state

Expand Down
Loading
Loading