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
68 changes: 68 additions & 0 deletions .agents/skills/ticket-queue-discipline/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
name: ticket-queue-discipline
description: >-
Agent-only judgment for tracker-backed ticket work.
Load before claiming, dispatching, closing, or auditing tickets in a project tracker
so readiness, claims, and close reasons stay tied to live canon rather than scratch state.
user-invocable: false
metadata:
internal: true
---

# ticket-queue-discipline

This skill is judgment only.
Mechanizable claim, close, and status mutations belong in code and trackers, not here.
Load before claiming, dispatching, closing, or auditing tracker-backed ticket work.

## One live tracker

Treat one tracker as authoritative.
A per-ship scratch copy is never a source of readiness or claims - it drifts the moment work lands elsewhere.
Query live; never cache tracker state in durable firstmate records.

## Claim at dispatch

Claim atomically at dispatch (`bd update <id> --claim` or the project's equivalent write-to-canon claim).
The value is the forced write to canon at the moment work is chosen, which is the verification step that catches already-delivered tickets before a worker starts.

## Verify at pickup

Check acceptance criteria against code and merge history, not against an impression of the ticket.
"Unclear" is a permitted answer and escalates - guessing acceptance criteria ships the wrong work.

## Close with a satisfied-by reason

Close only with a satisfied-by reason that names the merged PR.
A close without a land pointer makes later audits invent causality.

## Decision classes

- **Decide alone** - defects inside accepted criteria.
Reason: the ticket already authorized that fix surface.
- **Decide-and-report** - converging fix rounds, or fail-closed refusals that still leave the ticket on its intended path.
Reason: the captain needs the trail without owning every mechanical correction.
- **Stop-and-escalate** - the same defect family surviving twice, a new schema/contract/public interface, or a finding where the ticket fails its own criteria either way.
Reason: continuing alone burns cycles or freezes a bad contract.
- **Stop-for-the-captain** - widening or narrowing the product, accepting a residual, production, credentials, or customer data.
Reason: those choices are authority, not implementation detail.

Log real decisions only - never routine mechanics - because the log is sampled and noise hides the few lines that matter.

## Convergence

Falling counts of distinct defects means keep going.
The same family surviving repeatedly means stop and reassess.
Without that distinction, thrash looks like progress.

## Decision becomes a test

Every decision becomes an executable test that would fail if the decision were reversed or dropped.
An untested decision is an oral history and will be lost on the next pass.

## Evidence honesty

A check rollup containing any FAILURE is not "green" without naming what failed and why it no longer counts.
"No checks reported" means UNPROVEN, never green.
Never report an instruction delivered without confirming it landed.
False green is worse than a visible red: it ends supervision of work that is still broken.
1 change: 1 addition & 0 deletions .codex/skills
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,8 @@ jobs:
set -eu
[ "$(readlink CLAUDE.md)" = "AGENTS.md" ] || { echo "::error::CLAUDE.md must be a symlink to AGENTS.md"; exit 1; }
[ "$(readlink .claude/skills)" = "../.agents/skills" ] || { echo "::error::.claude/skills must be a symlink to ../.agents/skills"; exit 1; }
[ "$(readlink .codex/skills)" = "../.agents/skills" ] || { echo "::error::.codex/skills must be a symlink to ../.agents/skills"; exit 1; }
[ "$(readlink .grok/skills)" = "../.agents/skills" ] || { echo "::error::.grok/skills must be a symlink to ../.agents/skills"; exit 1; }
- name: Personal fleet paths must not be tracked
run: |
set -eu
Expand Down
1 change: 1 addition & 0 deletions .grok/skills
5 changes: 4 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ README.md public overview and development notes
.github/workflows/ shared CI and PR enforcement, committed
.tasks.toml tracked tasks-axi markdown backend config for the default backlog backend (section 10)
.agents/skills/ firstmate-loaded internal skills, committed; each carries metadata.internal=true for installers
.claude/skills symlink to .agents/skills for claude compatibility
.claude/skills symlink to .agents/skills for claude project discovery
.codex/skills symlink to .agents/skills for codex project discovery
.grok/skills symlink to .agents/skills for grok project discovery
skills/ standalone public installer-facing skills, committed; not loaded by firstmate
bin/ helper scripts, committed; read each script's header before first use
.env optional X-mode pairing token; LOCAL, gitignored; presence-gates section 14
Expand Down Expand Up @@ -500,6 +502,7 @@ These skills are not captain-invocable; load them only at their precise triggers
- `fmx-respond` - load on an `x-mention <request_id>` `check:` wake to handle the mention, on an `x-mode-error ...` `check:` wake to report the X-mode configuration blocker, on a `public-followup ...` `check:` wake or a startup-surfaced public commitment, and on any milestone or terminal wake for an X-mode-linked task before posting its completion follow-up; relevant only when X mode is on.
- `firstmate-codexapp` - load before coordinating a visible Codex Desktop thread, evaluating a Codex App backend request, or reconciling Codex Desktop host-tool smoke evidence for Firstmate work.
- `firstmate-coding-guidelines` - load before changing firstmate's shared, tracked material, as defined by section 1's list, whether editing directly or briefing a crewmate for a firstmate-repo task.
- `ticket-queue-discipline` - load before claiming, dispatching, closing, or auditing tracker-backed ticket work.

## 14. X mode

Expand Down
4 changes: 3 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ See the [no-mistakes quick start](https://kunchenguid.github.io/no-mistakes/star
## Repo conventions

- This repo is a template for running a firstmate orchestrator agent.
`AGENTS.md` is the agent's main job description and names when to load bundled firstmate skills; `CLAUDE.md` is a symlink to it, and `.claude/skills` is a symlink to `.agents/skills`.
`AGENTS.md` is the agent's main job description and names when to load bundled firstmate skills; `CLAUDE.md` is a symlink to it, and `.claude/skills`, `.codex/skills`, and `.grok/skills` are symlinks to `.agents/skills` so claude, codex, and grok project discovery share one canonical skill tree (see [`docs/verification/harness-skill-discovery.md`](docs/verification/harness-skill-discovery.md)).
- Only shared material is tracked: `AGENTS.md`, `README.md`, `CONTRIBUTING.md`, `.tasks.toml`, `.github/workflows/`, `bin/`, `.agents/skills/`, and `skills/`.
`.agents/skills/` holds agent-loaded skills that assume a live firstmate home and carry `metadata.internal: true` so installers such as [skills.sh](https://skills.sh) hide them from discovery; `skills/` holds standalone, installer-facing public skills with no firstmate dependency (see the README's "Two-tier skill layout").
Everything personal to one captain's fleet (`.env`, `data/`, `state/`, `config/`, `projects/`, `.no-mistakes/`) is gitignored; never commit it.
Expand Down Expand Up @@ -84,6 +84,8 @@ bin/fm-test-isolation-proof.sh --list # proven parallel candidate set (Phase 2
bin/fm-test-isolation-proof.sh --jobs 4 --json /tmp/fm-isolation-proof.json # re-run concurrent isolation proof only
[ "$(readlink CLAUDE.md)" = "AGENTS.md" ]
[ "$(readlink .claude/skills)" = "../.agents/skills" ]
[ "$(readlink .codex/skills)" = "../.agents/skills" ]
[ "$(readlink .grok/skills)" = "../.agents/skills" ]
tmp=$(mktemp -d) && printf 'done: smoke\n' > "$tmp/smoke.status" && FM_STATE_OVERRIDE="$tmp" FM_SIGNAL_GRACE=1 FM_POLL=1 FM_HEARTBEAT=999999 bin/fm-watch-arm.sh # watcher re-arm smoke test (prints arm status, then an actionable signal)
```

Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ Agent-only reference skills live under `.agents/skills/` and are loaded by first

Firstmate's skills live in two separate places with different audiences:

- `.agents/skills/` - agent-loaded skills (this section's table, plus firstmate's agent-only reference skills). Every one of these assumes a live firstmate home and is meaningless, or actively misleading, installed anywhere else, so each carries `metadata.internal: true` in its frontmatter. That flag hides them from installer discovery (tools like the [skills.sh](https://skills.sh) `npx skills add` installer) without affecting how firstmate itself loads them - frontmatter metadata is inert to the agent's own skill loader.
- `.agents/skills/` - agent-loaded skills (this section's table, plus firstmate's agent-only reference skills). Every one of these assumes a live firstmate home and is meaningless, or actively misleading, installed anywhere else, so each carries `metadata.internal: true` in its frontmatter. That flag hides them from installer discovery (tools like the [skills.sh](https://skills.sh) `npx skills add` installer) without affecting how firstmate itself loads them - frontmatter metadata is inert to the agent's own skill loader. Project discovery for claude, codex, and grok is wired through tracked symlinks (`.claude/skills`, `.codex/skills`, `.grok/skills`) that all point at this tree; see [`docs/verification/harness-skill-discovery.md`](docs/verification/harness-skill-discovery.md).
- `skills/` - public, installer-facing skills meant to be installed standalone into any project, independent of firstmate.
Each one is a self-contained skill with no dependency on firstmate's paths, tools, or vocabulary.
Today that is `skills/stow`, a generic session-knowledge-sweep skill that routes findings by explicit instruction first, then existing local conventions, then a private `.stow-notes.md` fallback in the current directory, and closes with a resume pointer for the next session.
Expand All @@ -207,6 +207,7 @@ Firstmate's skills live in two separate places with different audiences:
- [docs/cmux-backend.md](docs/cmux-backend.md) - current setup, socket security, and limits for the experimental cmux backend.
- [docs/codex-app-backend.md](docs/codex-app-backend.md) - the current blocked Codex App backend boundary and rollout contract.
- [docs/verification/runtime-backends.md](docs/verification/runtime-backends.md) - active maintainer verification for runtime backend guarantees.
- [docs/verification/harness-skill-discovery.md](docs/verification/harness-skill-discovery.md) - active maintainer verification for claude, codex, and grok project skill discovery.
- [docs/gitlab-merge-watch.md](docs/gitlab-merge-watch.md) - maintainer verification for GitLab merge watching on arbitrary instances.
- [docs/turnend-guard.md](docs/turnend-guard.md) - the primary session's current "no turn ends blind" backstop, scope, loop safety, and compatibility limits.
- [docs/verification/supervision.md](docs/verification/supervision.md) - active maintainer verification for session-start, guard, continuity, and wedge integrations.
Expand Down
8 changes: 8 additions & 0 deletions docs/documentation-audiences.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@
"path": ".agents/skills/stuck-crewmate-recovery/SKILL.md",
"audience": "agent-runtime"
},
{
"path": ".agents/skills/ticket-queue-discipline/SKILL.md",
"audience": "agent-runtime"
},
{
"path": ".agents/skills/updatefirstmate/SKILL.md",
"audience": "agent-runtime"
Expand Down Expand Up @@ -307,6 +311,10 @@
"path": "docs/verification/dispatch-auth.md",
"audience": "maintainer-verification"
},
{
"path": "docs/verification/harness-skill-discovery.md",
"audience": "maintainer-verification"
},
{
"path": "docs/verification/public-followup.md",
"audience": "maintainer-verification"
Expand Down
143 changes: 143 additions & 0 deletions docs/verification/harness-skill-discovery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# Harness skill discovery verification

Audience: maintainer verification.

This record supports the shared project-skill layout: `.agents/skills/` is the single canonical tree, and harness-native paths are symlinks to it (`.claude/skills`, `.codex/skills`, `.grok/skills`).
It records what each harness actually resolved on the versions below.
Task chronology stays in private reports or PR evidence.

Verified 2026-08-03 in the isolated firstmate worktree at
`/Users/agwerschky/.no-mistakes/worktrees/e661563b090a/01KZ4B0458NGJFN2BJ5QTM3VFN`
at commit `5939a39fbf2e52a6fe8e22a56d42cfdc2c8a65b0`.

## Versions

| Harness | Binary | Version |
| --- | --- | --- |
| claude | `/Users/agwerschky/.local/bin/claude` | 2.1.220 (Claude Code) |
| codex | `/Users/agwerschky/.local/bin/codex` | codex-cli 0.146.0-alpha.9.2 |
| grok | `/Users/agwerschky/.local/bin/grok` | grok 0.2.118 (1e1687c1cf6a) [stable] |

## Repo layout under test

- Canonical tree: real directory `.agents/skills/<name>/SKILL.md` (no copy of skill bodies).
- Claude: existing tracked symlink `.claude/skills -> ../.agents/skills`.
- Codex and Grok: tracked symlinks `.codex/skills -> ../.agents/skills` and `.grok/skills -> ../.agents/skills` (added on this branch; same relative target as Claude).

## What each harness resolved

### Grok

Commands:

```sh
grok inspect --json
# plus disposable probe repos under /tmp with distinct skills in
# .agents/skills, .grok/skills, .claude/skills, and .codex/skills
```

Relevant output for the new skill, after confirming that neither it nor `firstmate-coding-guidelines` existed under `~/.grok/skills`:

```json
{
"skill": {
"name": "ticket-queue-discipline",
"source": {
"type": "project",
"path": "/Users/agwerschky/.no-mistakes/worktrees/e661563b090a/01KZ4B0458NGJFN2BJ5QTM3VFN/.grok/skills/ticket-queue-discipline/SKILL.md"
},
"userInvocable": false
}
}
```

Findings:

- Project discovery works.
- Documented and observed project roots include `.grok/skills/`, `.agents/skills/`, and `.claude/skills/` (Claude compat).
- Grok does **not** treat project `.codex/skills/` as a skill root (probe skill there never appeared).
- With only the canonical `.agents/skills` tree present (before harness symlinks), every firstmate internal skill resolved as `source.type=project` with path under `.../firstmate/.agents/skills/<name>/SKILL.md`.
- After adding `.grok/skills -> ../.agents/skills`, the same skills resolve once (name-deduped) with path under `.../firstmate/.grok/skills/<name>/SKILL.md`.
- `firstmate-coding-guidelines` and `ticket-queue-discipline` were both absent from `~/.grok/skills`, so their observed `source.type=project` results did not come from user-level copies.
- User-level skills still come from `~/.grok/skills/` (and optional Claude user compat paths).

### Codex

Commands:

```sh
codex debug prompt-input "x"
# parse the model-visible ## Skills / ### Skill roots section
```

Relevant model-visible output:

```text
- `r0` = `/Users/agwerschky/.no-mistakes/worktrees/e661563b090a/01KZ4B0458NGJFN2BJ5QTM3VFN/.agents/skills`
- ticket-queue-discipline: Agent-only judgment for tracker-backed ticket work. Load before claiming, dispatching, closing, or auditing tickets in a project tracker so readiness, claims, and close reasons sta (file: r0/ticket-queue-discipline/SKILL.md)
```

Findings:

- Project discovery works for **both** `$REPO/.agents/skills` and `$REPO/.codex/skills` when they are distinct real directories (both appeared as separate skill roots; probe skills under each loaded).
- Official Codex docs also document walking `.agents/skills` from CWD up to the repo root (and user/admin/system locations).
- With only the real `.agents/skills` tree, every firstmate internal skill (all 18 pre-change names, then 19 including `ticket-queue-discipline`) appeared under skill root `.../firstmate/.agents/skills`.
- When `.codex/skills` is a symlink to `.agents/skills`, Codex lists a single project root at the resolved `.agents/skills` path and does **not** double-list the same skill.
- User-level skills come from `~/.codex/skills` (and related plugin/system roots).

### Claude

Commands:

```sh
claude -p --output-format stream-json --verbose --no-session-persistence \
--permission-mode dontAsk --tools Skill \
--debug-file /var/folders/bd/ky17fvwx45353ky4s2bg8ys80000gn/T/no-mistakes-evidence/01KZ4B0458NGJFN2BJ5QTM3VFN/claude-skill-debug.log \
--system-prompt 'Use the Skill tool when instructed. Do not use any other tool.' \
'Load the project skill ticket-queue-discipline. Then reply only: LOADED ticket-queue-discipline.'
rg 'Loading skills from:|SkillTool returning' \
/var/folders/bd/ky17fvwx45353ky4s2bg8ys80000gn/T/no-mistakes-evidence/01KZ4B0458NGJFN2BJ5QTM3VFN/claude-skill-debug.log
```

Findings:

- Claude's debug log names the project skill root as this worktree's `.claude/skills` path.
- The agent invoked `Skill` with `{"skill":"ticket-queue-discipline"}`.
- The runtime returned `Launching skill: ticket-queue-discipline`, logged `SkillTool returning 2 newMessages for skill ticket-queue-discipline`, and the agent replied `LOADED ticket-queue-discipline.` with `subtype=success` and `is_error=false`.
- This is a live load of the new skill in the feature worktree, not an inference from the symlink alone.
- `.claude/skills -> ../.agents/skills` resolves that runtime root to the same canonical body used by Codex and Grok.
- CI and CONTRIBUTING assert `[ "$(readlink .claude/skills)" = "../.agents/skills" ]` (and the same check for `.codex/skills` and `.grok/skills` after this branch).
- These filesystem and CI checks support the wiring evidence but do not substitute for the runtime load observation above.

## Symlinks, worktrees, and clone

The target commit records all three harness paths as git symlinks with the same link-target blob:

```sh
git ls-files -s .claude/skills .codex/skills .grok/skills
```

```text
120000 2b7a412b8fa0fb7e985b0793321bd4e698f2b6cd 0 .claude/skills
120000 2b7a412b8fa0fb7e985b0793321bd4e698f2b6cd 0 .codex/skills
120000 2b7a412b8fa0fb7e985b0793321bd4e698f2b6cd 0 .grok/skills
```

Separate disposable git repo probe (not firstmate content):

```sh
# after git add/commit of .agents/skills plus
# .claude/skills, .codex/skills, .grok/skills each -> ../.agents/skills
git clone <probe> <clone>
git worktree add <wt> HEAD
# in both clone and worktree: readlink and test -f <harness>/skills/x/SKILL.md
```

All three symlinks survived clone and linked worktree checkout and resolved to readable `SKILL.md` files when `core.symlinks` is enabled (default on this host).

## Contract that follows

1. Authors edit only `.agents/skills/`; never copy skill bodies into harness directories.
2. Harness-native paths stay symlinks to that tree so clone, worktree, and checkout stay one source of truth.
3. Do not invent a project path a harness does not scan; Grok's project `.codex/skills` is not a discovery root, while Codex does scan project `.codex/skills` when present.
4. Re-verify this record when a harness version changes skill-root behavior.
Loading