diff --git a/.oracle/orly.json b/.oracle/orly.json index 3f586e8..4aeb7ea 100644 --- a/.oracle/orly.json +++ b/.oracle/orly.json @@ -1,6 +1,6 @@ { "schema_version": 1, - "orly_version": "0.6.4", + "orly_version": "0.6.8", "packs": [ "universal.authoring", "language.zig", diff --git a/AGENTS.md b/AGENTS.md index 71c9ddf..9e9ebf3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -144,6 +144,7 @@ Guards fire pre-hoc regardless of lifecycle stage. Override: `: SKIPPED pe | write auth-flow / token-minting files | `write_auth` | `dispatch/write_auth.md` β€” auth invariants; reads the product repo's `docs/AUTH.md` before Β· 🟣 delegated (product repo). | | write published docs / OpenAPI prose | `write_documentation` | `dispatch/write_documentation.md` β†’ `docs/DOCUMENTATION_RULES.md` before narrower guides; page, fragment, API, changelog scopes differ Β· 🟣 delegated to repository pre-commit checks. | | write a changelog entry | `write_changelog` | `dispatch/write_changelog.md` β€” changelog voice (one headline, no marketing words, `**Bold lead-noun**` bullets, history append-only); reads `docs/CHANGELOG_VOICE.md` Β· πŸ€” judgment-only. | +| write/update a PR or MR body or its session notes | `write_pr_description` | `dispatch/write_pr_description.md` β€” append numbered `Session notes`, `Review`, and `Make`; measured fenced diagrams; review dispositions; commands with real output. | | claim "tests pass / ready / shipping" | `verify` | `dispatch/verify.md` β€” verification tiers (`make` canonical; package-scoped runners are **not** verification), done-message glyph format Β· πŸ€” judgment-only, `VERIFY GATE: skipped per environment constraint (reason: ...)` only when genuinely unrunnable. | | name a stream/channel/Redis namespace/queue/RPC/Postgres schema, or describe a flow | `name_architecture` | `dispatch/name_architecture.md` β€” architecture-consult discipline; grep relevant `docs/architecture/` (chat brainstorming counts) Β· **no override** β€” doc wins until reconciled. | | run a lifecycle stage (openβ†’close a stream, worktree setup, milestone bootstrap) | `lifecycle` | `dispatch/lifecycle.md` β€” stage runbooks: CHORE(open/close) checklists, PLAN expansions, spec discipline, deferral format, pre-PR gates, LAND Β· πŸ€” judgment-only. | @@ -240,7 +241,7 @@ Required when spec involved β€” after last COMMIT, before PR. Also runs when par **PR budget β€” one per milestone.** One ready PR plus one follow-up is the ceiling. Fold new scope into the open PR (reopen `done/`β†’`active/` if needed), not a third. -**Required outputs** β€” full checklist in `dispatch/lifecycle.md`: all Dimensions/Sections `DONE` (`IN_PROGRESS` if parked) Β· spec β†’ `docs/v*/done/` iff complete Β· new changelog `` **and** the affected `~/Projects/docs/` pages revised Β· `docs/architecture/**` diff or Session-Notes why-not Β· PR `## Session notes` (decisions, deferrals, skill + babysit outcomes) Β· orphan sweep (RULE ORP) Β· ephemeral `HANDOFF*` docs deleted Β· `git status -uall` audit, **empty post-commit** before the PR Β· version sync (`make check-version` passes). +**Required outputs** β€” full checklist in `dispatch/lifecycle.md`: all Dimensions/Sections `DONE` (`IN_PROGRESS` if parked) Β· spec β†’ `docs/v*/done/` iff complete Β· new changelog `` **and** the affected `~/Projects/docs/` pages revised Β· `docs/architecture/**` diff or Session-Notes why-not Β· PR body per `dispatch/write_pr_description.md` Β· orphan sweep (RULE ORP) Β· ephemeral `HANDOFF*` docs deleted Β· `git status -uall` audit, **empty post-commit** before the PR Β· version sync (`make check-version` passes). **Deferral discipline.** A "deferred to follow-up" claim requires an **user-acked verbatim quote** in PR Session Notes (or spec Discovery); agent-unilateral deferral = incomplete scope, not deferral β€” CHORE(close) blocks until the item lands or the quote is captured. Quote format + HANDOFF faithfulness: `dispatch/lifecycle.md`. diff --git a/audits/agents-md.md b/audits/agents-md.md index adc7a62..6645d1c 100644 --- a/audits/agents-md.md +++ b/audits/agents-md.md @@ -269,7 +269,7 @@ The questionnaire is organised by scenario. Each scenario corresponds to a momen This scenario exists because the most likely failure of the operating model is not a missing rule β€” it's the *agent misreading a rule that is present*. -AGENTS.md is ~32 KB of table-dense, exception-laden prose (SOUL.md inlined); the conditions +AGENTS.md is byte-capped, table-dense prose (SOUL.md inlined); the conditions below are where an LLM reading it tends to drift, conflate, or confabulate. The questions force *proof of reading* over *recall*. @@ -366,6 +366,18 @@ than only the one with a Read hook. | 28.3 | Does the DOC READ GATE require recording each triggered read with `bash audits/doc-read.sh log ` β€” runnable in every runtime, automatic in Claude Code via the `PostToolUse` Read hook β€” with `.githooks/pre-commit` comparing the record against the staged diff? | YES | | 28.4 | When no read record exists (a runtime without hook support, before the command is run), does `audits/doc-read.sh check` warn 🟠 and exit 0 rather than red β€” because a check that fires where it cannot work teaches people to ignore it? | YES | +### Scenario 29 β€” Pull-request and merge-request descriptions + +Pull Request (PR) and Merge Request (MR) bodies use the same shape on both +forges. + +| # | Question | Expected | +|---|---|---| +| 29.1 | Does writing or updating a PR/MR body through either `gh` or `glab` route to `dispatch/write_pr_description.md`? | YES | +| 29.2 | Must each working session re-read the forge body, append the highest numbered `## Session notes ` plus one followed by `## Review` and `## Make`, and preserve every earlier unit? | YES | +| 29.3 | Does the faΓ§ade require two or three outcome-first prose lines, useful fenced ASCII diagrams at most 78 columns using measured values, P0/P1/P2 review dispositions, and commands paired with actual output? | YES | +| 29.4 | Must clean review say `No findings.`, skipped review and verification name why, and unverified claims identify what would verify them? | YES | + ## Comprehension layer The deterministic audit proves the rules are *present*; it cannot prove an @@ -457,6 +469,8 @@ Scenario verdicts: | 25 | Allocator and concurrency discipline | | | 26 | Rules propagation | | | 27 | Rule-path residence and reachability | | +| 28 | Rule-enforcement ledger and doc reads | | +| 29 | PR and MR descriptions | | OVERALL: PASS | FAIL β€” ``` diff --git a/audits/data.sh b/audits/data.sh index 67d1e14..f1c1c67 100644 --- a/audits/data.sh +++ b/audits/data.sh @@ -45,7 +45,7 @@ REQUIRED_DISPATCH=( "write_spec" "write_http" "write_auth" "write_changelog" "write_documentation" "verify" "name_architecture" "edit_rules" "write_rust" "write_go" "write_python" "write_shell" "write_mdx" - "lifecycle" + "write_pr_description" "lifecycle" ) # Check 2 β€” every source/config language has at least one mention. @@ -105,6 +105,7 @@ DOTFILES_RESIDENT=( "dispatch/write_auth.md" "dispatch/write_changelog.md" "dispatch/write_documentation.md" + "dispatch/write_pr_description.md" "dispatch/verify.md" "dispatch/name_architecture.md" "dispatch/edit_rules.md" @@ -169,6 +170,7 @@ NAMED_SCENARIOS=( "Rules propagation" # Scenario 26 "Rule-path" # Scenario 27 "Rule-enforcement ledger" # Scenario 28 + "Pull-request and merge-request descriptions" # Scenario 29 ) # Check 14 β€” the Rule-extension protocol must enumerate all four wiring steps. diff --git a/core/operating-model.md b/core/operating-model.md index 5a40166..ebeac2e 100644 --- a/core/operating-model.md +++ b/core/operating-model.md @@ -148,6 +148,7 @@ Guards fire pre-hoc regardless of lifecycle stage. Override: `: SKIPPED pe | write auth-flow / token-minting files | `write_auth` | `dispatch/write_auth.md` β€” auth invariants; reads the product repo's `docs/AUTH.md` before Β· 🟣 delegated (product repo). | | write published docs / OpenAPI prose | `write_documentation` | `dispatch/write_documentation.md` β†’ `docs/DOCUMENTATION_RULES.md` before narrower guides; page, fragment, API, changelog scopes differ Β· 🟣 delegated to repository pre-commit checks. | | write a changelog entry | `write_changelog` | `dispatch/write_changelog.md` β€” changelog voice (one headline, no marketing words, `**Bold lead-noun**` bullets, history append-only); reads `docs/CHANGELOG_VOICE.md` Β· πŸ€” judgment-only. | +| write/update a PR or MR body or its session notes | `write_pr_description` | `dispatch/write_pr_description.md` β€” append numbered `Session notes`, `Review`, and `Make`; measured fenced diagrams; review dispositions; commands with real output. | | claim "tests pass / ready / shipping" | `verify` | `dispatch/verify.md` β€” verification tiers (`make` canonical; package-scoped runners are **not** verification), done-message glyph format Β· πŸ€” judgment-only, `VERIFY GATE: skipped per environment constraint (reason: ...)` only when genuinely unrunnable. | | name a stream/channel/Redis namespace/queue/RPC/Postgres schema, or describe a flow | `name_architecture` | `dispatch/name_architecture.md` β€” architecture-consult discipline; grep relevant `docs/architecture/` (chat brainstorming counts) Β· **no override** β€” doc wins until reconciled. | | run a lifecycle stage (openβ†’close a stream, worktree setup, milestone bootstrap) | `lifecycle` | `dispatch/lifecycle.md` β€” stage runbooks: CHORE(open/close) checklists, PLAN expansions, spec discipline, deferral format, pre-PR gates, LAND Β· πŸ€” judgment-only. | @@ -255,7 +256,7 @@ Required when spec involved β€” after last COMMIT, before PR. Also runs when par **PR budget β€” one per milestone.** One ready PR plus one follow-up is the ceiling. Fold new scope into the open PR (reopen `done/`β†’`active/` if needed), not a third. -**Required outputs** β€” full checklist in `dispatch/lifecycle.md`: all Dimensions/Sections `DONE` (`IN_PROGRESS` if parked) Β· spec β†’ `docs/v*/done/` iff complete Β· new changelog `` **and** the affected `~/Projects/docs/` pages revised Β· `docs/architecture/**` diff or Session-Notes why-not Β· PR `## Session notes` (decisions, deferrals, skill + babysit outcomes) Β· orphan sweep (RULE ORP) Β· ephemeral `HANDOFF*` docs deleted Β· `git status -uall` audit, **empty post-commit** before the PR Β· version sync (`make check-version` passes). +**Required outputs** β€” full checklist in `dispatch/lifecycle.md`: all Dimensions/Sections `DONE` (`IN_PROGRESS` if parked) Β· spec β†’ `docs/v*/done/` iff complete Β· new changelog `` **and** the affected `~/Projects/docs/` pages revised Β· `docs/architecture/**` diff or Session-Notes why-not Β· PR body per `dispatch/write_pr_description.md` Β· orphan sweep (RULE ORP) Β· ephemeral `HANDOFF*` docs deleted Β· `git status -uall` audit, **empty post-commit** before the PR Β· version sync (`make check-version` passes). **Deferral discipline.** A "deferred to follow-up" claim requires an **user-acked verbatim quote** in PR Session Notes (or spec Discovery); agent-unilateral deferral = incomplete scope, not deferral β€” CHORE(close) blocks until the item lands or the quote is captured. Quote format + HANDOFF faithfulness: `dispatch/lifecycle.md`. diff --git a/dispatch/write_pr_description.md b/dispatch/write_pr_description.md new file mode 100644 index 0000000..0c53225 --- /dev/null +++ b/dispatch/write_pr_description.md @@ -0,0 +1,152 @@ +# Pull-request and merge-request description dispatch + +Read this file before writing or updating a Pull Request (PR) or Merge Request +(MR) body, including an update that only appends session notes. It governs +GitHub and GitLab equally. + +## Trigger + +This dispatch fires before any forge command or API call that creates or changes +a PR or MR body. This includes `gh pr create`, `gh pr edit --body`, +`glab mr create`, and `glab mr update --description`. A helper, skill, or script +that writes the body fires the same rule. + +## Append unit and sequence + +Append exactly one complete unit per working session that touches the PR or MR, +after review and verification have finished: + +1. `## Session notes ` +2. `## Review` +3. `## Make` + +Read the complete existing body before composing the unit. Find every heading +that exactly matches `## Session notes `. Use 1 when none exists; +otherwise use the highest integer plus 1. Re-read the body immediately before +the write and recompute the number if another session appended meanwhile. The +forge body is the source of truth; chat, a local draft, and commit count are not. + +Append the unit once, preserving every earlier numbered unit. Never renumber, +rewrite, reorder, or consolidate earlier units. Build the complete unit locally +and make one body update so Review and Make cannot be mistaken for missing. + +For GitHub, read with `gh pr view --json body --jq .body` and write with +`gh pr edit --body` or `--body-file`. For GitLab, read with +`glab mr view --output json --jq .description` and write with +`glab mr update --description`. Preserve all body content that precedes the +first numbered unit. + +## Session notes + +Start with two or three lines of plain prose, never more. Lead with what was +fixed. Include decisions and open deferrals that the next agent needs. Do not +add a preamble or restate the ticket. + +Follow with a pictorial explanation using American Standard Code for +Information Interchange (ASCII) diagrams in fenced code blocks. The picture is +the substance when it can show a before/after, topology, proportion, measured +scale, or broken flow more clearly than a sentence. Use the sentence when it is +clearer. Never draw a box that merely repeats its caption. + +Every diagram must: + +- stay at or below 78 columns, including indentation; +- be inside a fence so both forges render it monospaced; +- label axes and units where they exist; +- use measured values copied from real command output, never illustrative + values. + +These are real examples from a test-hardening PR. Copy their register, never +their numbers: + +```text + BEFORE AFTER + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ 671 tests ........ PASS β”‚ β”‚ 671 tests ........ PASS β”‚ + β”‚ incl. all 5 properties β”‚ β”‚ scope property ... FAIL βœ“β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + a live cross-tenant read the mutant is caught + ships green +``` + +```text + compiler accepts 16 keys generator emitted 8 + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β”‚ BEFORE 50% β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +```text + 0.001ms 0.01 0.1 1 10 100 + β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ + β–² β–² β–² β–² + cache HIT NEW budget OLD budget cache MISS + 0.003-0.005ms 0.1ms 1.0ms 12-21ms +``` + +## Review + +Lead with the review result. Record every finding with P0, P1, or P2 severity, +the file and line, the defect, and its disposition. Use `FIXED` or `DEFERRED`; +a deferral also needs the user acknowledgement required by the lifecycle rule. + +```text +P0 oql_property_tests.rs:86 tenant-scope property asserted absence only β€” + passed with the scope clause deleted. FIXED +P1 query_load_test.rs:183 only assertion was arithmetic, green at any + latency. FIXED +P2 grpc_auth_test.rs:33 constant re-typed instead of imported. DEFERRED +``` + +Write `No findings.` when review ran and found none. If review did not run, +write `Review not run β€” .` A missing heading never means clean. + +## Make + +Lead with the verification state. List each command actually run with its exit +status and decisive output line. Use measured counts and baselines from that +run; never replace output with β€œtests pass.” + +```text +make test exit 0 860 passed; 0 failed (baseline 846, +14) +cargo clippy --all-targets -- -D warnings exit 0 +make harness-verify All checks passed! +gitleaks no leaks found, 54 commits scanned +``` + +For every command that could not run, name the command and the reason. Label +the evidence source when it is not Continuous Integration (CI), such as +`local β€” real stack`. Include the review skill and `orly-babysit-prs` command +outcomes here; if either could not run, name why. Never present a local run as +a green pipeline. + +## Whole-body rules + +- Every factual claim traces to an actual command output line in Make or to a + command-named measurement in the diagram. State unchecked facts as + `Unverified: β€” `. +- Lead with the answer in each section. Put reasoning after it and detail last. +- Use no marketing adjectives, throat-clearing opener, or closing paragraph + that repeats the body. +- Write for the next agent first: branch state, decisions, and open work must + be findable without reconstructing the session. + +## Complete template + +````markdown +## Session notes + + + +```text + +``` + +## Review + + + +## Make + + +```` diff --git a/docs/EXECUTE_DOC_READS.md b/docs/EXECUTE_DOC_READS.md index 1148066..be678a6 100644 --- a/docs/EXECUTE_DOC_READS.md +++ b/docs/EXECUTE_DOC_READS.md @@ -25,5 +25,6 @@ Every triggered document requires one `πŸ“– DOC READ: ` proof-line **per t | Auth-flow | `docs/AUTH.md`. | | Published `*.mdx`, reusable Markdown JSX (MDX) fragment, customer readme, or public OpenAPI prose | `dispatch/write_documentation.md` β†’ `docs/DOCUMENTATION_RULES.md` β€” establish page, fragment, API, or changelog scope before narrower guides. | | Changelog `` / release note (`changelog.mdx`) | First `dispatch/write_documentation.md`, then `dispatch/write_changelog.md` β†’ `docs/CHANGELOG_VOICE.md`; internal-only β‡’ no entry. | +| Write or update a PR/MR body, including session notes (`gh pr create/edit --body`, `glab mr create/update --description`, forge API, helper, or skill) | `dispatch/write_pr_description.md` β€” append-only numbered session unit, measured diagram, review findings, and command output. | | `schema/*.sql` / migration | `dispatch/write_sql.md` + `docs/SCHEMA_CONVENTIONS.md` β€” naming/type conventions, schema/migration rules + Schema Table Removal Guard. Re-print Schema Guard output. | | Any spec under `docs/v*/{pending,active,done}/` or `docs/TEMPLATE.md` | `docs/TEMPLATE.md` "Prohibited" section β€” no time/effort estimates, no complexity ratings, no percentage-complete, no owners/dates. SPEC TEMPLATE GATE per edit. | diff --git a/package.json b/package.json index 37b144f..d4de1aa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@agentsfleet/orly", - "version": "0.6.7", + "version": "0.6.8", "description": "Repository-scoped engineering harness: renders agent rules, materialises the gates that enforce them, and proves the PR boundary \u2014 for any coding agent.", "license": "MIT", "type": "module", diff --git a/registry.json b/registry.json index 1676f90..49822bb 100644 --- a/registry.json +++ b/registry.json @@ -32,6 +32,10 @@ "source": "dispatch/name_architecture.md", "target": "dispatch/name_architecture.md" }, + { + "source": "dispatch/write_pr_description.md", + "target": "dispatch/write_pr_description.md" + }, { "source": "audits/ufs.sh", "target": "audits/ufs.sh"