@agentsfleet/orly 0.10.13 → 0.11.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.
- package/.githooks/pre-push +2 -1
- package/AGENTS.md +21 -31
- package/README.md +65 -29
- package/SOUL.md +13 -23
- package/audits/agents-md.md +67 -57
- package/audits/deinit-pairs.sh +13 -18
- package/audits/design-tokens.sh +9 -23
- package/audits/doc-read.sh +10 -33
- package/audits/doc-reads.ts +41 -0
- package/audits/error-codes.sh +18 -25
- package/audits/logging-rust.awk +145 -0
- package/audits/logging.sh +10 -166
- package/audits/msid-ui.sh +45 -18
- package/audits/rule-ledger-lib.sh +9 -6
- package/audits/rust-error.sh +20 -15
- package/audits/scope.sh +88 -0
- package/audits/spec-template.sh +2 -2
- package/audits/spec-template.ts +1 -1
- package/audits/sql-mod.sh +11 -14
- package/audits/ufs-strings.awk +164 -0
- package/audits/ufs.sh +10 -188
- package/core/operating-model.md +8 -8
- package/dispatch/edit_rules.md +8 -6
- package/dispatch/lib.sh +41 -26
- package/dispatch/lifecycle.md +18 -6
- package/dispatch/name_architecture.md +8 -3
- package/dispatch/verify.md +1 -1
- package/dispatch/write_any.md +10 -3
- package/dispatch/write_changelog.md +7 -4
- package/dispatch/write_go.md +1 -1
- package/dispatch/write_http.md +5 -7
- package/dispatch/write_python.md +1 -1
- package/dispatch/write_rust.md +17 -1
- package/dispatch/write_shell.md +1 -1
- package/dispatch/write_spec.md +3 -1
- package/dispatch/write_sql.md +28 -6
- package/dispatch/write_ts_adhere_bun.md +11 -0
- package/dispatch/write_zig.md +53 -21
- package/docs/CHANGELOG_VOICE.md +11 -2
- package/docs/EXECUTE_DOC_READS.md +10 -10
- package/docs/HARNESS_VERIFY_OUTPUT.md +6 -3
- package/docs/JUDGMENTS.md +153 -0
- package/docs/LIFECYCLE_PATTERNS.md +26 -16
- package/docs/LOGGING_STANDARD.md +39 -19
- package/docs/ORLY_ARCHITECTURE.md +77 -6
- package/docs/RELEASE_TEMPLATE.md +21 -5
- package/docs/REST_API_DESIGN_GUIDELINES.md +86 -21
- package/docs/RULE_ENFORCEMENT.md +6 -6
- package/docs/SCHEMA_CONVENTIONS.md +24 -3
- package/docs/TEMPLATE.md +4 -4
- package/docs/VERIFY_TIERS.md +2 -2
- package/docs/greptile-learnings/RULES.md +81 -26
- package/llms.txt +37 -34
- package/package.json +6 -1
- package/packs/language/go/rules.md +1 -1
- package/packs/language/python/rules.md +1 -1
- package/packs/language/rust/rules.md +17 -1
- package/packs/language/shell/rules.md +1 -1
- package/registry.json +22 -7
- package/schemas/profile.schema.json +48 -5
- package/skills/orly-babysit-prs/SKILL.md +87 -34
- package/skills/orly-spec-new/SKILL.md +19 -6
- package/skills/orly-write-integration-test/SKILL.md +4 -4
- package/skills/orly-write-unit-test/SKILL.md +10 -1
- package/src/cli.test.ts +2 -2
- package/src/cli.ts +19 -75
- package/src/cli_help.ts +69 -0
- package/src/command_limits.ts +20 -0
- package/src/command_process.test.ts +109 -0
- package/src/command_process.ts +88 -0
- package/src/command_runner.test.ts +88 -0
- package/src/command_runner.ts +33 -0
- package/src/comprehension_cache.test.ts +123 -0
- package/src/config.test.ts +5 -4
- package/src/config.ts +26 -164
- package/src/config_discovery.ts +159 -0
- package/src/config_validation.test.ts +56 -0
- package/src/config_validation.ts +25 -0
- package/src/criteria.test.ts +1 -1
- package/src/criteria.ts +10 -26
- package/src/criteria_spec.ts +12 -20
- package/src/criteria_support.ts +2 -19
- package/src/doc_reads.test.ts +42 -0
- package/src/doc_rules.ts +2 -2
- package/src/evaluation_resources.test.ts +64 -0
- package/src/execution/config.ts +22 -0
- package/src/execution/plan.test.ts +65 -0
- package/src/execution/plan.ts +51 -0
- package/src/gates.ts +39 -24
- package/src/gates_spec.test.ts +110 -4
- package/src/gates_test_support.ts +9 -7
- package/src/install.test.ts +38 -222
- package/src/install.ts +117 -308
- package/src/install_loaders.test.ts +203 -0
- package/src/install_nested.test.ts +2 -2
- package/src/install_packs.test.ts +66 -6
- package/src/installation/hooks.ts +63 -0
- package/src/installation/lock.test.ts +97 -0
- package/src/installation/lock.ts +56 -0
- package/src/installation/migration.test.ts +212 -0
- package/src/installation/migration.ts +65 -0
- package/src/installation/plan.ts +96 -0
- package/src/installation/transaction.ts +126 -0
- package/src/installation_preservation.test.ts +48 -0
- package/src/judgments/advice.test.ts +38 -0
- package/src/judgments/advice.ts +32 -0
- package/src/judgments/command.integration.test.ts +47 -0
- package/src/judgments/command.ts +90 -0
- package/src/judgments/constants.ts +55 -0
- package/src/judgments/evidence.test.ts +48 -0
- package/src/judgments/evidence.ts +34 -0
- package/src/judgments/files.test.ts +62 -0
- package/src/judgments/files.ts +73 -0
- package/src/judgments/questions.test.ts +19 -0
- package/src/judgments/questions.ts +85 -0
- package/src/judgments/replay.test.ts +43 -0
- package/src/judgments/replay.ts +66 -0
- package/src/judgments/runner.integration.test.ts +165 -0
- package/src/judgments/runner.ts +97 -0
- package/src/judgments/scan.test.ts +19 -0
- package/src/judgments/scan.ts +40 -0
- package/src/judgments/syntax.test.ts +115 -0
- package/src/judgments/syntax.ts +71 -0
- package/src/judgments/syntax_worker.ts +70 -0
- package/src/judgments/test_support.ts +60 -0
- package/src/judgments/transport.integration.test.ts +63 -0
- package/src/judgments/transport.ts +35 -0
- package/src/judgments/types.test.ts +43 -0
- package/src/judgments/types.ts +66 -0
- package/src/judgments/wire.test.ts +48 -0
- package/src/judgments/wire.ts +40 -0
- package/src/loaders.test.ts +13 -16
- package/src/loaders.ts +28 -10
- package/src/model.test.ts +20 -3
- package/src/model.ts +7 -18
- package/src/pack_hygiene.test.ts +42 -1
- package/src/pack_hygiene.ts +18 -8
- package/src/references.ts +15 -7
- package/src/release_inventory.test.ts +80 -0
- package/src/render.test.ts +1 -1
- package/src/render.ts +3 -8
- package/src/required_scanner.test.ts +36 -0
- package/src/review_poll.test.ts +158 -0
- package/src/scanner_scope.test.ts +202 -0
- package/src/setup.test.ts +9 -6
- package/src/spec_baseline.test.ts +1 -1
- package/src/spec_completion.test.ts +74 -0
- package/src/spec_obligations.ts +64 -0
- package/src/spec_rehearsal.test.ts +182 -0
- package/src/spec_template_io.test.ts +11 -9
- package/src/surfaces.test.ts +2 -0
- package/src/surfaces.ts +1 -1
- package/src/validation.ts +7 -4
- package/src/verify.test.ts +18 -2
- package/src/verify.ts +7 -3
|
@@ -280,6 +280,16 @@ immediately preceding the edit. **User-invokable only.** Generic "scope creep" /
|
|
|
280
280
|
- Length caps live in `dispatch/write_any.md` (LENGTH GATE — file ≤ 350, fn ≤ 50, method ≤ 70 — same as every other source language).
|
|
281
281
|
- This file is the **TypeScript / Bun-specific** layer that those universal rules cannot express. Scan its section headers at the first TS/JS touch (`grep -nE "^##+ "` — two-plus hashes, so nested cards surface) and read the sections the diff shape touches; on sub-task shape change, re-scan and read only newly-touched sections — never the full file.
|
|
282
282
|
|
|
283
|
+
## Repository design system
|
|
284
|
+
|
|
285
|
+
> [JUDGMENT → ARCH]
|
|
286
|
+
|
|
287
|
+
Use the consuming repository's declared component library and design tokens.
|
|
288
|
+
Locate its exports and styles before substituting primitives; do not import
|
|
289
|
+
another product's package or invent its directory layout.
|
|
290
|
+
Run the repository's declared checks and review substitutions against that source.
|
|
291
|
+
|
|
292
|
+
<!-- oracle-packs:start product.agentsfleet -->
|
|
283
293
|
## Merged from dissolved gate cards
|
|
284
294
|
|
|
285
295
|
> [container]
|
|
@@ -491,3 +501,4 @@ If the arbitrary you want is a legitimate design value that simply has no token
|
|
|
491
501
|
4. Add the utility to the table above in this gate body (same dotfiles commit — Invariance Suite Gate applies)
|
|
492
502
|
|
|
493
503
|
This is the path to a system that grows without dilution.
|
|
504
|
+
<!-- oracle-packs:end -->
|
package/dispatch/write_zig.md
CHANGED
|
@@ -31,13 +31,15 @@ Status: Canonical Zig source of truth for agents and commits
|
|
|
31
31
|
|
|
32
32
|
> [JUDGMENT → ARCH]
|
|
33
33
|
|
|
34
|
-
For every commit
|
|
34
|
+
For every commit touching Zig, run the workflow below alongside the repository's
|
|
35
|
+
declared conformance and verification commands. The reviewer owns the rules
|
|
36
|
+
those commands cannot mechanically check.
|
|
35
37
|
|
|
36
38
|
1. **Before write (trigger: about to edit / create `*.zig`):** scan this façade's section headers (`grep -n "^## " dispatch/write_zig.md`). Re-read any section whose topic the diff touches: concurrency for atomics / threads, allocator-ownership for new structs, doc-comments for new `pub` types, comptime assertions for new invariants, single-type-module pattern for new file structure, etc.
|
|
37
39
|
|
|
38
40
|
2. **During write:** for each surfaced uncertainty (atomic ordering choice, allocator pattern, naming, structural choice), state the rule and the choice in chat — don't decide silently.
|
|
39
41
|
|
|
40
|
-
3. **Before commit (
|
|
42
|
+
3. **Before commit (after declared conformance):** inspect the staged diff for rules the repository's checks do not enforce. Comply or record an explicitly authorized exception.
|
|
41
43
|
- Weak atomic orderings (`\.\(acquire\|release\|monotonic\|unordered\)\b`) — every match needs a `// safe because: ...` comment within 3 lines.
|
|
42
44
|
- New `pub` symbols — confirm at least one external import via `grep -rn "<symbol>"`. Remove `pub` if unreferenced.
|
|
43
45
|
- New structs that own heap memory — confirm `alloc:` field OR doc-comment naming the caller-owned-allocator pattern.
|
|
@@ -55,15 +57,15 @@ For every commit that touches `*.zig`, the agent runs the workflow below — no
|
|
|
55
57
|
|
|
56
58
|
> [DETERMINISTIC → TODO-CHECK]
|
|
57
59
|
|
|
58
|
-
- Run
|
|
59
|
-
- Run
|
|
60
|
+
- Run the repository's declared conformance and verification commands and required secret scanner before committing Zig changes.
|
|
61
|
+
- Run its database-backed integration lane with its declared test configuration when touching database behavior.
|
|
60
62
|
- Read this file before creating any new `*.zig` file.
|
|
61
63
|
- Use `conn.exec()` for INSERT / UPDATE / DDL whenever possible.
|
|
62
64
|
- Drain early-exit `conn.query()` results before `deinit()`.
|
|
63
65
|
- Copy row-backed slices before `q.drain()` or `q.deinit()`.
|
|
64
66
|
- Materialize rows into owned memory before issuing writes on the same `pg.Conn`.
|
|
65
67
|
- Keep temp-table fixtures aligned with the real production write contract.
|
|
66
|
-
-
|
|
68
|
+
- Match container initialization and allocator calls to the repository's pinned Zig version; read that version's implementation before changing the shape.
|
|
67
69
|
- Use `q.*.next()` and `q.*.drain()` when the query result is passed through `anytype` as a pointer (`&q`). Direct local vars use `q.next()`.
|
|
68
70
|
- Reference nested struct types with the full path: `Module.Struct.NestedType`, not `Module.NestedType`.
|
|
69
71
|
- Add new test files to test discovery. Either `_ = @import("path/to/new_file.zig");` in `main.zig`'s test block, or — preferred when a façade already exists — in a `test {}` block inside the façade (`test { _ = @import("foo_test.zig"); }`). Zig strips `test {}` blocks in release builds, so this adds zero bytes to the production binary. The façade pattern keeps `main.zig` at a flat one-line-per-module list and lets each module own its own test discovery.
|
|
@@ -99,12 +101,18 @@ For every commit that touches `*.zig`, the agent runs the workflow below — no
|
|
|
99
101
|
|
|
100
102
|
> [DETERMINISTIC → PUB]
|
|
101
103
|
|
|
104
|
+
Use the repository's selected linter and preserve its unused-public-symbol
|
|
105
|
+
checks. If it has no such checker, review public consumers explicitly;
|
|
106
|
+
installing this language pack does not select a linter version.
|
|
107
|
+
|
|
108
|
+
<!-- oracle-packs:start product.agentsfleet -->
|
|
102
109
|
- This repo uses `zlint` as part of `make lint`.
|
|
103
110
|
- Pinned version: `v0.9.0`.
|
|
104
111
|
- **`unused-decls: error` is load-bearing.** PUB GATE (the pub-surface section of this façade) delegates mechanical consumer-grep to this rule — a `pub` without an in-tree consumer fails `make lint`. Disabling or downgrading it silently bypasses half the gate; if you must, amend PUB GATE in the same diff so the design call is captured elsewhere.
|
|
105
112
|
- `suppressed-errors` stays off because this repo intentionally uses narrow `pg` cleanup patterns that a generic rule cannot classify correctly.
|
|
106
113
|
- `unsafe-undefined` is a good future tightening target once current low-level uses are cleaned up or annotated.
|
|
107
114
|
- A disabled ZLint is not useful; prefer a scoped ruleset that passes today and tightens over time.
|
|
115
|
+
<!-- oracle-packs:end -->
|
|
108
116
|
|
|
109
117
|
## Memory Safety Rules
|
|
110
118
|
|
|
@@ -262,10 +270,15 @@ fix it in the same commit. No spec needed — these are incremental improvements
|
|
|
262
270
|
- Decide ownership before writing helpers: allocator, free/deinit path, and whether data is owned or borrowed.
|
|
263
271
|
- If the file touches `pg`, apply the query lifecycle rules above before writing the first helper.
|
|
264
272
|
|
|
265
|
-
## HTTP Integration Tests
|
|
273
|
+
## HTTP Integration Tests
|
|
266
274
|
|
|
267
275
|
> [JUDGMENT → ARCH]
|
|
268
276
|
|
|
277
|
+
Use the repository's shared HTTP harness and real schema fixtures.
|
|
278
|
+
Register new tests in its discovery graph and keep setup and cleanup owned by
|
|
279
|
+
each test. Do not assume another product's harness or environment variable.
|
|
280
|
+
|
|
281
|
+
<!-- oracle-packs:start product.agentsfleet -->
|
|
269
282
|
Canonical source: `src/http/test_harness.zig`. Every `*_http_integration_test.zig` under `src/http/` MUST consume it.
|
|
270
283
|
|
|
271
284
|
- **Do not** define a local `TestServer` / `RunningServer` struct, local `startTestServer()` / `startServer()`, local `sendReq()` / `sendRequest()`, or local `waitForServer()`. These are provided by `TestHarness` with a fluent Request/Response API.
|
|
@@ -274,17 +287,17 @@ Canonical source: `src/http/test_harness.zig`. Every `*_http_integration_test.zi
|
|
|
274
287
|
- **Test fixtures live in a sibling `*_test_fixtures.zig`** beside the integration file, or in a shared fixture module — not inlined. See `src/http/webhook_test_fixtures.zig` for the pattern.
|
|
275
288
|
- **Skip gracefully when DB is absent** — `TestHarness.start` returns `error.SkipZigTest` when `TEST_DATABASE_URL` is unset; tests just propagate it.
|
|
276
289
|
- New file registration: add `_ = @import("..._test.zig")` to the `test {}` block at the bottom of `src/http/server.zig` (not `src/main.zig`). Integration tests discover from there.
|
|
290
|
+
<!-- oracle-packs:end -->
|
|
277
291
|
|
|
278
292
|
## Commands
|
|
279
293
|
|
|
280
294
|
> [DETERMINISTIC → TODO-CHECK]
|
|
281
295
|
|
|
282
|
-
- `
|
|
283
|
-
-
|
|
284
|
-
-
|
|
285
|
-
- `gitleaks detect`
|
|
286
|
-
- Connection-drain audit — a static check that every `conn.query()` has `.drain()` in the same function. Run the repository's lane for it when touching any file that calls `conn.query()`.
|
|
296
|
+
- Declared `conform` and applicable `verify.*` commands from `.orly/orly.json`.
|
|
297
|
+
- The repository's database integration configuration and required secret scanner.
|
|
298
|
+
- Query cleanup — drain every result before releasing its connection, including early exits. Use wrapper-owned draining where the repository provides it. Run any declared cleanup check and review the owner's cleanup path; no generic static check proves wrapper behavior.
|
|
287
299
|
|
|
300
|
+
<!-- oracle-packs:start product.agentsfleet -->
|
|
288
301
|
## Zig 0.15.2 API Gotchas (M3_001)
|
|
289
302
|
|
|
290
303
|
> [DETERMINISTIC → XCOMPILE]
|
|
@@ -293,17 +306,24 @@ Canonical source: `src/http/test_harness.zig`. Every `*_http_integration_test.zi
|
|
|
293
306
|
- `std.fmt.parseHex` does not exist. Use `std.fmt.hexToBytes(&out, hex_str)` to decode hex to bytes.
|
|
294
307
|
- `std.fmt.fmtSliceHexLower` does not exist. Use `std.fmt.bytesToHex(bytes, .lower)` to encode bytes to hex.
|
|
295
308
|
- When unsure about an API, check the codebase first: `grep -rn "ArrayList\|hexToBytes" src/ --include="*.zig"` to see how existing code uses it.
|
|
309
|
+
<!-- oracle-packs:end -->
|
|
296
310
|
|
|
297
311
|
## Cross-Compile Verification (M22_001)
|
|
298
312
|
|
|
299
313
|
> [DETERMINISTIC → XCOMPILE]
|
|
300
314
|
|
|
315
|
+
Compile the repository's declared platform matrix, including applicable test
|
|
316
|
+
graphs. Execute platform-specific tests on their declared supported runtime;
|
|
317
|
+
compilation alone does not prove runtime behavior.
|
|
318
|
+
|
|
319
|
+
<!-- oracle-packs:start product.agentsfleet -->
|
|
301
320
|
- Run `zig build -Dtarget=x86_64-linux && zig build -Dtarget=aarch64-linux` before every commit that touches Zig files. Do not rely on macOS-only compilation.
|
|
302
321
|
- **Production-binary targets alone do NOT catch Linux-gated drift.** Code inside `if (builtin.os.tag == .linux)` branches and test-only helpers is comptime-dead on a macOS target and never analysed in the production graph (M82 shipped green locally; three Linux-gated `std.fs.accessAbsolute` sites failed CI). For cross-platform changes, also compile the linux **test graphs**: `zig build test -Dtarget=x86_64-linux` + `zig build test-lib -Dtarget=x86_64-linux` + `zig build --build-file build_runner.zig test -Dtarget=x86_64-linux`. A clean compile ending only in `unable to execute binaries from the target` is the PASS signal.
|
|
303
322
|
- **Linux-gated tests compile but never RUN on macOS** (`SkipZigTest` off-linux) — a wrong runtime assertion slips through to CI (M84_007). To execute locally: cross-compile the test graph `-Dtarget=aarch64-linux`, take the static ELF from `.zig-cache/o/*/`, and run it in a **native arm64** container: `docker run --rm --platform linux/arm64 -v "$PWD:/w" -w /w debian:stable-slim /w/<binary>`. qemu-emulated x86_64 is a false oracle — its fork/clone emulation breaks tests that pass on real Linux. Note: prod children run under bwrap (closes non-passed fds), so bwrap-less tests must assert the *relative* fd property (child fds ⊆ parent), never absolute fd counts.
|
|
304
323
|
- `std.http.Client.open()` does not exist on Linux targets in Zig 0.15.2. Use `client.request()` + `response.reader()` + `readVec()` for cross-platform HTTP streaming.
|
|
305
324
|
- `std.Io.Reader` on Linux has `readVec()`, not `read()`. Use `readVec(&[_][]u8{&buf})` for single-buffer reads.
|
|
306
325
|
- Verify stdlib API existence by grepping: `grep -n "pub fn" ~/.local/share/mise/installs/zig/*/lib/std/http/Client.zig`
|
|
326
|
+
<!-- oracle-packs:end -->
|
|
307
327
|
|
|
308
328
|
## TLS Transport (M22_001)
|
|
309
329
|
|
|
@@ -496,7 +516,7 @@ Rules:
|
|
|
496
516
|
|
|
497
517
|
> [DETERMINISTIC → XCOMPILE]
|
|
498
518
|
|
|
499
|
-
- Verification runs the repository's DECLARED commands (`.
|
|
519
|
+
- Verification runs the repository's DECLARED commands (`.orly/orly.json`), never `zig build test` standalone. `zig build test` runs only the Zig unit set and silently skips every other language's tests and the cross-language gates the declared commands cover. Use `zig build` for compilation, never for "did my change pass tests".
|
|
500
520
|
- A memory-leak lane, where the repository declares one, is required when the diff touches server lifecycle, allocator wiring, or cross-thread heap ownership. The macOS `leaks` tool prints a "not debuggable" line under System Integrity Protection — that is expected; the authoritative signal is the allocator-leak phase across `std.testing.allocator`-wrapped tests.
|
|
501
521
|
|
|
502
522
|
## Doc-Comments and Inline Comments
|
|
@@ -530,7 +550,8 @@ Extends "Type Design Rules". Two patterns, both legitimate; pick deliberately an
|
|
|
530
550
|
|
|
531
551
|
> [DETERMINISTIC → TODO-CHECK]
|
|
532
552
|
|
|
533
|
-
- snake_case
|
|
553
|
+
- Use snake_case for Zig names. Match externally defined field spellings only at an explicit interoperability boundary.
|
|
554
|
+
- `agentsfleet` has no JavaScript interoperability boundary; its Zig fields stay snake_case. <!-- oracle-packs:product.agentsfleet -->
|
|
534
555
|
|
|
535
556
|
## RULE UFS — Named constants for repeated and semantic literals
|
|
536
557
|
|
|
@@ -641,8 +662,8 @@ paths never reach a global to allocate. Debug/test builds pick the leak-checking
|
|
|
641
662
|
Purpose Allocator (GPA); release picks the C allocator. Global state never holds the allocator
|
|
642
663
|
for a Zig path.
|
|
643
664
|
**Exemplar:** ghostty `global.zig:74-96` (allocator selection at `main`, Valgrind detected at
|
|
644
|
-
runtime).
|
|
645
|
-
|
|
665
|
+
runtime). Everything below the owner takes `alloc` as an argument.
|
|
666
|
+
In `agentsfleet`, `agentsfleetd/main.zig` and `runner/daemon/worker_pool.zig` own the GPA. <!-- oracle-packs:product.agentsfleet -->
|
|
646
667
|
|
|
647
668
|
### A2 — errdefer ladder: one errdefer immediately after each acquisition
|
|
648
669
|
|
|
@@ -831,20 +852,31 @@ PUB GATE and LIFECYCLE GATE answer different questions and neither defers to the
|
|
|
831
852
|
|
|
832
853
|
The init/deinit pairing audit treats all of `deinit`, `close`, `release`, `destroy`, `shutdown`, `dispose`, `free` as lifecycle (cleanup) methods. Renaming `deinit` to `close` or `release` does NOT bypass the pairing requirement — a struct owning heap memory or an opaque handle still needs an `init`-paired cleanup method under any of those names.
|
|
833
854
|
|
|
834
|
-
### Empty-pair and arena-
|
|
855
|
+
### Empty-pair and arena-lifetime review
|
|
835
856
|
|
|
836
|
-
> [
|
|
857
|
+
> [JUDGMENT → ARCH]
|
|
837
858
|
|
|
838
|
-
|
|
859
|
+
The reviewer checks empty lifecycle pairs and arena-backed slices retained
|
|
860
|
+
beyond the arena's lifetime. `deinit-pairs.sh` emits neither finding.
|
|
861
|
+
Remove a redundant pair or explain its owned state; fix any lifetime mismatch
|
|
862
|
+
before the owning object can outlive the arena.
|
|
839
863
|
|
|
840
|
-
### Scope: full
|
|
864
|
+
### Scope: full tree, explicit files and indexed content
|
|
841
865
|
|
|
842
866
|
> [DETERMINISTIC → DEINIT]
|
|
843
867
|
|
|
844
|
-
`deinit-pairs.sh`
|
|
868
|
+
`deinit-pairs.sh` defaults to tracked Zig files throughout the working tree.
|
|
869
|
+
`--staged` checks staged paths from an owned snapshot of their indexed bytes and
|
|
870
|
+
configuration; `-- <files>` checks only the named working-tree files.
|
|
871
|
+
An unstaged fix cannot clear a staged violation.
|
|
845
872
|
|
|
846
873
|
### Deinit idempotency assertion (reviewer-owned)
|
|
847
874
|
|
|
848
875
|
> [JUDGMENT → DIDEM]
|
|
849
876
|
|
|
850
|
-
Every type
|
|
877
|
+
Every owning type needs a test of its cleanup lifetime.
|
|
878
|
+
For a value that survives cleanup, prove repeated cleanup is safe; for a heap
|
|
879
|
+
object that destroys itself, prove the owner releases it exactly once and
|
|
880
|
+
clears its handle. Never call a method through a freed pointer.
|
|
881
|
+
The leaf emits no `idempotency-test` result; the reviewer inspects the tests and
|
|
882
|
+
allocation paths, including success and failed initialization.
|
package/docs/CHANGELOG_VOICE.md
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
> Prerequisite: read [`DOCUMENTATION_RULES.md`](./DOCUMENTATION_RULES.md) first.
|
|
5
5
|
> Changelog history keeps its archive exception; this file adds the narrower voice.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Use these voice rules in the repository's declared changelog.
|
|
8
|
+
Apply Mintlify block rules only where that format is already selected.
|
|
8
9
|
|
|
9
10
|
- **One headline per entry, no marketing words.** Apply Documentation rule 07
|
|
10
11
|
(`DOC-07`) from `DOCUMENTATION_RULES.md`. Also ban "magical", "we are pleased
|
|
@@ -14,5 +15,13 @@ Editing `~/Projects/docs/changelog.mdx` or any other Mintlify `<Update>` block.
|
|
|
14
15
|
- **Internal cleanup / refactor entries get the most aggressive trimming.** One lead paragraph + one bullet list. Skip "Test coverage" sections unless the test count is the headline. Indy's exact direction: *"Keep internal code cleanup, refactor to a minimal."*
|
|
15
16
|
- **Never drop load-bearing facts.** Error codes (`UZ-AUTH-003`), endpoint paths + method + body shape + status code, env var names + defaults, schema column / table names, CLI subcommand + flag names, migration steps, money amounts. Tighten prose, not meaning.
|
|
16
17
|
- **Historical entries are archives.** Brevity-pass them; never rewrite the past. A typo correction (e.g. `$0.001` → `$0.01` when it was never true) is allowed and must be called out in the commit message.
|
|
17
|
-
- **Rate constants are declared once, so a money claim has one thing to match.**
|
|
18
|
+
- **Rate constants are declared once, so a money claim has one thing to match.**
|
|
19
|
+
Check claims against the repository's canonical billing constants and update
|
|
20
|
+
its published rate tables in the same change.
|
|
21
|
+
<!-- oracle-packs:start product.agentsfleet -->
|
|
22
|
+
- For `agentsfleet`, the rate sources are `rustd/crates/afd_billing/src/nanos.rs`
|
|
23
|
+
and the denominator in `afd_core::money`. Update
|
|
24
|
+
`~/Projects/docs/snippets/rates.mdx` through its authorized branch flow;
|
|
25
|
+
import its named values in Markdown JSX (MDX) instead of copying amounts.
|
|
26
|
+
<!-- oracle-packs:end -->
|
|
18
27
|
- **The Mintlify reference Indy pasted (May 1 / May 8 entries) is canonical voice.** Mirror its rhythm, not its product nouns.
|
|
@@ -12,22 +12,22 @@ Every triggered document requires one `📖 DOC READ: <path>` proof-line **per t
|
|
|
12
12
|
| Any source file (cross-cutting authoring) | `dispatch/write_any.md` — length, logging, milestone-id, error-registry, UFS, greptile read, legacy-workaround family. |
|
|
13
13
|
| Porting a codebase, module, or subsystem from another language | `dispatch/write_any.md` §Porting a codebase between languages — a port is a rewrite with a conformance test: port the guarantee, delete the workaround, conform on observable behaviour, name the debt not carried over. |
|
|
14
14
|
| Spec's "Applicable Rules" | Each rule (canonical). Missing → the cross-cutting codes of `dispatch/write_any.md` are the floor; surface omission. |
|
|
15
|
-
| `*.zig` | `dispatch/write_zig.md`. ZIG GATE per edit. |
|
|
16
|
-
| `*.ts`/`*.tsx`/`*.js`/`*.jsx` | `dispatch/write_ts_adhere_bun.md` — TS FILE SHAPE DECISION (§1) at PLAN, const/import/Bun-primitive discipline, anti-patterns. |
|
|
15
|
+
| `*.zig` | `dispatch/write_zig.md`. ZIG GATE per edit. | <!-- oracle-packs:language.zig -->
|
|
16
|
+
| `*.ts`/`*.tsx`/`*.js`/`*.jsx` | `dispatch/write_ts_adhere_bun.md` — TS FILE SHAPE DECISION (§1) at PLAN, const/import/Bun-primitive discipline, anti-patterns. | <!-- oracle-packs:language.typescript,language.javascript -->
|
|
17
17
|
| `*.rs` | `dispatch/write_rust.md` — ownership, error variants, feature combinations, and contention tests. | <!-- oracle-packs:language.rust -->
|
|
18
18
|
| Rust error type, `Result` alias, or any fallible signature | `dispatch/write_rust.md` §Error discipline — one error per crate, one `Result` alias, `#[from]` composition, `source()` never returns self. ERR-RS fires per edit: `audits/rust-error.sh` (via `dispatch/write_rust.sh`) blocks a `map_err` that stringifies its own cause and an error type with no alias in its crate; the remaining clauses stay judgment. | <!-- oracle-packs:language.rust -->
|
|
19
19
|
| Designing a Rust function, type, or module; writing `match` on a `Result`/`Option`; any production `unwrap()` | `dispatch/write_rust.md` §Functional design — Result pipelines over control-flow trees, illegal states unrepresentable, bind once, `unwrap` needs a proved invariant. | <!-- oracle-packs:language.rust -->
|
|
20
|
-
| `*.py` | `dispatch/write_python.md` — parsing boundaries, resource ownership, and specific exceptions. |
|
|
21
|
-
| `*.sh` | `dispatch/write_shell.md` — quoting, array arguments, cleanup, input safety, and shell compatibility. |
|
|
20
|
+
| `*.py` | `dispatch/write_python.md` — parsing boundaries, resource ownership, and specific exceptions. | <!-- oracle-packs:language.python -->
|
|
21
|
+
| `*.sh` | `dispatch/write_shell.md` — quoting, array arguments, cleanup, input safety, and shell compatibility. | <!-- oracle-packs:language.shell -->
|
|
22
22
|
| `*.mdx` | `dispatch/write_mdx.md` — structure, front matter, links, code fences, accessibility, and Mintlify isolation. | <!-- oracle-packs:language.mdx -->
|
|
23
23
|
| Log emit (any language; see LOGGING GATE triggers) | `docs/LOGGING_STANDARD.md` — wire format (logfmt), severity ladder, error-code embedding, scope/event discipline, PII redaction, §10A tightenings. LOGGING GATE per edit. |
|
|
24
|
-
| Lifecycle method in
|
|
25
|
-
|
|
|
24
|
+
| Lifecycle method in Zig | `docs/LIFECYCLE_PATTERNS.md` — ownership, acquisition cleanup, repeated cleanup of surviving values and exactly-once release of self-destroying objects. | <!-- oracle-packs:language.zig -->
|
|
25
|
+
| HTTP handlers, route registration or OpenAPI | `docs/REST_API_DESIGN_GUIDELINES.md` — endpoint checklist and the repository's mounted authorization and handler shape. | <!-- oracle-packs:domain.http -->
|
|
26
26
|
| `ui/packages/**/*.{tsx,jsx,css}`, `app/**/*.{tsx,jsx,css}`, `components/**/*.{tsx,jsx,css}`, repo-root `globals.css`, or any file changing visual tokens / motion / typography | `DESIGN.md` (repo root) or `docs/DESIGN_SYSTEM.md` — whichever the repo carries. Design system source of truth: typography stack, color tokens, the single accent and its currency rule, motion signature, spacing/density, component principles, CLI palette mapping. DOC READ proof-line per turn. |
|
|
27
|
-
| `*.tsx` / `*.jsx` under `ui/packages/{app,website}/` | `dispatch/write_ts_adhere_bun.md` (Design Tokens) — token-utility table (text/tracking/leading/max-w/min-w/spacing/motion/radius/color). DESIGN TOKEN GATE fires per edit; audit via project-side `audits/design-tokens.sh`. |
|
|
27
|
+
| `*.tsx` / `*.jsx` under `ui/packages/{app,website}/` | `dispatch/write_ts_adhere_bun.md` (Design Tokens) — token-utility table (text/tracking/leading/max-w/min-w/spacing/motion/radius/color). DESIGN TOKEN GATE fires per edit; audit via project-side `audits/design-tokens.sh`. | <!-- oracle-packs:language.typescript,language.javascript -->
|
|
28
28
|
| Auth-flow | `docs/AUTH.md`. |
|
|
29
|
-
| 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. |
|
|
30
|
-
| Changelog `<Update>` / release note (`changelog.mdx`) | First `dispatch/write_documentation.md`, then `dispatch/write_changelog.md` → `docs/CHANGELOG_VOICE.md`; internal-only ⇒ no entry. |
|
|
29
|
+
| 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. | <!-- oracle-packs:domain.documentation -->
|
|
30
|
+
| Changelog `<Update>` / release note (`changelog.mdx`) | First `dispatch/write_documentation.md`, then `dispatch/write_changelog.md` → `docs/CHANGELOG_VOICE.md`; internal-only ⇒ no entry. | <!-- oracle-packs:domain.changelog -->
|
|
31
31
|
| 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. |
|
|
32
|
-
|
|
|
32
|
+
| SQL / migration registration | `dispatch/write_sql.md` + `docs/SCHEMA_CONVENTIONS.md` — the repository's live-data policy and selected product guard. | <!-- oracle-packs:domain.sql -->
|
|
33
33
|
| 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. |
|
|
@@ -7,13 +7,16 @@ Runs after EXECUTE, before VERIFY. Aggregates every gate verdict; lifecycle cann
|
|
|
7
7
|
|
|
8
8
|
## Combined end-of-turn audit
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
`audits/msid-ui.sh` makes one awk pass over added lines. Its default
|
|
11
|
+
`--staged` mode reads `git diff --cached -U0`; `--diff` reads the comparison
|
|
12
|
+
revision through checkout HEAD (`audits/msid-ui.sh:76–85`). It emits:
|
|
11
13
|
|
|
12
14
|
- Emit `MS-ID:` hits when file is source/config and matches `M[0-9]+_[0-9]+|§[0-9]+(\.[0-9]+)+|\bT[0-9]+\b|\bdim [0-9]+\.[0-9]+\b`.
|
|
13
|
-
- Emit `PUB:` hits when `*.zig` and line matches `^\+(pub | *pub fn | *[A-Z][a-zA-Z]+,$)`.
|
|
14
15
|
- Emit `UI:` hits when under `ui/packages/app/**.{tsx,jsx}` and line contains `<(section|button|input|dialog|article|nav|header|form)\b`.
|
|
15
16
|
|
|
16
|
-
Non-empty = address before CONFORM passes.
|
|
17
|
+
Non-empty = address before CONFORM passes. Public declarations remain subject
|
|
18
|
+
to the separate Public (PUB) Gate: zlint checks unused declarations, and the
|
|
19
|
+
agent records the shape decision (`audits/msid-ui.sh:16–33`).
|
|
17
20
|
|
|
18
21
|
## Required output
|
|
19
22
|
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: reference
|
|
3
|
+
audience: contributor
|
|
4
|
+
verified: 2026-10-04
|
|
5
|
+
product_version: 0.11.0
|
|
6
|
+
executable: false
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Jev judgment advice
|
|
10
|
+
|
|
11
|
+
## Synopsis
|
|
12
|
+
|
|
13
|
+
`orly judge` asks one bounded question about evidence you select.
|
|
14
|
+
It accompanies planning, verification, review and documentation.
|
|
15
|
+
Its answer suggests an inspection or a fixed next action.
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
orly judge <plan|verify|review|document> --input <manifest>
|
|
19
|
+
[--project <root>] [--refresh] [--json]
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Jev is TypeSafe's System One model.
|
|
23
|
+
The command pins `jev-1.13.0` and runs TypeScript source with Bun.
|
|
24
|
+
Use the same `bunx` installation as 0.10.x.
|
|
25
|
+
TypeScript 7 is development tooling; evidence selection uses a JavaScript parser.
|
|
26
|
+
|
|
27
|
+
Advice cannot approve work, change a gate result or run a suggested command.
|
|
28
|
+
Existing deterministic checks and owner decisions still apply.
|
|
29
|
+
Hooks do not request advice or upload source.
|
|
30
|
+
|
|
31
|
+
## Example with output
|
|
32
|
+
|
|
33
|
+
Save a manifest describing the required result and its evidence:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"stage": "verify",
|
|
38
|
+
"items": [{
|
|
39
|
+
"id": "locale",
|
|
40
|
+
"question": "verify.assertion",
|
|
41
|
+
"requirement": "The label matches the requested locale's formatted date, including year, month and day.",
|
|
42
|
+
"evidence": [
|
|
43
|
+
{ "role": "implementation", "path": "src/label.ts", "selector": { "kind": "file" } },
|
|
44
|
+
{ "role": "test", "path": "src/label.test.ts", "selector": { "kind": "test", "name": "label respects locale" } }
|
|
45
|
+
]
|
|
46
|
+
}]
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Run without refresh to read an existing exact replay:
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
orly judge verify --input judgments.json
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
For inputs without a replay, the command reports:
|
|
57
|
+
|
|
58
|
+
```text
|
|
59
|
+
Jev advice — deterministic checks and owner decisions still apply.
|
|
60
|
+
locale: incomplete — No exact replay for these inputs. Use --refresh to permit scanned source upload.
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
This result has exit status `2` and makes no provider request.
|
|
64
|
+
To request live advice, supply `TYPESAFE_API_KEY` through your environment and install `gitleaks`.
|
|
65
|
+
Then explicitly permit the selected source upload:
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
bunx @agentsfleet/orly judge verify --input judgments.json --refresh --json
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The report includes typed answers, selected source references, request counts, elapsed time and token usage.
|
|
72
|
+
The report excludes selected source text and credentials.
|
|
73
|
+
|
|
74
|
+
## Options
|
|
75
|
+
|
|
76
|
+
| Option | Meaning |
|
|
77
|
+
|---|---|
|
|
78
|
+
| Stage | Must match the manifest and each selected question |
|
|
79
|
+
| `--input` | Required JSON manifest path; maximum 64 KiB |
|
|
80
|
+
| `--project` | Evidence root; defaults to the current directory |
|
|
81
|
+
| `--refresh` | Permits secret-scanned evidence upload and one provider request per item |
|
|
82
|
+
| `--json` | Prints a structured report |
|
|
83
|
+
| `--help` | Prints usage, selectors and the question catalog |
|
|
84
|
+
|
|
85
|
+
Kibibyte (KiB) means 1,024 bytes.
|
|
86
|
+
A manifest contains at most 12 uniquely named items.
|
|
87
|
+
Each item has a question, requirement and at most eight evidence references.
|
|
88
|
+
|
|
89
|
+
Each reference names a role, relative path and selector.
|
|
90
|
+
Roles are `spec`, `implementation`, `test`, `rule`, `claim`, `result` and `context`.
|
|
91
|
+
Name necessary unchanged context explicitly; the command does not discover dependencies.
|
|
92
|
+
|
|
93
|
+
| Selector | Required fields | Selected evidence |
|
|
94
|
+
|---|---|---|
|
|
95
|
+
| `file` | `kind` | Whole bounded file |
|
|
96
|
+
| `function` | `kind`, `name` | One complete TypeScript or JavaScript function |
|
|
97
|
+
| `test` | `kind`, `name` | One named executable `test` or `it` call |
|
|
98
|
+
| `section` | `kind`, `heading` | One plain Markdown heading through its peer or ancestor boundary |
|
|
99
|
+
|
|
100
|
+
Duplicate matches, skipped tests, malformed syntax and escaping paths are refused.
|
|
101
|
+
Individual files have a 256 KiB cap; complete selected state has a 24 KiB cap.
|
|
102
|
+
Oversized evidence is refused rather than truncated.
|
|
103
|
+
|
|
104
|
+
### Atomic questions and timing
|
|
105
|
+
|
|
106
|
+
| Question | Run when | Required input | Jev criterion | Decision to take |
|
|
107
|
+
|---|---|---|---|---|
|
|
108
|
+
| `plan.prerequisites` | Before accepting a plan | One requirement and its `spec` evidence | Necessary inputs, credentials, fetch locations, permissions and ordering are explicit | Clarify a missing prerequisite |
|
|
109
|
+
| `plan.observable_result` | Before implementation | One requirement and its `spec` evidence | Success and refusal have concrete observable results | Add the missing expected result |
|
|
110
|
+
| `verify.assertion` | Before accepting a test as proof | Required behavior plus complete `implementation` and `test` evidence | The assertion checks that behavior, distinguishes a supplied wrong result, and targets the named operation | Keep the exact assertion or strengthen a weak, missing or misplaced assertion |
|
|
111
|
+
| `review.failure_path` | While disposing of a failure finding | One named failure requirement and `implementation` evidence | The path preserves the failure and handles acquired resources | Trace the path and add a failure test |
|
|
112
|
+
| `review.rule_applicability` | Before deciding a rule finding | One `rule`, its condition and `implementation` evidence | The selected code meets that rule's trigger | Apply the rule or inspect applicability; the owner decides exceptions |
|
|
113
|
+
| `document.claim` | Before publishing a claim | One `claim` plus `implementation` or measured `result` evidence | Evidence supports the exact scope, quantities and conditions | Narrow the claim or collect missing proof |
|
|
114
|
+
|
|
115
|
+
Choice answers classify assertions as `exact`, `weak`, `wrong_target`, `missing` or `insufficient`.
|
|
116
|
+
Noul answers provide a probability for the question's stated property.
|
|
117
|
+
The question catalog supplies fixed actions; the model cannot supply commands.
|
|
118
|
+
|
|
119
|
+
The experiment marks strength below `0.8` as uncertain.
|
|
120
|
+
This threshold has no independent calibration.
|
|
121
|
+
Uncertainty requires inspection and cannot waive a rule or satisfy verification.
|
|
122
|
+
|
|
123
|
+
### Replay and request limits
|
|
124
|
+
|
|
125
|
+
Default mode reads `.orly/judgments/` without contacting the provider.
|
|
126
|
+
Identity binds the project root, model, question definition, requirement, selectors and selected source bytes.
|
|
127
|
+
Changed inputs require an explicit refresh.
|
|
128
|
+
|
|
129
|
+
Live preflight checks every item before uploading any item.
|
|
130
|
+
Each request has a 15-second deadline, including response reading, and a 64 KiB response cap.
|
|
131
|
+
Requests are sequential and receive no automatic retries.
|
|
132
|
+
|
|
133
|
+
Replay files use private permissions and omit source text.
|
|
134
|
+
Their checksum detects accidental reply changes; a local owner can edit and reseal them.
|
|
135
|
+
Replay remains advisory and cannot prove independent model accuracy.
|
|
136
|
+
|
|
137
|
+
## Errors
|
|
138
|
+
|
|
139
|
+
| Result | Meaning and next step |
|
|
140
|
+
|---|---|
|
|
141
|
+
| Exit `0` | Every item has valid advice; concerns and uncertainty still require inspection |
|
|
142
|
+
| Exit `2` | An item or manifest is incomplete; inspect the reported reason |
|
|
143
|
+
| No exact replay | Use unchanged inputs or explicitly request refresh |
|
|
144
|
+
| Missing credential | Supply the provider key through the environment |
|
|
145
|
+
| Failed secret scan | Remove credentials from selected evidence before retrying |
|
|
146
|
+
| Missing or ambiguous evidence | Correct the reference or include necessary context |
|
|
147
|
+
| Invalid provider reply | No valid replay was saved; inspect the provider failure before retrying |
|
|
148
|
+
|
|
149
|
+
## Related pages
|
|
150
|
+
|
|
151
|
+
- [Architecture](ORLY_ARCHITECTURE.md)
|
|
152
|
+
- [Project overview](../README.md)
|
|
153
|
+
- [Unit test skill](../skills/orly-write-unit-test/SKILL.md)
|
|
@@ -149,7 +149,10 @@ pub const Watcher = struct {
|
|
|
149
149
|
**Mandatory rules:**
|
|
150
150
|
|
|
151
151
|
1. **`deinit` must free everything `init` allocated.** Lints catch the inverse (`init` allocates, `deinit` doesn't free) but not silently-correct cases (`init` allocates A and B, `deinit` frees only A — silent leak). Reviewer responsibility: walk the alloc list against the free list.
|
|
152
|
-
2.
|
|
152
|
+
2. **Cleanup follows the object's lifetime.** A surviving value clears its
|
|
153
|
+
owned fields and permits repeated cleanup. A heap object that destroys
|
|
154
|
+
itself is released exactly once by its owner, which clears its handle;
|
|
155
|
+
calling `deinit` through the freed pointer is forbidden.
|
|
153
156
|
3. **`deinit` does not return errors.** Cleanup that *can* fail (closing a file, flushing a buffer) must be split into a separate explicit method (`pub fn close(self: *Self) !void`) called before `deinit`, or the failure must be logged and swallowed inside deinit.
|
|
154
157
|
4. **No partial deinit.** Once `deinit` runs, the struct is dead. Don't leave half-freed state for "the caller will free the rest" — that's a leak waiting to happen.
|
|
155
158
|
5. **Deinit order is reverse of init order.** Free children before freeing the parent that owns them. `errdefer` chains in init naturally produce the right order; mirror it in deinit.
|
|
@@ -254,17 +257,21 @@ Anything else is a smell:
|
|
|
254
257
|
|
|
255
258
|
The struct's `deinit` method is the single source of truth for cleanup. Call sites use `defer self.deinit()` (or `errdefer` if ownership might transfer mid-function) and never reach inside the struct.
|
|
256
259
|
|
|
257
|
-
## §10 ·
|
|
260
|
+
## §10 · Machine checks and mandatory ownership review
|
|
258
261
|
|
|
259
|
-
|
|
262
|
+
`deinit-pairs.sh` checks refined public initializer/cleanup pairing and nearby
|
|
263
|
+
`defer`/`errdefer` conflicts on the same target. It does not prove struct-level
|
|
264
|
+
ownership, cleanup placement, allocator lifetime or failure-path coverage.
|
|
265
|
+
|
|
266
|
+
| Pattern | Detection | Fix |
|
|
260
267
|
|---|---|---|
|
|
261
|
-
|
|
|
262
|
-
|
|
|
263
|
-
| `errdefer` at end of init scope (batched) |
|
|
264
|
-
| `defer` and `errdefer` on the same allocation | **blocking** | Pick
|
|
265
|
-
| `init` returning `*Self` without
|
|
266
|
-
|
|
|
267
|
-
| Stored allocator field never used in
|
|
268
|
+
| Allocating or heap-returning public `init` without a same-file cleanup method | **blocking machine check**; reviewer verifies the matching owner | Add the owner's cleanup method; resource-free value initialization needs no empty pair. |
|
|
269
|
+
| Cleanup with no corresponding ownership acquisition | **mandatory review** | Check all acquisition paths before removing or renaming the method. |
|
|
270
|
+
| `errdefer` at end of init scope (batched) | **mandatory review** | Move adjacent to the allocation it protects. |
|
|
271
|
+
| `defer` and `errdefer` on the same allocation | **blocking machine check** within four lines; mandatory review elsewhere | Pick the cleanup matching the ownership path. |
|
|
272
|
+
| `init` returning `*Self` without failure-path destruction | **mandatory review** | Release the heap owner on every failed initialization path. |
|
|
273
|
+
| Cleanup order invalidates an allocator still needed by children | **mandatory review** | Release children before invalidating their allocator. |
|
|
274
|
+
| Stored allocator field never used in cleanup | **mandatory review** | Remove the field or release the owned resources through it. |
|
|
268
275
|
|
|
269
276
|
## §10A · Tightening clauses (closures of common skip rationalizations)
|
|
270
277
|
|
|
@@ -272,18 +279,21 @@ Failure modes the audit script and reviewer must close. These are **not aspirati
|
|
|
272
279
|
|
|
273
280
|
| # | Rationalization | Closure |
|
|
274
281
|
|---|---|---|
|
|
275
|
-
| LC1 | "Struct is small / one allocation, skip `deinit`" |
|
|
282
|
+
| LC1 | "Struct is small / one allocation, skip `deinit`" | Every owned allocation or opaque handle needs cleanup. The leaf checks allocating or heap-returning public initializers for a same-file cleanup method; the reviewer checks ownership acquired later and matches every acquisition to release. |
|
|
276
283
|
| LC2 | "Renamed `deinit` to `close` / `release` to dodge pair audit" | Audit script treats `deinit`, `close`, `release`, `destroy`, `shutdown`, `free`, `dispose` as **lifecycle methods**. All require a paired `init` and trigger LIFECYCLE GATE. Rename does not bypass; intent does. |
|
|
277
|
-
| LC3 | "I'll batch `errdefer` at the bottom of init, easier to read" |
|
|
284
|
+
| LC3 | "I'll batch `errdefer` at the bottom of init, easier to read" | Place each `errdefer` immediately after its acquisition, before the next fallible operation. The reviewer checks every early return; the leaf does not enforce placement. |
|
|
278
285
|
| LC4 | "Both `defer` and `errdefer` on the same allocation, belt-and-suspenders" | Audit greps for `defer X.free(Y)` + `errdefer X.free(Y)` (or the reverse) in the same scope. **Blocking violation** — pick one per §6. |
|
|
279
|
-
| LC5 | "
|
|
280
|
-
| LC6 | "Storing arena slice in long-lived struct works in my test" |
|
|
281
|
-
| LC7 | "Empty no-op `init` paired with empty no-op `deinit` to satisfy the gate" |
|
|
286
|
+
| LC5 | "Cleanup works in practice; no test needed" | Reviewer verifies repeated cleanup of surviving values or exactly-once release and cleared owner handles for self-destroying heap objects. Never invoke a freed object's method. The leaf reports no test-presence verdict. |
|
|
287
|
+
| LC6 | "Storing arena slice in long-lived struct works in my test" | Reviewer checks that the arena outlives every retained slice and fixes any mismatch; the leaf emits no arena-lifetime warning. |
|
|
288
|
+
| LC7 | "Empty no-op `init` paired with empty no-op `deinit` to satisfy the gate" | Reviewer removes redundant pairs or explains their owned state; the leaf emits no empty-pair warning. |
|
|
282
289
|
| LC8 | "Auto-mode is on" | **Auto-mode does NOT cover gate skips.** Skip without explicit user-given override = automatic violation. |
|
|
283
290
|
| LC9 | "Renamed-only file (no content change), gate doesn't fire" | Rename without content change does **not** fire LIFECYCLE GATE. Rename + content change does. Pure rename is a no-op for the gate. |
|
|
284
291
|
| LC10 | "Two docs disagree (e.g. write_zig.md says X, LIFECYCLE_PATTERNS says Y)" | Precedence: dispatch façade > standards doc > spec. The façade (`dispatch/write_zig.md`, lifecycle) is the canonical enforcement layer. |
|
|
285
292
|
|
|
286
|
-
|
|
293
|
+
`deinit-pairs.sh` checks allocating initializer pairs and adjacent conflicting
|
|
294
|
+
`defer`/`errdefer` releases. The reviewer handles the other obligations above;
|
|
295
|
+
a green leaf result cannot replace them. The dispatch façade names the same
|
|
296
|
+
ownership rules.
|
|
287
297
|
|
|
288
298
|
## §11 · Carve-out: PUB GATE vs LIFECYCLE GATE
|
|
289
299
|
|