## What
Round-2 Gas City doctrine sweep (**ag-94vu**). Re-narrates the **5 named
skill surfaces** that still framed Gas City as THE live reference
substrate (present-tense operator instructions) to the canonical
substrate trio — **NTM (tmux swarm) + MCP (`ao mcp serve`) +
managed-agents (`ao agent`)** — matching [`docs/3.0.md`](docs/3.0.md).
Driver: post-mortem checkpoint #6 Judge-3 FAIL ("the repo does not yet
speak one doctrine").
## Surfaces (9 insertions / 9 deletions, 5 files)
- `skills/domain/references/factory.md` — "Gas City is the reference
substrate" → the NTM/MCP/managed-agents trio; "Mayor-driven / `gc
sling`" → **swarm-driven** dispatch.
- `skills/scope/SKILL.md` — cron-cadence orchestration reference.
- `skills/session-bootstrap/SKILL.md` — substrate submit reference.
- `skills/SKILL-TIERS.md` — dream retired-pointer note.
- `skills-codex/using-agentops/SKILL.md` — **codex-twin parity**:
dropped the stale `gc` runtime-mode row for the canonical `substrate`
row (the Claude twin was already correct; this one slipped in #679).
## Bounded by design
This PR is the coherent **"live skill operator-instructions speak one
doctrine"** slice. A repo-wide grep shows ~35 more refs across other
skills + `docs/` narrative; bundling them would reproduce the #682
mega-PR that was rejected for sprawl. Deferred to tracked follow-ups:
- **ag-r6g1** — round-3 narrative sweep (remaining skills/ + docs/ ~35
refs; many docs already frame GC correctly as "the reference" — triage
required).
- **ag-82pv** — remove orphaned
`GasCityPhaseEvidence*`/`GasCityTranscript*` dead types in
`cli/internal/rpi/artifacts.go`.
## Verification (local, green)
- codex-parity-drift: PASS · registry-drift: PASS (80) ·
skill-catalog-drift: up-to-date · skill-isolation: PASS · skill-size:
0/0 · markdownlint: 0 errors.
- Residual live-substrate grep over the 5 surfaces: clean.
Closes-scenario: ag-94vu#live-substrate-renarration
Bounded-context: BC1-Corpus
Evidence: skills/domain/references/factory.md
Lands the honest AgentOps 3.0 doctrine so the repo's narrative matches
the shipped code: the daemon is **deleted**, AgentOps is the
**in-session** agent operating loop + context compiler, and
out-of-session orchestration is delegated to a substrate (the reference
**Gas City City** or **Olympus**).
## What landed
- **`docs/3.0.md`** (north star, rewritten): in-session-only identity;
honest GC reference-City section — dispatch is **mayor-driven** today,
order-auto-dispatch is a labeled **GC-upstream maturity gap**
(`soc-5jwah`), not turnkey; two reference implementations table
(AgentOps-on-GC has **no** daemon; Olympus **kept** its daemon because
it is a sovereign product); e2e-proof evidence cited.
- **`docs/architecture/canonical-loop-model.md`** (new): one loop body,
two drivers, one inner tick, one config. Evolve (in-session,
AgentOps-shipped) vs Factory (out-of-session, substrate-owned);
crank/swarm placed as in-session steps.
- **`docs/adr/ADR-0009-daemon-deletion-in-session-only.md`** (new,
Accepted): the daemon-deletion decision — DELETE-not-deprecate rationale
(AgentOps has no core to protect; Olympus kept its daemon because it's
sovereign), the rejected *deprecate-keep-standalone* alternative, the
sovereignty tradeoff (always-on requires GC), the e2e GC dispatch gap.
References `soc-j7a5q`.
- **`skills/domain/references/`**: loop-family vocabulary (loop, evolve,
factory, rpi, autodev, context-compiler) as 6 entries + INDEX rows +
SKILL.md links.
- **README**: "Two ways to use it" reframed to **in-session vs
out-of-session**; deleted-command prose (`ao daemon` / `ao schedule` /
`ao overnight`) reframed to in-session + GC reference.
- **`packs/agentops`**: dispatch relabeled mayor-driven;
order-auto-dispatch GC-upstream gap (`soc-5jwah`) called out in
`bead-dispatch.toml`, `rpi-dispatch.toml`, and `FINALIZE-NOTES.md`. `gc
config show --validate` still exits 0.
- Reconciled stale `agentopsd` prose in `skills/scope` +
`skills/session-bootstrap`.
## Gates
- `heal.sh --strict`: clean
- doc-release gate: succeeded (link validation PASS, 0 broken)
- `gc config show --validate --city .`: exit 0
- markdownlint: 0 errors
- `generate-registry.sh --check`: up to date
- codex parity (domain): passed
- `go build ./...`: success
**Do not merge** — the operator reviews `docs/3.0.md` before tagging.
Closes-scenario: soc-j7a5q#3.0-honest-doctrine
Bounded-context: BC1-Corpus
Evidence: .agents/discovery/2026-05-24-gvkj6-e2e-proof.md
#275's billboard refactor thinned process-skill SKILL.md files and moved
detail into references/, but the validate contracts still grepped SKILL.md.
skill-lint + smoke-test: relax content-presence checks in crank/implement/
post-mortem/swarm validate.sh to scan the skill as a unit (SKILL.md +
references/); structural/identity checks stay SKILL.md-only. test-first-smoke
updated to match relocated SPEC/TEST WAVE + Step 0/4 headings.
skill-lint line caps: trim flywheel 310 -> 286 (cap 300), using-agentops
261 -> 239 (cap 250) by removing redundant prose, no content lost.
skill-integrity: link 3 orphaned references (crank/branch-isolation,
validation/flags + release-readiness-gates).
codex parity: regenerate stale skills-codex source hashes (77 skills).
Local: run-all.sh PASS, heal.sh --strict clean, smoke-test PASS.
Hard-block enforcement of declared edit scopes. Ports gstack's
/freeze + /unfreeze + /guard semantics with codex-parity skill bundle.
CLI:
- ao scope freeze <dir>... — additive set of locked dirs
- ao scope unfreeze [<dir>] — empty arg clears all
- ao scope status [--json] — print current Lock state
Hook:
- hooks/edit-scope-guard.sh on PreToolUse matcher Edit|Write|Bash.
Reads JSON tool input from stdin, compares target path against
.agents/scope.lock entries, exits 2 with structured stderr reason
if outside scope. Fail-open on malformed input (per pre-mortem
Finding 3): jq parse failure or missing target -> exit 0 with
stderr warning, never crash to block all edits.
- hooks/hooks.json: single-block append (no other Wave 1 issue
touches this file).
Atomic-write contract (per pre-mortem hand-off requirement):
- cli/internal/scope.Write delegates to llmwiki.SafeAtomicWrite first,
then falls back to llmwiki.AtomicWriteFile if .agents/ is outside
the wiki vault allowlist. Both paths use temp+rename, no new locking
semantics. Same atomic guarantee proven in agentopsd queue-claim
invariants.
- cli/internal/scope/scope_test.go includes 100-goroutine concurrency
test asserting torn-write impossibility.
Pre-mortem Finding 2 (hook activation test) applied:
- tests/hooks/test-edit-scope-guard-fires.sh exercises 7 cases incl.
fail-open on malformed JSON, missing lock, empty frozen_dirs, nested
subdir. All 7 PASS.
Pre-mortem Finding 3 (malformed-input defense) applied verbatim
at hooks/edit-scope-guard.sh:18-27.
Codex parity: skills-codex/scope/{SKILL.md,prompt.md,references/}
ships in same commit. scripts/audit-codex-parity.sh --skill scope
passes.
Note: pre-mortem pseudocode for L2 test case 2 had inverted freeze
semantics; reconciled to spec-correct positive allow-list (when
frozen_dirs is non-empty, only paths under them are allowed).
Addresses CLAUDE.md's #1 swarm failure mode ("file overlap"). Hard
enforcement, not advisory like dangerous-git-guard.sh.
Wave 1 of epic soc-irg1 (gstack absorption Tier 1).