| name | orc-learn |
| description | Per-feature onboarding docs for the LOCAL project. Use for "/orc-learn", "help me learn feature X", "onboard me to this feature", or "orc-learn refresh". Runs INDEPENDENTLY — no orchestrator, no run folder. Picks one feature (wiki topics first), then generates learning-docs/<feature>/ with learning.md (pedagogy: mental model, walkthrough, recipes, FAQ) and knowledge.md (reference: file:line-anchored functions & flow, contracts, fingerprints). Output is LOCAL and git-ignored — each dev regenerates their own. Refresh lists every generated feature with a computed freshness flag and regenerates only what the user picks. The skill dispatches the pinned orc-learn-writer-opus-5-low agent — it never writes the docs itself.
|
ORC-LEARN (standalone)
Teach a developer ONE feature of the local repo well enough to safely extend
it — the human-onboarding lane. It is NOT the wiki: the wiki grounds the
pipeline (repo-wide, contract-level); orc-learn goes one level deeper for a
person — function-level, full-flow, pedagogical. Target is always
<repo root>/learning-docs/<feature-slug>/ (git-ignored, local per dev).
Dispatch, don't do. Whatever model this chat runs on, the skill only picks
the topic/mode and spawns orc-learn-writer-opus-5-low (the pinned
engine) — the deepening scan + all writes run at Opus 5 low regardless of
the caller's tier. The skill's only self-writes are the behavior-trace
markers around the spawn. Interactivity is DELIBERATELY minimal but non-zero
(unlike orc-claude): exactly one question per mode — "which feature?" (INIT)
or "which to refresh?" (REFRESH). Never more.
Grounding precedence (constellation rule, unchanged):
code > fresh wiki > stale wiki (hints) > model priors. The writer re-verifies
every wiki claim it uses against the code; on conflict the code wins.
Worked example (orient only — never execute from it):
examples/learn-run-mock.md.
The two modes (auto-selected by argument)
- INIT (default:
/orc-learn, optional focus=<hint>) — pick ONE
feature, generate learning-docs/<slug>/learning.md + knowledge.md,
derive learning-docs/INDEX.md.
- REFRESH (
/orc-learn refresh) — list every generated feature with a
computed freshness flag; regenerate only the ones the user picks.
Protocol: references/refresh.md.
Not inside a git repo / no project root findable → say so and stop.
Phases
orc lane phases orc-learn --json is this lane's pipeline: the ordered list, where
each phase lives, and how much of it to read. The CLI owns the order — never
derive it from the headings below, and never renumber or rename one without the
manifest, because a read: section pointer names a HEADING and a renamed heading
is a pointer into nothing.
Mode A — INIT
Behavior-trace logging is permanent (always on). Resolve log_dir
(../orc/config.md default + .claude/orc.config.yaml) at start and follow
../_shared/phases/trace.md; the marker set is in "Behavior trace"
below. Weave the Trace: steps in as each event happens.
- Topic pick (wiki-first). Read
wiki/INDEX.md +
.claude/orc/wiki-meta.json and compute the freshness tier
(../orc-wiki/references/staleness.md — computed on read, never stored).
Trace: WIKI-CONSULT tier=<FRESH|AGING|STALE|none> :: topic-pick
(emitted even when the wiki is absent, with none).
- Wiki FRESH/AGING → present its feature areas as a pick-list; the chosen
area's
covers globs seed the writer's file set.
- No wiki / STALE / topic not covered → ask the user to point at the
feature (a directory or a
focus= hint); the writer will do a
targeted scan of just those files — never repo-wide. A stale wiki
doc may still ride along as hints (precedence above).
- Ask which feature as ONE question (one feature per invoke). Derive
feature_slug (kebab-case) from the chosen topic/area.
- Trace: write
log_dir/.current = run-learn-<slug>-<DDMMYY>-<HHMMSS>.txt and
touch the trace file of that name in the SAME step, BEFORE the spawn (a
pointer to a missing file reads as dangling and the hook rotates away).
- Spawn
orc-learn-writer-opus-5-low with: mode=init, repo_root,
feature_slug, topic_area, covers[] (from wiki or user pointer),
wiki_tier, focus_hint|null, and the paths to
references/deepen.md, references/template-learning.md,
references/template-knowledge.md. Trace:
DISPATCH orc-learn-writer :: init <slug> expect=opus-5/low just
before the spawn (the hook adds SPAWN/RETURN on its own).
- On return, check
actual_model/actual_effort against the pinned tier —
mismatch → prepend a tier-downgrade warning to the report. Trace:
VERIFY writer actual=<model>/<effort> ✅ MATCH (or
⛔ DOWNGRADE expected=opus-5/low).
- Relay the writer's report verbatim. If
learning-docs/ is not in
.gitignore, offer the line (learning-docs/) — append only on an
explicit yes; never edit silently. ,
then delete . Stop. The skill NEVER writes the docs
itself — not even a "trivial" INDEX touch.
Mode B — REFRESH
- No
learning-docs/ (or no feature folders inside) → "nothing generated
yet; run /orc-learn first." Stop — no trace run needed.
- Read every
learning-docs/<feature>/knowledge.md fingerprint header
(source_commit + per-file hashes) and compute FRESH/AGING/STALE per
feature — references/refresh.md. Freshness is computed on read, never
stored as a status.
- Present the FULL list, each with its computed flag; the user
multi-selects which to regenerate (one question, multi-select). Nothing
selected → stop, no writes.
- Trace: write
log_dir/.current = run-learn-<slug>-<DDMMYY>-<HHMMSS>.txt. For each
selected feature, spawn the writer with mode=refresh and that feature's
slice (re-deepen just that feature; a FRESH/AGING wiki may again seed the
boundary — emit one WIKI-CONSULT tier=<tier> :: refresh when the wiki is
read). One DISPATCH/VERIFY pair per feature, same markers as INIT.
- The (last) writer re-derives
learning-docs/INDEX.md from all current
feature headers. Relay the combined report. Trace:
FINISH :: refresh <n> features, then delete log_dir/.current.
Behavior trace (always on)
../_shared/phases/trace.md (core, at run start; orc lane phases names
the file and the layers). Lane token learn, tier Single-dispatch —
exactly ONE end-of-run packet, dispatched solo after the writer return
validates and BEFORE .current is deleted.
At run start write log_dir/.current = run-learn-<slug>-<DDMMYY>-<HHMMSS>.txt AND
touch the trace file of that name in the SAME step.
Nothing else about the protocol is restated here; a phase that ends with
zero new trace lines is a protocol violation.
Dispatch-only lane: emit ONLY the markers it can truthfully witness — no
PHASE/SCORE/FINDING/VERDICT, because deepening and writing happen
inside the writer, which self-traces nothing and returns only
actual_model/actual_effort. The marker set, in order (actor orc, plus the
hook's SPAWN/RETURN): WIKI-CONSULT tier=<tier> :: <topic-pick|refresh> at
every wiki read · DISPATCH orc-learn-writer :: <mode> <slug> expect=opus-5/low
per spawn (REFRESH runs one per selected feature) · VERIFY writer actual=<model>/<effort> · FINISH :: <init <slug>|refresh <n> features>.
decisions carries which feature was picked and why, plus the user's answer
verbatim.
Boundaries
- Writes ONLY under
learning-docs/ (via the writer) and, on an explicit
yes, one .gitignore line. Never edits source code, never commits, never
pushes.
- One question per mode, ever. Which feature (INIT); which to refresh
(REFRESH). Everything else is decided or reported, never asked.
learning-docs/ is LOCAL — git-ignored, regenerated per dev, never a
committed shared artifact. A stale copy costs one regeneration, nothing
more.
INDEX.md is DERIVED by the writer from the feature headers in the same
dispatch — never hand-maintained, never edited by the skill.
- The wiki is consumed read-only as a boundary source; orc-learn never
writes wiki files, never triggers a wiki scan, never treats "not in the
wiki" as a blocker (it falls back to a targeted scan of user-pointed
files).
- Reminder: to see usage limits, tell the user to run
/usage (never invoke
it programmatically).
Config
Resolve with orc lane config orc-learn --json and obey effective. Never merge
.claude/orc.config.yaml yourself, and never re-derive a precedence. Exit ≠ 0 →
say so and use ../_shared/config-precedence.md's documented defaults, out
loud. Nothing this lane reads is contested, gated or a stop, so it owes no
preflight line and has no gate to honour.
Calls
ONE catalogue, and it is not you: orc lane calls orc-learn --json names every
CLI call this lane makes, each with its exit-code contract, its cost, when to run
it, and what an EMPTY answer means. Never invent a spelling, never re-word an
exit code, and never re-derive a state word — the CLI's state words are the only
state words, and an exit code is an ANSWER wherever that contract says so, not
a failure. A call the answer does not name is a call this lane does not make.
Exit ≠ 0 from the catalogue itself → say the CLI is unavailable and name the
command you are about to run, out loud, before running it.
Waiting mid-run (/orc-wait)
Canonical: ../_shared/wait.md. a lane that waits without a hand-back has broken this contract.
Checkpoint none · safe point single dispatch. Nothing here to checkpoint, so all three modes behave identically — say so rather than asking. Never begin a wait between a dispatch and its validated return, or before the smoke gate has reported.