@agentsfleet/orly 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/.githooks/pre-commit +42 -0
  2. package/.githooks/pre-push +67 -0
  3. package/AGENTS.md +348 -0
  4. package/LICENSE +21 -0
  5. package/README.md +249 -0
  6. package/SOUL.md +90 -0
  7. package/audits/agents-md.md +497 -0
  8. package/audits/agents-md.sh +353 -0
  9. package/audits/cross-tier-rates.sh +105 -0
  10. package/audits/data.sh +185 -0
  11. package/audits/deinit-pairs.sh +224 -0
  12. package/audits/design-tokens.sh +143 -0
  13. package/audits/doc-read.sh +183 -0
  14. package/audits/error-codes.sh +221 -0
  15. package/audits/fixtures/clean.diff +15 -0
  16. package/audits/fixtures/dirty.diff +16 -0
  17. package/audits/lifecycle-anchors.sh +22 -0
  18. package/audits/logging.sh +217 -0
  19. package/audits/msid-ui.sh +144 -0
  20. package/audits/parity-dispatch.sh +51 -0
  21. package/audits/rule-ledger-lib.sh +264 -0
  22. package/audits/rule-ledger.sh +225 -0
  23. package/audits/rule-paths.sh +108 -0
  24. package/audits/spec-template.sh +258 -0
  25. package/audits/sql-mod.sh +102 -0
  26. package/audits/ufs.sh +303 -0
  27. package/bin/orly +26 -0
  28. package/core/operating-model.md +256 -0
  29. package/dispatch/edit_rules.md +69 -0
  30. package/dispatch/lib.sh +213 -0
  31. package/dispatch/lifecycle.md +187 -0
  32. package/dispatch/name_architecture.md +93 -0
  33. package/dispatch/verify.md +111 -0
  34. package/dispatch/write_any.md +740 -0
  35. package/dispatch/write_any.sh +49 -0
  36. package/dispatch/write_auth.md +36 -0
  37. package/dispatch/write_changelog.md +64 -0
  38. package/dispatch/write_documentation.md +45 -0
  39. package/dispatch/write_go.md +24 -0
  40. package/dispatch/write_http.md +45 -0
  41. package/dispatch/write_mdx.md +7 -0
  42. package/dispatch/write_python.md +8 -0
  43. package/dispatch/write_rust.md +38 -0
  44. package/dispatch/write_shell.md +8 -0
  45. package/dispatch/write_spec.md +105 -0
  46. package/dispatch/write_sql.md +112 -0
  47. package/dispatch/write_sql.sh +36 -0
  48. package/dispatch/write_ts_adhere_bun.md +493 -0
  49. package/dispatch/write_ts_adhere_bun.sh +37 -0
  50. package/dispatch/write_zig.md +852 -0
  51. package/dispatch/write_zig.sh +40 -0
  52. package/docs/CHANGELOG_VOICE.md +18 -0
  53. package/docs/DISPATCH_ARCHITECTURE.md +664 -0
  54. package/docs/DISPATCH_REVIEW_DISPOSITION.md +65 -0
  55. package/docs/DOCUMENTATION_RULES.md +209 -0
  56. package/docs/EXECUTE_DOC_READS.md +29 -0
  57. package/docs/HARNESS_VERIFY_OUTPUT.md +40 -0
  58. package/docs/LIFECYCLE_PATTERNS.md +316 -0
  59. package/docs/LOGGING_STANDARD.md +397 -0
  60. package/docs/ORLY_ARCHITECTURE.md +129 -0
  61. package/docs/REST_API_DESIGN_GUIDELINES.md +783 -0
  62. package/docs/RULE_ENFORCEMENT.md +41 -0
  63. package/docs/SCHEMA_CONVENTIONS.md +93 -0
  64. package/docs/TEMPLATE.md +411 -0
  65. package/docs/VERIFY_TIERS.md +57 -0
  66. package/docs/greptile-learnings/README.md +51 -0
  67. package/docs/greptile-learnings/RULES.md +1045 -0
  68. package/fixtures/registry-invalid.json +1 -0
  69. package/fixtures/registry-valid.json +18 -0
  70. package/fixtures/unclosed-pack-block.md +8 -0
  71. package/package.json +63 -0
  72. package/packs/language/go/rules.md +24 -0
  73. package/packs/language/mdx/rules.md +7 -0
  74. package/packs/language/python/rules.md +8 -0
  75. package/packs/language/rust/rules.md +38 -0
  76. package/packs/language/shell/rules.md +8 -0
  77. package/registry.json +405 -0
  78. package/schemas/evidence.schema.json +43 -0
  79. package/schemas/profile.schema.json +12 -0
  80. package/schemas/registry.schema.json +12 -0
  81. package/skills/orly-babysit-prs/SKILL.md +326 -0
  82. package/skills/orly-spec-new/SKILL.md +157 -0
  83. package/skills/orly-write-integration-test/SKILL.md +470 -0
  84. package/skills/orly-write-unit-test/SKILL.md +520 -0
  85. package/src/cli.test.ts +70 -0
  86. package/src/cli.ts +287 -0
  87. package/src/config.test.ts +226 -0
  88. package/src/config.ts +288 -0
  89. package/src/criteria.test.ts +137 -0
  90. package/src/criteria.ts +166 -0
  91. package/src/criteria_spec.ts +127 -0
  92. package/src/criteria_support.ts +53 -0
  93. package/src/gates.test.ts +183 -0
  94. package/src/gates.ts +169 -0
  95. package/src/gates_spec.test.ts +98 -0
  96. package/src/gates_test_support.ts +194 -0
  97. package/src/git_env.ts +20 -0
  98. package/src/install.test.ts +514 -0
  99. package/src/install.ts +447 -0
  100. package/src/install_nested.test.ts +32 -0
  101. package/src/model.test.ts +31 -0
  102. package/src/model.ts +245 -0
  103. package/src/references.test.ts +47 -0
  104. package/src/references.ts +147 -0
  105. package/src/render.test.ts +60 -0
  106. package/src/render.ts +94 -0
  107. package/src/surfaces.test.ts +43 -0
  108. package/src/surfaces.ts +89 -0
  109. package/src/validation.test.ts +11 -0
  110. package/src/validation.ts +87 -0
  111. package/src/verify.test.ts +13 -0
  112. package/src/verify.ts +59 -0
