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
7 changes: 7 additions & 0 deletions .claude/skills/frame-standup/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,13 @@ whose entrance criteria now look satisfied (offer to flip `status: queued → re
THIS step's human judgment, the one thing the compiler never does), and `delivered` slices
awaiting the merge ritual. These feed Step 5 ranking and Step 7b dispatch.

**A slice whose entrance you cannot assert either way has found fog** — the blocker is an open
question, not a missing deliverable. Route it to `/wayfinder` to chart rather than leaving it
`queued` indefinitely, which is how a slice quietly becomes permanent backlog. Surface it in the
day plan as "chart it", not as a dispatchable action; charting is a session of its own and closes
zero slices. (Boundary: *what/whether* → `/wayfinder`; *how to ship safely in stages* →
`/gated-slice`.)

### Step 5 — Generate the day plan

Cross-reference: daily-logger suggested actions + open action backlog +
Expand Down
7 changes: 5 additions & 2 deletions .claude/skills/skill-loader/knowledge/skill-catalog.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"version": "1.20",
"updated": "2026-07-29",
"version": "1.21",
"updated": "2026-07-31",
"skills": [
{
"name": "opm",
Expand Down Expand Up @@ -689,6 +689,9 @@
],
"layer_affinity": [
0
],
"scope": [
"user"
]
},
{
Expand Down
14 changes: 10 additions & 4 deletions .claude/skills/wayfinder/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,26 @@ You are a wayfinder charting work that is too big for one agent session and wrap
## Core principles

1. **Plan, don't do.** A wayfinder session either charts the map or works exactly one ticket. Resolving tickets during charting is the signature failure.
2. **The map is file-canonical; issues are the projection.** The map lives at `decisions/wayfinder/<slug>.md`; tickets are GitHub child issues with native blocking edges so the frontier renders in the tracker. Fix the map by editing the file (same posture as roadmap files vs compiled beads).
2. **The map is file-canonical; issues are the projection.** In full mode the map lives at `<core_root>/decisions/wayfinder/<slug>.md` — one library, so any surface can enumerate every open frontier in a single read; tickets are GitHub child issues with native blocking edges so the frontier renders in the tracker. Fix the map by editing the file (same posture as roadmap files vs compiled beads). In lite mode it lives at `<cwd>/decisions/wayfinder/<slug>.md` with no tracker projection (`knowledge/fleet-substrate.md`).
3. **Placement litmus** (`adr:wayfinder-decision-maps`): can you state `success` + a machine-runnable `check`? → it's a roadmap slice, not a ticket here. Can you state only the question precisely? → wayfinder ticket. Can't state the question yet? → `## Not yet specified` fog. Fog graduates to a ticket when the question — not the answer — becomes statable.
4. **Facts are gathered; decisions are the user's.** Charting may explore the repo freely, but every ticket's decision belongs to the user (grilling tickets are HITL by definition — an agent answering its own ticket has broken the loop).
5. **Refer by name.** Tickets are referenced by title in prose, never bare issue numbers.

## Modes

This skill is installed at user scope, so it can fire anywhere on this machine. **Before anything else, decide the charting mode** — `scripts/resolve-anchor.mjs --detect` returns `full` (fleet substrate resolves) or `lite` (it doesn't). Announce it in one line; a lite map must never be mistaken for an anchored one. The full mode table is in `knowledge/fleet-substrate.md`.

### Chart (default — new map)

1. **Grill the Destination first** (via `/grill-with-docs`, charting variant — breadth-first): what does "arrived" look like? Name it before anything else; if the map is anchored to a northstar, cite the properties (`ns:<slug>#P<n>`, resolve-or-fail). The Destination fixes scope.
1. **Grill the Destination first** (via `/grill-with-docs`, charting variant — breadth-first): what does "arrived" look like? Name it before anything else; if the map is anchored to a northstar, cite the properties (`ns:<slug>#P<n>`, resolve-or-fail — run `scripts/resolve-anchor.mjs --anchor=ns:<slug>#P<n>` and don't write the anchor if it exits non-zero). The Destination fixes scope.
1b. **Read the reference layer** (full mode only): consult `~/selfco/wiki/` — `synthesis/`, `concepts/`, `entities/` — for prior lenses bearing on the Destination, and cite what you use under `## Notes`. Design-time, read-only, one-way: a vault page informs a ticket body, it never *is* a decision (`adr:bonded-pair-division-of-labor`, draft).
2. **No-fog early exit:** if the journey fits one session, skip the map — say so and route to `/plan-feature` directly.
3. Breadth-first over the fog: enumerate the open questions, apply the placement litmus to each, and type every ticket:
- `research` (AFK) — resolved via the **deep-research harness, ONE cycle at a time** (sequential-research rule; a charting session that fans research out in parallel is a bug, not a speedup); findings filed to `decisions/research/`, never throwaway branches.
- `grilling` (HITL, the default) — resolved via `/grill-with-docs`; its in-loop ADR stubs give `## Decisions so far` real `decisions/adr/` entries to index.
- `prototype` (HITL) — resolved via `/prototype`; artifact linked from the ticket (disposition per `/prototype`, incl. the kept-branch primary-source option).
- `task` (either) — manual unblocking work: provisioning, access, data moves.
4. Write the map file (`knowledge/map-format.md`), then create the child issues labelled `wayfinder:<type>` in dependency order, wiring blocking edges with the tracker's native blocked-by relationship the **frontier** (open + unblocked + unclaimed) must render in the tracker. Sized so each ticket fits one session.
4. Write the map file (`knowledge/map-format.md`) at the mode's path, then — **full mode only** — create the child issues labelled `wayfinder:<type>` in dependency order, wiring blocking edges with the tracker's native blocked-by relationship, so the **frontier** (open + unblocked + unclaimed) renders in the tracker. In lite mode the Tickets table *is* the frontier. Sized so each ticket fits one session.
5. **Stop.** Zero tickets resolved in the charting session.

### Work (one ticket per session)
Expand Down Expand Up @@ -64,7 +67,8 @@ The charted decisions are exactly what make `entrance`/`success`/`check` statabl
- **Parallel research is the tempting bug.** Upstream's chart-time fan-out is rewritten to sequential here (2026-06-05 API-saturation failure; the verify stage collapses under concurrency). Slower charting is the accepted price — the SKILL says so, so don't "optimize" it back.
- **Don't put deliveries on the map.** If a ticket's closure would be a merged PR, it's a roadmap slice that skipped the litmus — move it out. Mixing deliveries into the map (or questions into the roadmap) breaks both ledgers' closure semantics.
- **The map body in the tracker is a projection.** Editing the GitHub issue body and not the file forks canon; the file wins, same as roadmaps vs beads.
- **A standup that can't assert a slice's entrance found fog.** The move is "chart it" — not leaving the slice queued forever (`/frame-standup` cross-ref).
- **A standup that can't assert a slice's entrance found fog.** The move is "chart it" — not leaving the slice queued forever (`/frame-standup` Step 4.6 routes here).
- **Lite mode is a degradation, not a dialect.** Say so out loud when it engages. The failure is a map that silently drops its `northstar:` anchor because the substrate wasn't found, then reads later as deliberately unanchored. A *claimed* anchor that won't resolve is an error — never write it and carry on.

---

Expand All @@ -73,5 +77,7 @@ $ARGUMENTS
## See Also

- `knowledge/map-format.md` — the map file schema + ticket issue template
- `knowledge/fleet-substrate.md` — full/lite modes, substrate read order, sharp edges (slug identity, vantage misses)
- `scripts/resolve-anchor.mjs` — `--detect` (mode) and `--anchor=ns:<slug>#P<n>` (resolve-or-fail)
- `decisions/adr/0101-wayfinder-decision-maps.md` — the governing decision (adapted from mattpocock/skills v1.1, verdicts D11–D13)
- `/grill-with-docs` (grilling tickets, charting variant) · `/prototype` (prototype tickets) · `/gated-slice` (post-decision staging) · `/plan-feature --from-conversation` + `/orchestrate --emit=github-issues` (handoff)
90 changes: 90 additions & 0 deletions .claude/skills/wayfinder/knowledge/fleet-substrate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Wayfinder — fleet substrate and charting modes

`/wayfinder` is installed at user scope (`scope: ["user"]` in `skill-catalog.json`), so it can
fire in any repo on this machine — including repos with no northstars, no `core/decisions/`, and
no fleet tracker. It therefore charts in one of **two modes**, decided by substrate
resolvability rather than by path.

## Deciding the mode

```bash
node "<skill>/scripts/resolve-anchor.mjs" --detect # human
node "<skill>/scripts/resolve-anchor.mjs" --detect --json # { mode, core_root, reason, registry_entries }
```

The script walks ancestors of the cwd looking for `decisions/northstar/README.md`, and for
`core/decisions/northstar/README.md` (the sibling-repo vantage — cwd is `~/ojfbot/<app>`, core is
`~/ojfbot/core`). **Full** mode requires that registry to parse with at least one entry.
Everything else is **lite**.

Detection is deliberately *not* a `~/ojfbot` path prefix: a core checkout moved elsewhere still
charts in full mode, and a scratch directory that happens to be named `ojfbot` does not.

Announce the mode in one line at the start of a charting session. A lite map must never be
mistaken for an anchored one.

## What changes between modes

| | **full** (substrate resolves) | **lite** (it doesn't) |
|---|---|---|
| Map path | `<core_root>/decisions/wayfinder/<slug>.md` | `<cwd>/decisions/wayfinder/<slug>.md` |
| `northstar:` anchor | resolve-or-fail via the script | omitted — a claimed anchor is an **error**, never a silent skip |
| Ticket projection | GitHub child issues, `wayfinder:<type>`, native blocked-by edges | table rows in the map only; `tracker_issue:` omitted |
| selfco reference read | yes (design-time, read-only) | skipped |
| Handoff | `/plan-feature --from-conversation` → `/orchestrate --emit=github-issues`, slices appended to the northstar's roadmap | `/plan-feature` only; no roadmap append |

Full-mode maps all land in one library under core, which is what lets any surface enumerate every
open frontier in a single read. Lite-mode maps stay local to the repo that produced them.

## Resolving an anchor

```bash
node "<skill>/scripts/resolve-anchor.mjs" --anchor=ns:l2-ojfbot#P1
```

Exit 0 with the resolved property, or exit 1 with the reason. This is the mechanism behind
"resolve-or-fail" — run it before writing a `northstar:` line, and do not write the anchor if it
fails.

## Sharp edges

- **Slugs are immutable identity** (ADR-0087) and are matched verbatim. `buddy-check` is
registered *without* the `l1-` prefix; `l1-virtuallight` is lowercase while its directory is
`virtualLight`. Never case-fold or prefix-normalize either — the script won't, and neither
should prose in a map.
- **Registered-but-absent is usually a vantage artifact,** not a registry lie: a sibling checkout
missing from this working copy. `northstar-lint.mjs` downgrades these to WARNs and `--detect`
keeps full mode; only anchors pointing into an absent file fail, and they fail individually
with `unreachable: true`.
- **Registry paths are core-root-relative** (`../<app>/.claude/northstar.md`). Resolution belongs
to `northstar-fm.mjs`; don't hand-join paths.
- **The registry is markdown frontmatter, not JSON.** Only `northstar-fm.mjs`'s constrained,
`LIST_KEYS`-gated parser is safe on it. Import it; never reimplement or `JSON.parse` it.
- **A known parser gap:** inline YAML comments are not stripped, so `slug: buddy-check # NB: …`
parses with the comment attached. `resolve-anchor.mjs` works around this for slug comparison
only. Tracked as `decisions/defects/dr-northstar-fm-inline-comment-not-stripped.md` — don't
"fix" it with a naive strip, which would truncate live roadmap values containing `PR #165`.

## The selfco read (full mode, charting only)

Per `adr:bonded-pair-division-of-labor` (**draft**), the operational spine carries *work objects*
(beads, registry, slices, instances) and the selfco vault carries *understanding objects* (lenses,
entity pages, syntheses), which the spine reads **at design time only**.

Charting is design time. Before enumerating fog, consult `~/selfco/wiki/` — `synthesis/`,
`concepts/`, and `entities/` — for prior thinking that bears on the Destination, and cite what you
use under the map's `## Notes`. The `operating-surface-bonded-pair` map already does this by hand,
citing the `precedent-survey-methodology` corpus as its design-judgment source.

Strictly read-only and one-way. Wayfinder never writes to the vault, and never treats a vault page
as a decision — vault pages inform ticket bodies; the decision still belongs to the user in that
ticket's session. Skip entirely when `~/selfco` is absent or in lite mode.

## Read order for a charting session

1. `resolve-anchor.mjs --detect` → mode.
2. Full mode only: `decisions/northstar/README.md` frontmatter → `registry:` + `roadmaps:`.
3. `resolve-anchor.mjs --anchor=…` for the Destination's claimed properties.
4. `~/selfco/wiki/` for prior lenses and syntheses on the Destination.
5. Existing maps in the map library — an initiative may already be charted, or its fog may
already be someone else's `## Out of scope`.
8 changes: 6 additions & 2 deletions .claude/skills/wayfinder/knowledge/map-format.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# Wayfinder map format

The map is file-canonical at `core/decisions/wayfinder/<slug>.md`; GitHub child issues are the
projection (`adr:wayfinder-decision-maps`). Slug: kebab-case initiative name, no date.
The map is file-canonical; GitHub child issues are the projection
(`adr:wayfinder-decision-maps`). Slug: kebab-case initiative name, no date.

Where the file lands depends on the charting mode (`knowledge/fleet-substrate.md`):
**full** → `<core_root>/decisions/wayfinder/<slug>.md` (the one map library);
**lite** → `<cwd>/decisions/wayfinder/<slug>.md`, with `northstar:` and `tracker_issue:` omitted.

## Map file

Expand Down
Loading
Loading