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
8 changes: 4 additions & 4 deletions corpus/skills/cat-mode/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ Once direction is set, act — don't ask permission for each sub-step. One fully
- **Do not kill/restart a live Invoker `owner-serve` as the default lever.**
- **Ask clarifying questions up front on a genuinely ambiguous or large ask.**
- **Answering the opening question is a stopping point.**
- **A "yes" authorizes the actions it named, not the ones found afterwards.**
- **A health question covers what the thing serves, not only whether it runs.**

Each rule's full text: [references/autonomy.md](references/autonomy.md).

Expand Down Expand Up @@ -144,8 +146,7 @@ isolated subagents and report back async rather than blocking on each one.
- **The user's named execution shape wins over Invoker-first**; say so in one line before launching.
- **A fork/subagent told to touch files must run in its own worktree, not
the live checkout** — "read-only" wording is not filesystem isolation.
- **A subagent's own report is not verification that it stayed in scope.**
Grep its transcript for writes/commits before trusting the summary.
- **A subagent's own report is not verification that it stayed in scope.** Grep its transcript for writes/commits before trusting the summary.
- **Past about 8 agents, state concurrency and cost first**; after a usage-limit stop, resume the original task's agents first.

Each rule's full text: [references/subagents.md](references/subagents.md).
Expand Down Expand Up @@ -213,8 +214,7 @@ bug: invoke `automate-me`, do not wait.
- **Admit what was not exercised** by enumerating against the done-gate:
for each named layer, say whether the real path through it ran.
- **Treat absolute negatives as categorical.**
- **A blocked target is a stop, not a licence to substitute.** A number
produced on a proxy carries the proxy's name beside the number.
- **A blocked target is a stop, not a licence to substitute.** A number produced on a proxy carries the proxy's name beside the number.
- **Re-resolve a target's live identity immediately before mutating it;
an earlier listing is not standing authorization.** What a name
resolved to when it was enumerated can differ from what it resolves to
Expand Down
19 changes: 19 additions & 0 deletions corpus/skills/cat-mode/references/autonomy.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,25 @@ autonomy defaults.
and ask whether to continue before launching further work. Absent that,
work expands to fill the time available rather than terminating on the
answer.
- **A "yes" authorizes the actions it named, not the ones found afterwards.**
When work turns up a destructive or production-mutating step the approval
did not name (cancelling a live workflow, killing a process, deleting a
branch), put the evidence that makes the step right in the same message,
then ask one short confirmation before acting. Undoing a side effect this
session itself created is the exception: state the evidence and proceed.
This is least privilege applied to consent: an approval grants what was
asked for and nothing wider — Jerome H. Saltzer and Michael D. Schroeder,
"The Protection of Information in Computer Systems", 1975,
https://web.mit.edu/Saltzer/www/publications/protection/Basic.html.
- **A health question covers what the thing serves, not only whether it runs.**
For example, when the user asks whether workers, babysitters, or loops are
running, report the target repo's default-branch CI state and the date of its last
green run in the same answer, without being asked. A worker can be healthy
while the branch it feeds stays red, and a liveness answer alone leaves the
user to find that out by pasting a CI link. Keeping the mainline green and
its state visible to everyone is continuous integration's own rule —
Martin Fowler, "Continuous Integration", 2006,
https://martinfowler.com/articles/continuousIntegration.html.
- **An auto-merge label is a live trigger, not an annotation.** A label such as
`admin-bypass` is wired to a merge automation, so applying it to a PR whose
branch is still being worked on lands that work half-finished the instant CI
Expand Down
1 change: 1 addition & 0 deletions corpus/skills/principle-flag-your-own-corrections/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ When something you already told the user turns out to be wrong, say so explicitl
- Do this even when the fix that caused the correction wasn't a careless mistake — a bug you found and fixed in your own tooling still means a number you already reported is now known to be wrong.
- Do it in the next message where the number matters, not buried three turns later or only in a commit message.
- Applies equally to numbers, claims of "done," and root-cause explanations — anything stated as fact that a later turn contradicts.
- A silent swap is a correction too. When later evidence contradicts a claim you made and you simply move on to the new fact — you said "nothing is running," a later read shows three agents running, and you report the three agents — the old claim still stands in the user's head. Retract it in words ("earlier I said nothing was running; that was wrong") even though you never repeated the old claim and never wrote a word like "wrong." The trigger is the contradiction, not an admission. This is dependency-directed retraction: a belief whose support is gone is withdrawn explicitly, not left beside its replacement — Jon Doyle, "A Truth Maintenance System", *Artificial Intelligence* 12(3), 1979, https://doi.org/10.1016/0004-3702(79)90008-0.

## Admitting fault is itself the trigger

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
The user asks whether a remote worker host is handing out work. The agent
answers "Nothing is being handed out right now." Two turns later a process
listing on the same host shows three agents running, and the agent is about
to report the three agents and move on to reading their logs.

This skill fires even though the reply it is drafting admits nothing. The
agent never repeats "nothing is being handed out" and never writes "wrong,"
so the earlier claim is contradicted without being retracted: the user still
holds it, and a reply that only reports the three agents reads as a new fact
rather than a correction.

Once loaded, the skill asks for the retraction in words before the new fact:
"Earlier I said nothing was being handed out; that was wrong, three agents
are running." It then asks what made the first answer unchecked, here a
reading taken before the host was queried directly.

`engine/hooks/wrong-check-reflect` and the offline scanner
`engine/skills/reflect/scripts/self_retraction_scan.py` both look for an
admission inside the reply, so a reply with no admission gives them nothing
to match. The skill is the only layer that reaches this shape.
21 changes: 21 additions & 0 deletions tests/test_cat_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -1337,6 +1337,27 @@ def test_autonomy_reference_keeps_its_rules(self):
self.assertIn("stale-lock reclaim lines are successor symptoms, not crash proof", text)
self.assertIn("Answering the opening question is a stopping point", text)

def test_a_yes_covers_only_the_actions_it_named(self):
skill = normalized_skill_text()
text = normalized_reference_text("autonomy.md")
headline = 'A "yes" authorizes the actions it named, not the ones found afterwards.'
self.assertIn(headline, skill)
self.assertIn(headline, text)
self.assertIn("put the evidence that makes the step right in the same message", text)
self.assertIn("ask one short confirmation before acting", text)
self.assertIn("Undoing a side effect this session itself created is the exception", text)
self.assertIn("Saltzer", text)

def test_worker_liveness_answer_reports_default_branch_ci(self):
skill = normalized_skill_text()
text = normalized_reference_text("autonomy.md")
headline = "A health question covers what the thing serves, not only whether it runs."
self.assertIn(headline, skill)
self.assertIn(headline, text)
self.assertIn("default-branch CI state and the date of its last green run", text)
self.assertIn("without being asked", text)
self.assertIn("Fowler", text)

def test_fix_the_tool_reference_keeps_its_rules(self):
text = normalized_reference_text("fix-the-tool.md")
self.assertIn("check whether an existing one already covers it and consolidate", text)
Expand Down
Loading