@@ -0,0 +1,187 @@
1
+ # lifecycle.md — stage-runbook latent façade
2
+
3
+ Read this at a lifecycle stage transition: CHORE(open), PLAN, EXECUTE onboarding,
4
+ CHORE(close), LAND, worktree setup, or milestone bootstrap. The generated
5
+ `AGENTS.md` carries each stage's binding essence; this façade carries the
6
+ runbooks — the checklists, recipes, and output formats an agent needs only at
7
+ that moment. 🤔 judgment-only — no `.sh` pair; CONFORM's deterministic gates and
8
+ `orly gate` remain the mechanical anchors.
9
+
10
+ Section-scan first (`grep -n "^## " dispatch/lifecycle.md`); read the stage you
11
+ are entering, not the whole file.
12
+
13
+ ## CHORE (open) — runbook
14
+
15
+ 1. Spec `docs/v*/pending/` → `active/`; `Status: IN_PROGRESS`; `Branch:` set.
16
+ 2. **Test Baseline** — run the repository's declared `verify.unit` (and
17
+ `verify.integration` where declared) from `.oracle/orly.json`; copy the
18
+ reported counts into the spec header as `**Test Baseline:** unit=<N>
19
+ integration=<M>` (VERIFY's Test Delta row compares against it; a product
20
+ pack may name a dedicated counter — see the product block below).
21
+ 3. Create the worktree; verify CWD is inside it (`pwd` + `git worktree list`).
22
+ 4. Commit the four steps on the feature branch. No code until the commit lands.
23
+
24
+ <!-- oracle-packs:start product.agentsfleet -->
25
+ ## Worktree recipe (agentsfleet)
26
+
27
+ `git checkout main && git branch feat/mNN-name && git worktree add ../agentsfleet-mNN-name feat/mNN-name && cd ../agentsfleet-mNN-name && bun install && (cd cli && bun install && bun run build)`.
28
+ The root `bun install` hydrates the workspace (`ui/packages/*`); `cli/` is its
29
+ own Bun project needing install + build. `git worktree add` fires
30
+ `.githooks/post-checkout` → symlinks `~/.config/agentsfleet/{ui,runner}.env.local`
31
+ into the tree; on 🟠 run `provision-env-1password`, re-link. Post-merge:
32
+ `git worktree remove ../agentsfleet-mNN-name`.
33
+
34
+ **agentsfleet Test Baseline counter:** `make _lint_zig_test_depth`.
35
+
36
+ **agentsfleet CHORE(close) paths:** the `<Update>` lands in
37
+ `~/Projects/docs/changelog.mdx` (template + version-bump matrix:
38
+ `skills/release-template.md` in the governance checkout — re-source each
39
+ release, never paraphrase). Version sync: `VERSION` touched → `make
40
+ sync-version`; commit propagated `build.zig.zon` / `agentsfleet/package.json` /
41
+ `agentsfleet/src/cli.js`; `make check-version` passes.
42
+
43
+ **dotfiles takes NO worktree — feature branches in the main checkout.** Every
44
+ agent-home symlink and every consumer's `ORLY_ROOT` resolves to
45
+ `~/Projects/dotfiles`; a linked worktree's `.git` is a *file*, and the audit
46
+ chain the hooks run spawns git against other directories. Under a hook that
47
+ combination corrupted the real index and flipped `core.bare` (Aug 16, 2026).
48
+ So: `git checkout -b feat/mNN-name` in `~/Projects/dotfiles` itself, and
49
+ `orly update` always renders the one true root. One stream at a time —
50
+ a second concurrent agent coordinates in-session rather than forking a tree.
51
+ This is the dotfiles exception; product repos keep the worktree recipe above.
52
+ <!-- oracle-packs:end -->
53
+
54
+ **Mid-stream spec → ask before hydrating (default: same tree).** A spec created
55
+ inside an active worktree → ask the user before spinning up a second one. Lean
56
+ same tree: a second tree fragments the outcome and adds a PR to babysit.
57
+ Complete the outcome in place; fold new scope into the current spec/PR (reopen
58
+ `done/`→`active/` if closed) unless the work is genuinely disjoint AND the user opts
59
+ into a separate tree.
60
+
61
+ ## Bootstrap & milestone gates
62
+
63
+ - **Complete `.oracle/orly.json` on first sight.** `orly init` seeds it
64
+ mechanically — it reads the Makefile (following `include` one level) and
65
+ `package.json` scripts, matches a fixed list of target names, and writes what
66
+ it matched. It finds the obvious ones and misses the rest, and it never
67
+ guesses `surfaces`.
68
+ First session in a repository whose config is still that seed:
69
+ 1. Read the build files properly. Fill every `verify.*` the repository really
70
+ has — the tiering is fixed (`conform` + `verify.unit` are the fast tier,
71
+ every other `verify.*` is slow and skips on prose-only branches).
72
+ 2. Set `surfaces.user` and `surfaces.docs` to real path prefixes, or the docs
73
+ gate can never fire and a user-visible change ships undocumented.
74
+ 3. Add any opt-in pack the repository's own sources cannot imply
75
+ (`persona.indy`, `product.agentsfleet`, `workflow.governance`), then run
76
+ `orly update` so they materialise.
77
+ 4. Commit it. Every teammate and every later session reads this file, and
78
+ `orly` never rewrites it — so an edit here is permanent.
79
+ A seeded-but-uncompleted config is why `orly gate` reports a repository with
80
+ no declared commands: the fix is this list, not another `orly init`.
81
+ - **Priming:** (1) Human runs `playbooks/founding/01_bootstrap/001_playbook.md`.
82
+ (2) Agent runs `./playbooks/founding/02_preflight/00_gate.sh` (green before
83
+ next). (3) Agent runs `playbooks/founding/03_priming_infra/001_playbook.md`.
84
+ Milestones only after PRIMING_INFRA verified.
85
+ - **Credential gate** — milestones needing external creds start `M{N}_001`
86
+ enumerating every downstream credential (name + fetch location). Fail loud
87
+ listing all missing before any `M{N}_002+`.
88
+ - **Agent-first sequencing** — minimize human steps; post-handoff steps
89
+ retryable + idempotent. Vault is the inter-step interface; never pass creds
90
+ by argument/env.
91
+
92
+ ## PLAN — expansions
93
+
94
+ **Quality-ceiling line** — would it be more performant / leaner / a better user
95
+ experience (fluid) / sounder under concurrency if built differently, and would a
96
+ larger refactor beat the patch? Default solution-size ≈ problem-size; "yes" →
97
+ surface option + cost, the user picks. Read docs when behavior is unclear.
98
+
99
+ **Surface-area checklist** — yes/no + reason each: OpenAPI changes (list paths)
100
+ · the product's CLI · user-facing docs · release notes
101
+ / version bump · schema changes (≤100 lines/file, single-concern, update
102
+ `schema/embed.zig` + migration array) · Schema Removal Guard output ·
103
+ spec-vs-rules conflict (amend spec).
104
+
105
+ ## EXECUTE — spec discipline expansions
106
+
107
+ - **Golden-path before PLAN approval** — walk the concrete end-to-end with every
108
+ lookup/data-source/secret-storage named; any `[?]` blocks the spec.
109
+ - **DONE = called in production + tested** — grep the production entry-point for
110
+ the named symbol; no call → not DONE.
111
+ - **Changelog claim challenge** — before any `<Update>`, ask "Would this be true
112
+ if the test file vanished?" Only test evidence (not middleware/handler/CLI) →
113
+ claim unearned.
114
+ - **Spec → Code → Test alignment:** every Dimension → test case (no test = not
115
+ implemented); every Interface → exact spec signature (signature change →
116
+ update spec first); every Acceptance Criterion → verifiable command ("works
117
+ correctly" is not a criterion; "`make test` passes" is); no code commits
118
+ without tests (`/orly-write-unit-test`); every Error Table row → negative test.
119
+ - **Recovery notes:** local Docker `ENOSPC` → `~/bin/mac-cleanup.sh`, verify
120
+ `docker system df`, retry.
121
+
122
+ ## CHORE (close) — required outputs
123
+
124
+ - All Dimensions/Sections `DONE` (`IN_PROGRESS` if parked); spec moved
125
+ `docs/v*/active/` → `docs/v*/done/` iff complete.
126
+ - Changelog: a new entry on the repository's declared docs surface
127
+ (`surfaces.docs`; `write_changelog` façade where materialised) for
128
+ user-visible changes **AND, re-reading the spec, the affected published docs
129
+ pages revised to match (endpoints/CLI/flags/behavior)** — an entry alone is
130
+ insufficient when documented behavior changes. Product-specific paths: the
131
+ product pack block above.
132
+ - `docs/architecture/**` carries a non-empty diff for flow-defining changes, or
133
+ Session Notes says why not (`dispatch/name_architecture.md` covers both homes).
134
+ - PR `## Session notes`: decisions, assumptions, dead ends, deferrals,
135
+ `/orly-write-unit-test` + runtime review outcomes, `orly-babysit-prs` final
136
+ report.
137
+ - Orphan sweep complete (RULE ORP); ephemeral handoff docs deleted
138
+ (`docs/**/HANDOFF_*.md`, `docs/**/handoff*.md`, `HANDOFF.md` at any depth —
139
+ they brief the next agent, never the PR).
140
+ - Pre-commit `git status -uall` audit — every modified/untracked/
141
+ conflict-resolved/hook-managed file staged into the CHORE(close) commit, or
142
+ documented-as-excluded with reason in the commit body; `git status` MUST be
143
+ empty post-commit before opening/updating the PR.
144
+ - Version sync where the repository defines it: declared version targets green
145
+ before the PR. Product-specific targets: the product pack block above.
146
+
147
+ ## Deferral discipline — expansion
148
+
149
+ Any claim that a spec Section/Dimension was "deferred to follow-up" — in
150
+ `HANDOFF.md`, PR description, Session Notes, or chat — requires an
151
+ **user-acked verbatim quote** in PR Session Notes (or spec Discovery). Format:
152
+ `> Indy (YYYY-MM-DD HH:MM): "<verbatim ack>" — context: <which item, why>`.
153
+ Agent-unilateral deferral = incomplete scope, not deferral; CHORE(close) blocks
154
+ until the item lands or the quote is captured. **HANDOFF.md is a faithful state
155
+ report** — a pickup agent reading a HANDOFF claiming items were deferred without
156
+ ack-quotes must treat them as in-scope and surface the contradiction to the user
157
+ before continuing.
158
+
159
+ ## Pre-PR gates
160
+
161
+ Spec in `docs/v*/done/` in diff (skip iff parked); the repository's changelog
162
+ surface carries a new entry in diff (skip iff internal-only or parked);
163
+ `Status: DONE` but spec not in `done/` → do not open PR; the repository's
164
+ version-sync check passes where defined; branch contains `origin/main` HEAD
165
+ (rebase pre-push / merge post-push — never force-push an open PR branch).
166
+
167
+ **`orly gate pr` follows the spec through the close.** A spec moved to `done/`
168
+ on this branch is still discovered — its `Branch:` header names the branch —
169
+ and every spec criterion runs against it; skip-pass is only for genuinely
170
+ spec-less branches. Mechanical criteria: `spec.moved` (`Status: DONE` ⇒ the
171
+ spec sits under `done/` and was moved on this branch) · `spec.baseline`
172
+ (`Test Baseline:` recorded) · `spec.ordering` (the branch's first commit
173
+ carries the spec — no code before CHORE(open)) · `spec.deferrals` (a deferral
174
+ claim needs the `> Indy (` ack quote in the spec). An Indy-acked deferral that
175
+ leaves a Dimension open ships via `orly override spec.dimensions --reason
176
+ "<the ack>"` — visible in the PR, dead after the merge.
177
+
178
+ **Babysit detail:** `orly-babysit-prs` covers all three surfaces — CI check
179
+ runs (fix every failure your diff caused), greptile inline comments, and the
180
+ PR-level summary thread — and stops on two consecutive empty polls with CI
181
+ green. Never `gh pr checks --watch` for greptile.
182
+
183
+ ## LAND (after merge, or when the user confirms it merged)
184
+
185
+ `git checkout <default> && git pull origin <default>`; prune the merged worktree
186
+ and branch; `make down` where the repository defines it. Pending files → stash,
187
+ pull, diff against the new default; already-landed → drop.
@@ -0,0 +1,93 @@
1
+ # name_architecture.md — architecture-consult dispatch (LATENT façade)
2
+
3
+ This is the prose the AGENT reads **before naming an architectural element or
4
+ describing a data flow**. Like `verify`, it has **no deterministic `.sh` half** —
5
+ no script can detect the moment an agent is *about to name a stream* or *assert a
6
+ cardinality*. It is a pure **🤔 judgment** dispatch grounded in `docs/architecture/`.
7
+ (This is the former Architecture Consult & Update gate absorbed into the dispatch model.)
8
+
9
+ **Signal legend:**
10
+
11
+ - 🤔 DECIDE — judgment-only; the agent greps the relevant `docs/architecture/`
12
+ topic file and grounds its naming/flow claim in it. Blocks the *turn*, not a
13
+ commit.
14
+
15
+ ## Trigger — grep/read the relevant `docs/architecture/` topic file before
16
+
17
+ - Naming a stream / pub-sub channel / Redis key namespace / consumer group /
18
+ queue / RPC method / Postgres schema / table.
19
+ - Asserting cardinality ("one row per X", "exactly one consumer per stream",
20
+ "fleet-wide vs per-tenant").
21
+ - Describing a flow ("on crash → X reclaims via Y", "trigger source A lands on
22
+ stream B with actor C").
23
+ - Answering a user question about how data flows between components.
24
+ - Proposing a change to any of the above as part of a spec or implementation.
25
+ - A new architecture-adjacent question that arises mid-task — re-consult per
26
+ topic, not once per task.
27
+
28
+ **Override:** none — doc wins until reconciled.
29
+
30
+ ## Why
31
+
32
+ `docs/architecture/` (the directory; topic files linked from
33
+ `docs/architecture/README.md`) is canonical for stream/channel/queue names, table
34
+ cardinality, ownership, and end-to-end flows. The failure mode is reinventing
35
+ terms or asserting flow shapes from training data instead of grounding in the
36
+ doc. Specs are *instances*; this doc is the *constant* — when they disagree, the
37
+ doc wins until reconciled.
38
+
39
+ ## Behavior
40
+
41
+ - **Doc answers** → proceed (no citation block).
42
+ - **Doc silent** → proceed with extra care; land doc decision in same commit.
43
+ - **Doc conflicts** → surface with a one-line citation (`grounded in §X.Y,
44
+ proposal extends/conflicts because <reason>`) and wait.
45
+ - **Greenfield** → land initial doc + code in same commit.
46
+
47
+ ## Landing rule (non-negotiable)
48
+
49
+ An architecture decision lands its `docs/architecture/` edit either:
50
+
51
+ - **(a)** immediate doc-only commit on the active branch (preferred), OR
52
+ - **(b)** same commit as the implementation.
53
+
54
+ **Never** (c) follow-up commit AFTER the code.
55
+
56
+ **Chat brainstorming counts as "describing a flow."** A multi-turn chat designing
57
+ a new pattern (naming a channel, asserting cardinality, tracing a flow, defining
58
+ an invariant) HAS fired the dispatch even if no code touched yet. Acceptable
59
+ resolutions: (a) doc-only commit BEFORE the next agent action, or (b) Indy-acked
60
+ deferral quote (per CHORE(close) deferral discipline) routing the capture into
61
+ same-commit-with-code. The failure mode this clause names explicitly: encoding the
62
+ brainstorm as a "punchlist task to land after the code ships" — that's exactly (c)
63
+ and is forbidden. Pickup agents reading a task whose description says "capture
64
+ architecture in docs/architecture/ AFTER <slice> lands" must rewrite it to
65
+ same-commit OR doc-only-now before continuing.
66
+
67
+ ## Required output (only when doc conflicts or is silent)
68
+
69
+ ```
70
+ ARCH: grounded in <topic-file>:<§X.Y> | proposal: <one-line> | status: <extends|conflicts|silent> | landing: <a|b>
71
+ ```
72
+
73
+ When the doc directly answers, no output is required.
74
+
75
+ ## CHORE(close) check — both doc homes
76
+
77
+ Architecture truth has TWO homes with different audiences; an architecture-touching
78
+ branch settles both before the Pull Request (PR) opens:
79
+
80
+ - **Product repo `docs/architecture/**`** (internal design truth). Every M-spec
81
+ branch that touched flow-defining code produces a non-empty
82
+ `git diff origin/main..HEAD -- docs/architecture/`. Else PR Session Notes
83
+ documents why nothing architectural changed.
84
+ - **Docs project `~/Projects/docs/`** (user-facing, `docs.agentsfleet.net`). When
85
+ the change alters documented user-facing behaviour (endpoints, Command-Line
86
+ Interface (CLI) surface, flags, flows users see), the affected pages are
87
+ revised per the CHORE(close) required
88
+ outputs in `AGENTS.md` — a changelog `<Update>` alone is insufficient.
89
+ Internal-only reshaping with no documented-behaviour change → no docs-project
90
+ edit, and Session Notes say so.
91
+
92
+ Updating one home and not the other is the failure mode this section names: the
93
+ internal doc drifts from what users are told, or vice versa.
@@ -0,0 +1,111 @@
1
+ # write — verify.md — verification dispatch (LATENT façade)
2
+
3
+ This is the prose the AGENT reads **before emitting any message that asserts work
4
+ is verified**. Unlike `write_zig` / `write_any`, `verify` has **no deterministic
5
+ `.sh` half** — no script can detect the moment an agent is *about to claim done*.
6
+ It is a pure **🤔 judgment** dispatch: the agent reads this, runs the canonical
7
+ `make` targets, and emits the verdict block. The trigger is a *claim*, not a file
8
+ edit. (This is the former Verification gate absorbed into the dispatch model.)
9
+
10
+ **Signal legend:**
11
+
12
+ - 🤔 DECIDE — judgment-only; the agent must run the targets below and report
13
+ honestly. No script gates this — it blocks the *turn*, not a commit.
14
+ - 🟣 delegated — the `make` targets themselves live in the product repo; dotfiles
15
+ carries only the discipline of *which* targets are canonical and when.
16
+
17
+ ## Trigger
18
+
19
+ Fires before any user-facing message asserting verification: *"tests pass",
20
+ "ready to merge", "shipping", "ready for review", "CHORE(close) ready"* — or any
21
+ equivalent.
22
+
23
+ **Override:** `VERIFY GATE: <target> skipped per environment constraint (reason: ...)`.
24
+ Only when a target is genuinely unrunnable (e.g. Docker missing for integration
25
+ tests). Surface the limitation in the done message — never dress a skip as "tests
26
+ pass".
27
+
28
+ ## Why `make` is canonical
29
+
30
+ Package-scoped runners (`bun run test`, `vitest <file>`, `zig build test` without
31
+ the integration tier) are **not** verification — they skip cross-package lint,
32
+ cross-compile, pg-drain, and integration. `make` targets are the canonical gates.
33
+
34
+ ## Required runs
35
+
36
+ | Target | When |
37
+ |---|---|
38
+ | `make lint` | Always. |
39
+ | `make test` | Always (tier 1, unit-only by definition). |
40
+ | `make test-integration` | Tier 2: diff touches HTTP handlers, schema, DB code, Redis code, or any `_integration_test.zig`. Focused subsets: `make test-integration-db` / `make test-integration-redis`. |
41
+ | `make test-integration` | Tier 3: at least once per branch before declaring ship-ready, from a clean state (e.g. after `make down`) when tier 2 is intermittent — fresh DB proves no state carry-over. |
42
+ | `make memleak` | Server lifecycle (`src/http/**`, `src/cmd/serve.zig`), allocator wiring, cross-thread heap ownership. |
43
+ | `make bench` (local) | Diff touches request-path code, allocator wiring, or startup/shutdown sequencing. |
44
+ | `API_BENCH_URL=https://api-dev.agentsfleet.net/healthz make bench` | After branch deploys to dev. |
45
+ | Cross-compile `x86_64-linux` + `aarch64-linux` | Whenever `*.zig` touched. |
46
+ | `make check-pg-drain` | Whenever `*.zig` touched. |
47
+ | `/orly-write-integration-test` (skill) | With `/orly-write-unit-test` at VERIFY when the diff crosses module boundaries with real I/O; otherwise record `N/A — <reason>`. |
48
+ | Acceptance e2e (product repo's live tier) | Diff touches a surface the live/acceptance tier covers — relevant acceptance suites green, or their opt-in skip matrix recorded. |
49
+
50
+ `make test` never substitutes for tier 2/3. Tier 2 passing but tier 3 failing
51
+ means state pollution — fix isolation before shipping.
52
+
53
+ ## Memleak evidence rule
54
+
55
+ Before CHORE(close) reports green, paste the final `make memleak` result line into
56
+ the PR Session Notes block OR cite the CI memleak job URL. Branches touching
57
+ `src/http/**`, `src/cmd/serve.zig`, or allocator wiring MUST include the last 3
58
+ lines verbatim. No "I ran it, trust me."
59
+
60
+ ## Coverage discipline
61
+
62
+ - **Branch coverage is the goal; line coverage is the floor.** One input "covers" a multi-clause condition while leaving its logic untested (`trimmed === "" || === "y" || === "yes"` passes line coverage with a single `"y"`). Feed varied inputs across the equivalence classes — each OR clause independently, success-retry AND fail-retry paths, every early-return guard, empty/casing/whitespace/garbage for normalizers. bun's lcov emits no branch records, so this is test-design discipline, not a number to chase.
63
+ - **Do not chase per-file 97% on declaration-heavy files.** bun marks compiler-erased lines (`import type`, `interface`) as 0-hit — no test can execute them, and restructuring to lift the number backfires (inlined type literals get instrumented as 0-hit too). The enforced gates are **aggregates** (`enforce-coverage.mjs` global row; codecov patch across uploaded packages); a few erased lines dilute to noise there. No codecov `ignore` entries either — gate on the aggregate.
64
+
65
+ ## Bench knobs
66
+
67
+ `make/test-bench.mk` env vars: `API_BENCH_METHOD`, `API_BENCH_DURATION_SEC`,
68
+ `API_BENCH_CONCURRENCY`, `API_BENCH_TIMEOUT_MS`, `API_BENCH_MAX_ERROR_RATE`,
69
+ `API_BENCH_MAX_P95_MS`, `API_BENCH_MAX_RSS_GROWTH_MB`.
70
+
71
+ ## Required output (done-message)
72
+
73
+ **Success:**
74
+
75
+ ```
76
+ ✅ Verified: 🧪 lint ✓ · 🧪 test ✓ <N>p/<M>s · 🧩 test-integration ✓ (or N/A — no handler/schema/redis) · 🎯 cross-compile ✓ (zig only)
77
+ ```
78
+
79
+ **Failure (any required target failed):**
80
+
81
+ ```
82
+ 🔴 NOT VERIFIED: <target> ✗ — <one-line reason>
83
+ ```
84
+
85
+ **Skipped (environment constraint, not a pass):**
86
+
87
+ ```
88
+ 🟠 <target> skipped per environment constraint (reason: ...)
89
+ ```
90
+
91
+ A skipped target MUST be surfaced — never dressed up as "tests pass".
92
+
93
+ ## PR description results table
94
+
95
+ Before opening/updating the PR at CHORE(close), the PR/MR description carries a
96
+ ✅/❌ results table covering the skill chain (`/orly-write-unit-test` ·
97
+ `/orly-write-integration-test` or its recorded N/A · `/review`) and the verification
98
+ lanes above — **all ✅ (or an explicit recorded N/A/skip) required**. A lane
99
+ missing from the table counts as ❌.
100
+
101
+ ## Emoji legend
102
+
103
+ | Glyph | Meaning |
104
+ |---|---|
105
+ | ✅ | Verified — all required targets passed |
106
+ | 🔴 | Verification failed — at least one target failed |
107
+ | 🟠 | Skipped per environment constraint — read the reason |
108
+ | 🧪 | Lint / unit / integration test |
109
+ | 🧩 | Integration test (cross-process) |
110
+ | 🎯 | Cross-compile target |
111
+ | 🔆 | Informational note (does not affect verdict) |