Agent asset hierarchy โ
Status: draft, 2026-08-22. Open questions at the bottom need operator rulings. Issue: #950
What problem is this solving? โ
Six layers hold agent guidance. Nothing says which layer a new piece belongs in, so the choice is made by whoever is writing at the time, and the same guidance can end up in two layers or none.
The only written argument on record is in .agents/workflows/README.md: a rule that fails by being skipped belongs in a workflow, a rule that needs judgment at every step stays a skill. That test is correct and it covers one boundary out of five.
What are the six layers? โ
Ordered by how hard they are to ignore, strongest first.
| Layer | What it is | How it fails | When it loads |
|---|---|---|---|
| Hook | A script that inspects a tool call and can refuse it | Cannot be ignored. Fails by being absent, wrong, or unwired | Every matching tool call |
| Rule | Always-present guardrail text | Ignored by inattention, mid-session drift, or context pressure | Every session, eagerly |
| Workflow | A script whose steps run in order, every time | Steps cannot be skipped. Fails by never being invoked | On invocation |
| Skill | A procedure the model reads and applies with judgment | Fails by not being recalled, or by being read and walked past | When the model recalls it |
| Context | One person's overlay: voice, people, focus, projects | Fails silently when stale or absent | Every session, eagerly |
| Output style | How the agent talks | Fails silently when generated but not selected | Every session |
The ordering is the point. A hook cannot be talked out of, a rule can be forgotten, a skill can be not-recalled. Strength costs reach and flexibility, which is what the routing test trades against.
Which layer does a new piece of guidance belong in? โ
Walk it top to bottom. The first yes wins.
1. Can a machine decide it, and does a violation cost real money or real trust?
- Then a hook, and also a rule. See the pairing question below.
- Deterministic and expensive is the hook case: an em dash in shipped copy, a PR aimed at main, a branch switch under a parallel session, a secret inlined into a command, a PR marked ready without her word.
2. Does it bind on every piece of work, whatever the task?
- Then a rule.
- Rules are the only layer loaded eagerly for every agent on every tool. That is their whole value and also their cost: every rule added is context spent on every session forever, including the sessions it does not apply to.
3. Is it a fixed sequence, where the failure is skipping a step rather than doing a step badly?
- Then a workflow.
- The proof case is on the record: on 2026-08-21 the agenda-creation skill said to rank every candidate against the north star, and the launch plan was never opened, because prose cannot force a read.
- A step inside a workflow may still be "go think about this". The sequence is guaranteed; the judgment happens inside the steps.
4. Is it a procedure for one kind of task, needing judgment at each step?
- Then a skill.
- Most guidance lands here, which is why the skills layer is the one with 33 entries and no internal structure.
5. Is it true for one person and not the team?
- Then context. Voice, the people she works with, what is in front of her this week.
Nothing routes to the output style directly. It is generated from the voice rule. Treat it as a compile target, not a place to put things.
Why does a rule need a hook, and a hook need a rule? โ
A hook is never the only home for a rule.
Hooks reach Claude Code and nothing else, and they fire at call time, which means an agent can spend a whole session heading somewhere a hook will refuse. The rule is what stops the trip; the hook is what catches the one that got through.
The em dash convention is the worked example, and it is the pattern to copy:
| Layer | Artifact | Catches |
|---|---|---|
| Rule | key-conventions.md | The agent that would otherwise type one, on all four tools |
| Hook | guard-em-dash.sh | The Claude write that slipped past the rule, at write time |
| CI | lint:emdash, ratcheted | Everything else, including humans and Copilot |
Three layers, one convention, each catching what the one before it missed. Rule 17 and rule 16 have the same shape.
A hook with no matching rule is a trap. It refuses an action the agent had no way to know was forbidden, and it refuses it only for Claude.
Which tools actually see each layer? โ
Nowhere else is this written down, and it is the reason the pairing rule exists.
| Layer | Claude | Copilot | Gemini | Cursor |
|---|---|---|---|---|
| Rules | yes | yes | yes | yes |
| Skills | yes | yes | yes | no |
| Workflows | yes | no | no | no |
| Hooks | yes | no | no | no |
| Context | yes | partial, via context:sync-tools | no | partial |
Putting a guardrail in a hook means Copilot and Gemini never see it. That is a fine trade when the hook is a backstop for a rule, and a silent hole when the hook is the only copy.
What are the skill tiers, and why do they matter? โ
Built 2026-08-22. tier: is a required frontmatter field, enforced by the Skill Sync gate. Before it existed, 33 skills presented identically to a model choosing one, and they are not the same kind of thing.
| Tier | What it is | Members |
|---|---|---|
| Orchestrator | Sequences other skills, run once per session or day | autopilot, project-manager, agenda-creation |
| Procedure | Does one task a specific way, invoked for that task | pr-workbench, session-pr, monitor-ci, test-plan, browser-test, cloud-service, env-vars, script-wiring, planning, design-mockups, distill-agent-log, curate-memory, context-onboard, scenario-matrix, decision-log, frustration-signal, project-creation |
| Discipline | How to work, applies inside whatever else you are doing | tdd, verified-done, code-review-rigor, code-comments, debug, self-improve, safe-automation, authorization, multi-agent, worktree |
| Reference | Lookup, no procedure to follow | repo-map, design, privacy-architecture, verify |
Why it matters:
- A discipline should be recalled during other work.
- A reference only when a fact is needed.
- An orchestrator at most once a session.
- Before the field existed, all three arrived with the same weight, so a model choosing between
repo-mapandautopilothad nothing to go on but the description text.
Disciplines are the tier most likely to be walked past, since nothing triggers them. That makes them the strongest candidates for promotion to rules or hooks, which is the routing test running in reverse.
What rule governs the command field? โ
None yet, and that is the finding.
- 20 skills set
command: true. - 4 set
command: false. - 9 omit it.
sync-skills.jsreads it asif (meta.command), so omitted behaves exactly like false. The nine are not a different choice; they are an unrecorded one.
Proposed rule:
command: truewhen a person would plausibly type it (/agenda-creation,/test-plan,/monitor-ci).command: falsewhen the model should recall it but no human would ever invoke it (code-comments,debug,privacy-architecture).- Make the field required, so the sync check fails on omission and the choice is always deliberate.
How do I test and refine an agent asset? โ
The loop already exists. Nothing names it, so no one runs it deliberately.
| Stage | Question | Tool |
|---|---|---|
| Observe | How often did she have to correct an agent, and why? | frustration-signal skill |
| Capture | Turn one correction into a durable change | self-improve skill |
| Route | Which layer does it belong in? | The routing test above |
| Graduate | Move it from memory to its permanent home | curate-memory skill |
| Verify behavior | Did the change make the agent pick better? | test-rank.js workflow |
| Verify coverage | Will this prompt actually answer the ask? | preflight-prompt-check.js workflow |
| Gate | Did the generated copies drift from source? | Skill Sync, Agents Sync in validate |
Two observations about the shape:
- The gates only check that copies match their source. Nothing checks whether the source is any good.
test-rank.jsis the only asset that tests behavior rather than bytes, and it covers exactly one step of one workflow. That is the real gap in "testing", and it is not cheap to close, because the only honest test of a skill is whether an agent given a realistic task actually reaches for it. - Verify-behavior is the stage that gets skipped, for the same reason every unenforced step gets skipped: it costs a run, and the change looks obviously correct. Naming it in the loop is the cheap half.
Why does the context layer fail differently? โ
Every other layer is committed, so drift shows up as a diff. Context is per-user and per-machine, so it drifts silently and no gate can see it. Two live examples, both found while writing this doc on 2026-08-22.
This laptop's context home was 102 commits behind.
- The dev VM had been syncing since 08-11;
mwrazerbladehad not pulled once. npm run context:syncis in no SessionStart hook, so the machine that runs it pushes and the machine that does not simply falls behind.- Everything downstream was the 08-11 version: voice, people, projects, and no
active/focus.mdat all, which was then the first file the agenda-creation skill opened. - An agent on this machine would have planned a day against a focus that did not exist and had no way to notice. That is #834.
Memory does not sync at all.
- The context home's
memoriesentry is a symlink to~/.claude/projects/<repo>/memory, a machine-local path. - This laptop holds 51 notes; the 2026-08-19 graduation ledger counted 60 on the VM.
- They are separate directories that keep diverging. Filed as #654.
That divergence is the argument for graduation, not a bug to patch. #927 moved the durable half of the corpus into committed skills (authorization, repo-map, safe-automation, frustration-signal, plus additions to verified-done, tdd, debug, multi-agent), where it reaches every tool on every machine.
Read against the routing test, memory is not a seventh layer. It is a staging area: the place a learning lands before anyone knows which layer it belongs in. self-improve writes into it, curate-memory empties it. Anything still sitting there after a graduation sweep is either genuinely personal, or overdue.
Why were workflows pinned to one machine? โ
All three scripts defaulted ROOT to /home/cattreedev/lantern_app, and two also defaulted a context path under that home. On this laptop, /home/mechelle/repos/lantern_app, every one of them read a tree that is not there.
A workflow script has no filesystem or Node API access by design, so it cannot resolve the path itself. The caller has to pass repoRoot through args. The old fallback hid that: on the wrong machine the script did not refuse, it just read nothing and reported on nothing.
Resolved 2026-08-22: repoRoot is required on all three, and contextHome on the two that read the per-user context home.
What has the operator ruled on this design? โ
Six rulings, 2026-08-22, during the PM skill refactor. Execution detail is in implementation.md.
| Ruling | What it means |
|---|---|
The new-day branch delegates to agenda-creation rather than absorbing it | Kills the duplication between two orchestrators that both claimed the split |
| The agenda has no top-level Need-from-you table | An ask lives on the task block it belongs to. A single collected table becomes a wish list, and the loudest row wins over the current one |
active/focus.md is retired; the focus is a line in the agenda header | "That is what the agenda is for." One less file to sync, one less thing that can disagree with the board |
| The status sweep runs on her ask, plus once before the EOD report | No timer, no unprompted pushes. Sessions that need to tell her something tell her themselves |
| Sessions may be polled on a status she asked for, not on the pre-EOD run | Resolved an apparent conflict between the 2026-08-08 "ask first, dig second" rule and the 2026-08-21 "do not poll any session" instruction. Both hold, on different runs |
| The morning survey restructures to backlog-first | The launch plan and the tracker become filters, not candidate sources |
One of those turned out to be blocked by a transport fact, not a policy one. A workflow subagent can send a message but cannot receive a reply, so the polling had to move to the caller. The ruling survived; only its implementation site changed. See implementation.md.
What is broken right now? โ
Both filed as #951, both fixed on 2026-08-22 per rule 18.
sync-workflows.jshad no--check, and validate had no Workflow Sync entry. Edit a workflow, forget to sync, and the stale.claude/workflows/copy runs. Silently. Skills and rules each have this gate..agents/workflows/README.mdsaid the layer was not wired. It is. The wiring shipped in the same PR, so the source of truth told readers to paste scripts in by hand.
What is still open? โ
- RESOLVED, 2026-08-22: frontmatter.
tier:is required on every skill and validated bylint.sync-skills.js, which rejects a missing tier and a tier outside the four. All 34 skills carry one (3 orchestrator, 17 procedure, 10 discipline, 4 reference). Proven to fail by mutation, both on a removed tier and a misspelled one. Schema in.agents/meta/frontmatter.md. - Should hooks move under
.agents/hooks/? They are the only layer outside the source of truth. Moving them makes the pairing rule checkable: a hook with no matching rule could fail the sync. Cost is a real move plus settings rewiring. - Does verify-behavior become a workflow? A skill saying "test your skill change" is a discipline, and disciplines get walked past. A workflow forces it, at the cost of a run per asset change.
- Is 33 skills too many? Not asked here, but the tiering will make the answer visible. Four references and ten disciplines suggest some of both belong in rules.
- RESOLVED, 2026-08-22: it refuses.
repoRootis required on all three workflows, andcontextHomeon the two that read the per-user context home. Each throws a message naming what to pass. Proven both directions: no args exits 1 with the message, correct args resolves this machine's path. - Should
context:syncrun at session start? It would have caught the 102-commit gap on its own. The cost is a network call on every session boot and a write path in a hook, whichsafe-automationwarns about specifically: N sessions boot at once when the fleet starts. A pull-only variant may be the safe half. - Does the PM sequence become a workflow? Now with evidence on both sides.
agenda-status.jsproves the sequence can be forced and that forcing it surfaces real defects. It also proves a workflow cannot do everything a skill can, since it cannot receive a peer's reply.