@agentsfleet/orly 0.10.14 → 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 +12 -5
- 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 +9 -6
- package/src/gates_spec.test.ts +52 -6
- 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
package/docs/LOGGING_STANDARD.md
CHANGED
|
@@ -9,7 +9,7 @@ Pre-design rules, decisive defaults, and the anti-patterns each rule exists to p
|
|
|
9
9
|
Triggers on every `Edit`/`Write` that adds, removes, or changes a log emit:
|
|
10
10
|
|
|
11
11
|
- `*.zig` outside `vendor/`/`third_party/`/`.zig-cache/` — `std.log.*`, `std.debug.print`, `std.io.getStdErr().writer().print`, any helper in `src/lib/logging/`.
|
|
12
|
-
- `*.rs`
|
|
12
|
+
- Runtime `*.rs` outside test and benchmark scopes — `tracing::{error,warn,info,debug,trace}!`, `println!`, `eprintln!`, and `dbg!`.
|
|
13
13
|
- `*.ts`/`*.tsx`/`*.js`/`*.jsx` outside `vendor/`/`node_modules/` — `console.*`, custom logger calls.
|
|
14
14
|
- `*.sh` outside generated directories — `echo`, `printf` to `&2`.
|
|
15
15
|
|
|
@@ -19,8 +19,10 @@ Out of scope (explicitly):
|
|
|
19
19
|
- Build/release scripts — the harness's own `audits/*`, `audits/release-*`, and any governance-repo tooling — toolchain output, not application logs.
|
|
20
20
|
- Generated framework noise (Next.js startup banners, Bun runtime warnings) — out of our control.
|
|
21
21
|
|
|
22
|
-
The
|
|
22
|
+
The LOGGING GATE in `dispatch/write_any.md` applies alongside the repository's
|
|
23
|
+
selected language rules.
|
|
23
24
|
|
|
25
|
+
<!-- oracle-packs:start product.agentsfleet -->
|
|
24
26
|
## §2 · Today's de-facto standard (survey-derived)
|
|
25
27
|
|
|
26
28
|
Documented honestly, not aspirationally. Pre-M62 baseline (the fix-pass converges every existing emit toward §3 onward):
|
|
@@ -39,6 +41,7 @@ Documented honestly, not aspirationally. Pre-M62 baseline (the fix-pass converge
|
|
|
39
41
|
- No collector-friendly format. Logs are a mix of free-form English and ad-hoc `key={value}` fragments.
|
|
40
42
|
|
|
41
43
|
The proposed standard below is what every new emit must conform to and what the fix-pass converges existing emits toward.
|
|
44
|
+
<!-- oracle-packs:end -->
|
|
42
45
|
|
|
43
46
|
## §3 · Wire format — logfmt
|
|
44
47
|
|
|
@@ -168,12 +171,16 @@ Log the source (`source=env:OPENAI_API_KEY`), never the value, at every level.
|
|
|
168
171
|
|
|
169
172
|
> [DETERMINISTIC → LOG]
|
|
170
173
|
|
|
171
|
-
Every `err`
|
|
174
|
+
Every `err` or `warn` record for a domain error carries its code from the
|
|
175
|
+
repository's declared error registry. Validate new references through its
|
|
176
|
+
configured checker; installing this pack does not select a code prefix.
|
|
172
177
|
|
|
178
|
+
<!-- oracle-packs:start product.agentsfleet -->
|
|
173
179
|
- **Used-but-undeclared** (`UZ-FAKE-999` appearing in code, no entry in registry): **blocking** in `make lint`.
|
|
174
180
|
- **Declared-but-unreferenced** (registry has `UZ-LEGACY-007`, no code references it): **informational**. Deletion may be deferred to a sweep milestone.
|
|
175
181
|
|
|
176
182
|
Embed the code as a struct field on the logger call: `log.err("event_name", .{ .error_code = error_codes.ERR_X, .err = @errorName(err) })`. The encoding helpers in `src/lib/logging/mod.zig` serialize it as `error_code=UZ-XXX-NNN` per §3. CLI (`agentsfleet`) renders the code in human format and as `code: "UZ-XXX-NNN"` in `--json` output (see §8).
|
|
183
|
+
<!-- oracle-packs:end -->
|
|
177
184
|
|
|
178
185
|
System-level failures with no domain meaning (e.g. raw `EACCES` from a syscall before we attribute it to a tenant operation) emit without `error_code`. The follow-up rule: if a syscall failure surfaces to a user, it gets attributed to a registry code at the boundary.
|
|
179
186
|
|
|
@@ -181,20 +188,30 @@ System-level failures with no domain meaning (e.g. raw `EACCES` from a syscall b
|
|
|
181
188
|
|
|
182
189
|
> [UNENFORCED → broad principle; no scan covers every log call site in the codebase for credential-shaped values]
|
|
183
190
|
|
|
184
|
-
|
|
191
|
+
Secrets must not appear in log records at any level. Read the repository's
|
|
192
|
+
redactor and verify coverage of every stream used by the changed operation.
|
|
185
193
|
|
|
186
194
|
> [JUDGMENT → REDACT]
|
|
187
195
|
|
|
188
196
|
- **Allocator outputs** (Postgres connection strings, Redis URLs, OAuth tokens, OpenAI keys) — never log. If a record needs to identify a config source, log the *source* (`source=env:OPENAI_API_KEY`), not the *value*.
|
|
189
|
-
- **Tenant-supplied secrets**
|
|
190
|
-
|
|
197
|
+
- **Tenant-supplied secrets** — log emit sites must preserve the repository's
|
|
198
|
+
redaction boundary. Check both stdout and stderr; never assume a stream is
|
|
199
|
+
covered merely because another product's harness covers it.
|
|
191
200
|
|
|
192
201
|
> [JUDGMENT → MSG-REVIEW]
|
|
193
202
|
|
|
194
|
-
- **`msg=` fields** —
|
|
203
|
+
- **`msg=` fields** — reviewers inspect copied values for credentials and test
|
|
204
|
+
renderer bounds. The source leaf does not detect long messages.
|
|
195
205
|
|
|
196
206
|
When in doubt, omit. A missing field is recoverable; a leaked secret is not.
|
|
197
207
|
|
|
208
|
+
## Repository logger binding
|
|
209
|
+
|
|
210
|
+
Use the consuming repository's structured logger and error registry.
|
|
211
|
+
Read its exports and test actual rendered records for the fields, bounds and
|
|
212
|
+
escaping above; installing a pack does not create a logging module.
|
|
213
|
+
|
|
214
|
+
<!-- oracle-packs:start product.agentsfleet -->
|
|
198
215
|
## §7 · Per-language binding — Zig
|
|
199
216
|
|
|
200
217
|
The wire format above is produced by helpers in `src/lib/logging/mod.zig`, exposed as the named module `log` so any layer-isolated tree (auth/, executor/) can import it without violating layer rules. Call sites use:
|
|
@@ -279,11 +296,11 @@ Schema mirrors Bun's `SystemError` extern struct (`bun:src/bun.js/bindings/Syste
|
|
|
279
296
|
|
|
280
297
|
> [DETERMINISTIC → LOG]
|
|
281
298
|
|
|
282
|
-
**Logging emit sites** in `cli/src/**` use a thin Bun-runtime logger that produces logfmt records to `stderr`. `console.log` / `console.error` are forbidden in source per `dispatch/write_ts_adhere_bun.md` §10 — `logging.sh` enforces this for TS/JS.
|
|
299
|
+
**Logging emit sites** in `cli/src/**` use a thin Bun-runtime logger that produces logfmt records to `stderr`. `console.log` / `console.error` are forbidden in source per `dispatch/write_ts_adhere_bun.md` §10 — `logging.sh` enforces this for TS/JS. <!-- oracle-packs:language.typescript,language.javascript -->
|
|
283
300
|
|
|
284
301
|
> [JUDGMENT → TS-STYLE]
|
|
285
302
|
|
|
286
|
-
**Module-level error style** is governed by
|
|
303
|
+
**Module-level error style** is governed by the selected language's error discipline. The error type itself is the same:
|
|
287
304
|
|
|
288
305
|
```ts
|
|
289
306
|
class AgentError extends Error {
|
|
@@ -295,6 +312,7 @@ class AgentError extends Error {
|
|
|
295
312
|
|
|
296
313
|
Throw-style modules `throw new AgentError({...})`. Result-style modules return `{ ok: false, error: new AgentError({...}) }`. Render path picks human or JSON based on the runtime mode.
|
|
297
314
|
|
|
315
|
+
<!-- oracle-packs:end -->
|
|
298
316
|
## §8A · Per-language binding — Rust
|
|
299
317
|
|
|
300
318
|
> [DETERMINISTIC → LOG]
|
|
@@ -390,16 +408,18 @@ Failure modes the audit script and reviewer must close. These are **not aspirati
|
|
|
390
408
|
| # | Rationalization | Closure |
|
|
391
409
|
|---|---|---|
|
|
392
410
|
| L1 | "Temporary debug print, I'll remove later" | `logging.sh` rejects `std.debug.print`, Rust `println!` / `eprintln!` / `dbg!`, and `console.log` / `console.debug` / `console.info` in runtime source. Direct Zig or Rust stream output needs `// logging: <reason>` on or immediately above the emit. The reason must be non-empty and explain why the stream is the program interface. |
|
|
393
|
-
| L2 | "
|
|
411
|
+
| L2 | "The standard logger already has a scope" | Use the repository's structured logger and prove the §3 record shape. For `agentsfleet`, this is the named `log` module's `logging.scoped`, as §7 specifies. The leaf does not enforce logger imports or reject every `std.log` call; the reviewer checks this binding. |
|
|
394
412
|
| L3 | "I added `error_code=UZ-NEW-001` — registry entry coming next commit" | The registry entry **must land in the same commit** as the first reference. `error-codes.sh` runs against the staged diff; missing entry = blocking. |
|
|
395
413
|
| L4 | "This per-iteration event matters for debugging — `info`-level" | Per-iteration and per-row paths are `debug`, including mandatory boundary pairs on hot polls. `debug` is the level with a volume switch. This closes the ONLY `info` prohibition — there is no allow-list of event names and none may be reintroduced (§4). The inverse rationalization is closed too: "this operation is obviously fine, no need to log it" does not survive §4 rule 1, which requires a `_started`/`_completed`\|`_failed` pair on every boundary-crossing operation. Reviewer checks the pair and the loop, never the spelling. |
|
|
396
|
-
| L5 | "Operator needs the full stack trace in `msg=`" | `msg=` capped at 300
|
|
397
|
-
| L6 | "Embedded newlines because I copy-pasted output" |
|
|
414
|
+
| L5 | "Operator needs the full stack trace in `msg=`" | `msg=` stays capped at 300 characters and each record at 15 fields. Emit correlated stack traces separately at `debug`. These are renderer and reviewer checks; the leaf emits no message-size or field-count verdict. |
|
|
415
|
+
| L6 | "Embedded newlines because I copy-pasted output" | Encode newline characters as `\n` within values. Verify the actual rendered record in tests and review; the leaf cannot inspect runtime output. |
|
|
398
416
|
| L7 | "Auto-mode is on, the gate block is ceremony" | **Auto-mode does NOT cover gate skips.** Skip without an explicit user-given override = automatic violation. No size threshold lets an edit bypass the gate. |
|
|
399
417
|
| L8 | "I read this doc at session start; subsequent edits don't need re-print" | Gate fires **per-edit**. The printed `🔴 LOGGING GATE` block is required before every triggered Edit/Write, not once per session. |
|
|
400
418
|
| L9 | "Fix-pass touches every line; printing per-line is noise" | Fix-pass produces **one combined gate block per file**, not per-line. The block lists all violations addressed in that file. Still required, just consolidated. |
|
|
401
419
|
|
|
402
|
-
|
|
420
|
+
The leaf checks source emit forms; reviewers and renderer tests check the
|
|
421
|
+
record shape, logger binding, bounds and escaping named above.
|
|
422
|
+
The dispatch façade requires both kinds of evidence.
|
|
403
423
|
|
|
404
424
|
## §11 · Anti-patterns (named, banned)
|
|
405
425
|
|
|
@@ -410,7 +430,7 @@ These are enforced by `logging.sh` (mechanical) and the dispatch façade (`dispa
|
|
|
410
430
|
| Rust `println!`, `eprintln!`, or `dbg!` outside tests | No level, event, or structured fields — dev diagnostics that escaped to main. |
|
|
411
431
|
| Rust `tracing` emit without `event` | Drops the stable event key required by §3. |
|
|
412
432
|
| Positional formatting in a Rust `tracing` emit | Values become opaque message text instead of queryable fields. |
|
|
413
|
-
| `console.log` in `agentsfleet` source | Bypasses logger, breaks `--json` mode, violates
|
|
433
|
+
| `console.log` in `agentsfleet` source | Bypasses logger, breaks `--json` mode, violates the selected language's error discipline. |
|
|
414
434
|
| Logging on hot per-iteration paths at `info` | Floods collectors. Use `debug` (gated off by default). |
|
|
415
435
|
| `error_code=` missing on `err`/`warn` mapping to registry codes | Breaks traceability; future operator can't link log to docs. |
|
|
416
436
|
| Logging credentials, tokens, or BYOK keys | Severe leak surface. Redaction harness mandatory. |
|
|
@@ -430,10 +450,10 @@ immediately preceding the edit. Generic "scope creep" is not a valid reason —
|
|
|
430
450
|
|
|
431
451
|
## §13 · Family
|
|
432
452
|
|
|
433
|
-
- `dispatch/write_ts_adhere_bun.md` §10 — banned `console.log` in
|
|
434
|
-
- `dispatch/write_ts_adhere_bun.md` §9 — module-level error style
|
|
435
|
-
- `dispatch/write_zig.md` — Zig discipline
|
|
436
|
-
- `dispatch/write_rust.md` — Rust discipline
|
|
453
|
+
- `dispatch/write_ts_adhere_bun.md` §10 — banned `console.log` in runtime source. <!-- oracle-packs:language.typescript,language.javascript -->
|
|
454
|
+
- `dispatch/write_ts_adhere_bun.md` §9 — module-level error style. <!-- oracle-packs:language.typescript,language.javascript -->
|
|
455
|
+
- `dispatch/write_zig.md` — Zig authoring discipline. <!-- oracle-packs:language.zig -->
|
|
456
|
+
- `dispatch/write_rust.md` — Rust authoring discipline. <!-- oracle-packs:language.rust -->
|
|
437
457
|
- `LIFECYCLE_PATTERNS.md` — orthogonal: ownership/cleanup of structs, including allocator wiring for the thread-local log buffer.
|
|
438
458
|
- M42_002 redaction harness (`src/runner/engine/runner_progress.zig`) — secret-redaction precondition; this doc's §6 inherits.
|
|
439
459
|
- Universal rules (RULE UFS, RULE TGU, RULE PRI, RULE FLL, RULE ORP, RULE TST-NAM) live in `docs/greptile-learnings/RULES.md`.
|
|
@@ -455,7 +475,7 @@ its line covers the clauses under it until the next heading.
|
|
|
455
475
|
| `[JUDGMENT → BOUNDARY]` | is this operation boundary-crossing, and is its `_started`/`_completed`\|`_failed` pair complete | the agent at write time; the reviewer at `/review` |
|
|
456
476
|
| `[JUDGMENT → REDACT]` | is this value a secret, or the label of one | the agent at write time; the M42_002 harness covers only executor-child output |
|
|
457
477
|
| `[JUDGMENT → MSG-REVIEW]` | does this `msg=` carry a credential | the reviewer; no length or content check runs today |
|
|
458
|
-
| `[JUDGMENT → TS-STYLE]` | throw-style or Result-style for this module |
|
|
478
|
+
| `[JUDGMENT → TS-STYLE]` | throw-style or Result-style for this module | the selected language façade, reviewer-decided |
|
|
459
479
|
| `[JUDGMENT → RUST-STYLE]` | does a Rust failure map to a registry code, and are field expressions safely hoisted | the agent at write time; the reviewer at `/review` |
|
|
460
480
|
| `[JUDGMENT → EVENT-COMPAT]` | does a language port preserve the event bytes consumed by existing dashboards | the agent compares old and new event constants; the reviewer confirms intentional renames |
|
|
461
481
|
| `[JUDGMENT → SECTION-SCAN]` | which sections of this file the current sub-task needs | the agent; `audits/doc-read.sh` records façade reads, not delegated-doc reads |
|
|
@@ -31,7 +31,7 @@ unaffected by anything below.
|
|
|
31
31
|
Every other repository gets its rules a different way: `orly init` materialises
|
|
32
32
|
the packs its own sources select — rendered `AGENTS.md`, the rule docs, the gate
|
|
33
33
|
scripts, the hooks that run them — into that repository, and writes
|
|
34
|
-
`.
|
|
34
|
+
`.orly/orly.json` recording the engine version and every file it wrote,
|
|
35
35
|
alongside the repository's own packs, commands, and surfaces. `orly update` re-materialises against the currently installed engine
|
|
36
36
|
version; `orly doctor` reports drift between the lock and disk instead of
|
|
37
37
|
silently tolerating it. A materialised repository needs no checkout of this
|
|
@@ -55,7 +55,7 @@ restores storage, but not the failure mode that got it removed: `orly update`
|
|
|
55
55
|
turns a rule change into one command per repository instead of the manual
|
|
56
56
|
sync M01 rejected, and the lock makes staleness a reported condition —
|
|
57
57
|
`orly doctor` — instead of a silent one. cache-kit.rs is the evidence for both
|
|
58
|
-
failure modes in the same repository: its `.
|
|
58
|
+
failure modes in the same repository: its `.orly/` snapshot from the
|
|
59
59
|
pre-thin model sat frozen for four weeks with no update path, and its
|
|
60
60
|
generated `AGENTS.md` told a Rust crate its project name was `agentsfleet` —
|
|
61
61
|
a persona/product leak M03 also closes, by fencing both behind opt-in packs a
|
|
@@ -90,8 +90,11 @@ Four behaviours worth knowing:
|
|
|
90
90
|
with a printed reason, so an ad-hoc bug fix meets the quality gates without
|
|
91
91
|
being told to write a spec. A spec moved to `done/` on the branch is still
|
|
92
92
|
discovered through its `Branch:` header and gates the PR — CHORE(close)
|
|
93
|
-
never skip-passes the criteria it exists to satisfy.
|
|
94
|
-
|
|
93
|
+
never skip-passes the criteria it exists to satisfy. Headers accept a plain
|
|
94
|
+
token or an inline-code token. Active specs explicitly owned by other branches
|
|
95
|
+
do not displace this branch's spec; active specs without a branch remain gated.
|
|
96
|
+
Multiple specs may fold into one owner through `Folded-into`; two independent
|
|
97
|
+
owners on the current branch remain an error.
|
|
95
98
|
- **A worktree is its repository.** `repositories.json` registers primary
|
|
96
99
|
checkouts only; a linked worktree resolves through the set of checkouts git
|
|
97
100
|
reports for the shared object store. Streams stay ephemeral and unregistered,
|
|
@@ -113,13 +116,15 @@ malformed trailer is not an override; the gate stays red.
|
|
|
113
116
|
|
|
114
117
|
## Profiles
|
|
115
118
|
|
|
116
|
-
`.
|
|
119
|
+
`.orly/orly.json` names any opt-in packs, the command surface, and optionally the diff
|
|
117
120
|
surfaces:
|
|
118
121
|
|
|
119
122
|
```json
|
|
120
123
|
{
|
|
124
|
+
"schema_version": 1,
|
|
121
125
|
"commands": { "conform": [["make", "harness-verify"]],
|
|
122
126
|
"verify.unit": [["make", "test-unit-all"]] },
|
|
127
|
+
"limits": { "verify.unit": { "timeout_ms": 1800000, "output_bytes": 67108864 } },
|
|
123
128
|
"surfaces": { "user": ["src/http/", "cli/src/"],
|
|
124
129
|
"docs": ["docs/"] }
|
|
125
130
|
}
|
|
@@ -132,6 +137,14 @@ checks without declaring application test suites. `init` reports missing
|
|
|
132
137
|
commands; `doctor` rejects incomplete setup without running those commands.
|
|
133
138
|
The final tree check includes the spec, so its evidence must be committed.
|
|
134
139
|
|
|
140
|
+
`schemas/profile.schema.json` describes the repository file, including ownership records and disabled execution settings.
|
|
141
|
+
Both configuration readers refuse unknown settings, malformed types and unsupported execution modes before selecting commands.
|
|
142
|
+
Each invocation defaults to 30 minutes and 64 mebibytes of combined output; `limits` supplies per-command overrides.
|
|
143
|
+
|
|
144
|
+
The synchronous gate calls a Bun supervisor that reads both streams and stops the owned process group on either limit.
|
|
145
|
+
Limited commands return a failure with measured duration, byte count and a private receipt directory containing all captured bytes.
|
|
146
|
+
Normal commands remove their temporary files after the gate reads the complete output; limit receipts remain until the caller removes them.
|
|
147
|
+
|
|
135
148
|
## Usage telemetry
|
|
136
149
|
|
|
137
150
|
Orly keeps usage telemetry off until a person enables anonymous collection in
|
|
@@ -154,5 +167,63 @@ the Fleet is an analysis consumer and never the public ingestion boundary.
|
|
|
154
167
|
## Evidence
|
|
155
168
|
|
|
156
169
|
`orly verify --all --write-evidence` records the source commit and every check
|
|
157
|
-
into `.
|
|
170
|
+
into `.orly/evidence.json` (git-ignored). Pre-push writes it when the pushed
|
|
158
171
|
range touches governance paths.
|
|
172
|
+
|
|
173
|
+
## TypeScript judgment experiment
|
|
174
|
+
|
|
175
|
+
The 0.11.0 experiment keeps the Bun command line and installed `.orly/`
|
|
176
|
+
layout. `orly judge` accompanies the deterministic gates with explicit advice.
|
|
177
|
+
Indy canceled the native rewrite and its Milestone 07 plans on Oct 04, 2026.
|
|
178
|
+
|
|
179
|
+
### Timing and authority
|
|
180
|
+
|
|
181
|
+
| Stage | Input | Bounded decision | Follow-up |
|
|
182
|
+
|---|---|---|---|
|
|
183
|
+
| PLAN | One spec requirement and its selected section | Are prerequisites explicit? Is the result observable? | Clarify setup or expected results before implementation |
|
|
184
|
+
| VERIFY | Required behavior, complete implementation and linked test | Does the assertion discriminate correct behavior from the supplied incorrect behavior? | Add an exact assertion before accepting test evidence |
|
|
185
|
+
| REVIEW | One failure path or one rule with selected code | Is the failure handled? Does this rule apply? | Inspect the named path or rule before disposing of the finding |
|
|
186
|
+
| DOCUMENT | One claim and selected implementation or measured output | Does supplied evidence support this claim? | Narrow the claim or gather the missing proof |
|
|
187
|
+
| Commit, push and PR | Existing deterministic facts and command results | Existing checks only | Model advice cannot change gate outcomes |
|
|
188
|
+
|
|
189
|
+
Questions and possible next actions live in a fixed catalog. Noul supplies a
|
|
190
|
+
probability for one property. Choice selects an assertion category. There is
|
|
191
|
+
no overall quality score, model-written command or automatic owner decision.
|
|
192
|
+
The agent invokes advice explicitly. Skill instructions explain optional timing;
|
|
193
|
+
hooks never upload source and never request a model answer.
|
|
194
|
+
|
|
195
|
+
### Evidence and upload
|
|
196
|
+
|
|
197
|
+
A stage-specific manifest names the required behavior and role-labeled source
|
|
198
|
+
references. Each reference selects a complete file, TypeScript function, named
|
|
199
|
+
test, or Markdown section. Missing, ambiguous, escaping and oversized inputs
|
|
200
|
+
are refused before inference. Evidence remains data even when it contains
|
|
201
|
+
instructions. Necessary unchanged context must be named by the manifest.
|
|
202
|
+
|
|
203
|
+
The shipped command uses the official TypeSafe System One API and pins
|
|
204
|
+
`jev-1.13.0`. Only `--refresh` permits a live request. The provider key comes
|
|
205
|
+
from `TYPESAFE_API_KEY` at runtime. A passing secret scan is required for the
|
|
206
|
+
entire selected state before any request. Source and credentials stay out of
|
|
207
|
+
reports and error messages. Limits cover source, state, request and response
|
|
208
|
+
bytes, item count, subprocess duration, fetch and body-reading duration.
|
|
209
|
+
Requests are sequential and receive no automatic retries.
|
|
210
|
+
|
|
211
|
+
Evidence selection uses Babel's JavaScript parser in a bounded Bun worker.
|
|
212
|
+
The installed command runs TypeScript source through Bun, with the same `bunx`
|
|
213
|
+
installation as 0.10.x. TypeScript 7 supplies development checks. The shipped
|
|
214
|
+
runtime has no native compiler dependency or compiler installation step.
|
|
215
|
+
|
|
216
|
+
### Replay and proof
|
|
217
|
+
|
|
218
|
+
Default mode reads a local exact-input replay. Identity binds project root,
|
|
219
|
+
model, catalog definitions, requirements, selectors and selected source bytes.
|
|
220
|
+
A changed input or invalid record is incomplete. Replay files include typed
|
|
221
|
+
answers and integrity metadata, without source text. Local replay is editable
|
|
222
|
+
by the repository owner and is advisory evidence, never approval or a gate.
|
|
223
|
+
|
|
224
|
+
A consumer experiment uses a new `agentsfleet` worktree and the locally packed,
|
|
225
|
+
unpublished 0.11.0 package. The controls compare the same incorrect locale code
|
|
226
|
+
with a weak assertion and an exact assertion, plus healthy exact behavior.
|
|
227
|
+
Repeated live observations report successes, misses, uncertainty, latency and
|
|
228
|
+
token usage. The trial proves bounded usefulness only; broader accuracy and
|
|
229
|
+
runtime superiority require different evidence.
|
package/docs/RELEASE_TEMPLATE.md
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
|
-
# Release
|
|
1
|
+
# Release documentation template
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Use the consuming repository's declared changelog and version source.
|
|
4
|
+
Preserve its selected format; a Markdown changelog does not acquire a Mintlify
|
|
5
|
+
site, sibling checkout or `VERSION` file by installing this pack.
|
|
6
|
+
Use its declared synchronization command when it maintains generated versions.
|
|
7
|
+
|
|
8
|
+
<!-- oracle-packs:start product.agentsfleet -->
|
|
9
|
+
For `agentsfleet`, the changelog is `~/Projects/docs/changelog.mdx` and `VERSION`
|
|
10
|
+
is the binary version source. `make sync-version` updates `build.zig.zon`,
|
|
11
|
+
`agentsfleet/package.json` and `agentsfleet/src/cli.js`.
|
|
12
|
+
New `<Update>` blocks go after the leading `<Tip>` or `<Note>`.
|
|
13
|
+
<!-- oracle-packs:end -->
|
|
14
|
+
|
|
15
|
+
For a repository already using Mintlify, use the block and label rules below.
|
|
16
|
+
Other formats carry the same applicable upgrading, behavior and API information
|
|
17
|
+
in their existing entry structure.
|
|
4
18
|
|
|
5
19
|
## Block template
|
|
6
20
|
|
|
@@ -23,7 +37,7 @@ Source of truth: `~/Projects/docs/changelog.mdx`. New `<Update>` blocks go at th
|
|
|
23
37
|
{User-visible bugs fixed — observed behavior before/after. Omit if none.}
|
|
24
38
|
|
|
25
39
|
## CLI
|
|
26
|
-
{
|
|
40
|
+
{Command additions or shape changes. Omit if none.}
|
|
27
41
|
</Update>
|
|
28
42
|
```
|
|
29
43
|
|
|
@@ -36,11 +50,13 @@ Source of truth: `~/Projects/docs/changelog.mdx`. New `<Update>` blocks go at th
|
|
|
36
50
|
- Every breaking change appears under `Upgrading` with a migration step, even if also mentioned elsewhere.
|
|
37
51
|
- Body copy may reference a past entry by date (`"…that shipped on Apr 22, 2026"`); do not reference past releases by semver (`"shipped in v0.27.0"`) — that drags the two timelines back together.
|
|
38
52
|
|
|
39
|
-
## Version bumps (
|
|
53
|
+
## Version bumps (the repository's version source)
|
|
40
54
|
|
|
41
55
|
- Feature milestone → minor (`0.7.0` → `0.8.0`).
|
|
42
56
|
- Bug fix → patch.
|
|
43
57
|
- Pre-v1.0 breaking → minor (semver 0.x carve-out); call out under Upgrading.
|
|
44
58
|
- Post-v1.0 breaking → major.
|
|
45
59
|
- Internal-only refactor: terse `<Update>` with `tags={["Internal", ...]}`, one-paragraph summary, skip section structure. Prefer folding into the next user-visible release.
|
|
46
|
-
- Parallel branches
|
|
60
|
+
- Parallel branches reconcile their version source against the current default
|
|
61
|
+
branch and run the repository's declared synchronization check. This never
|
|
62
|
+
authorizes rebasing or force-pushing a published branch.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# REST API Design Guidelines
|
|
1
|
+
# REST API Design Guidelines
|
|
2
2
|
|
|
3
3
|
**Status:** Canonical instruction set. Read this before adding, modifying, or removing any HTTP endpoint.
|
|
4
4
|
**Trigger:** the global instruction `HTTP handler or OpenAPI changes → read docs/REST_API_DESIGN_GUIDELINES.md first` fires when the diff touches a handler, `public/openapi.json`, or any `route_*` file. If you're an agent reading this — you got here because that trigger fired. Follow this doc as a checklist, not as background reading.
|
|
@@ -9,10 +9,11 @@ This is a goal-oriented instruction set. Each rule states the goal it serves so
|
|
|
9
9
|
|
|
10
10
|
## Audience — who this binds
|
|
11
11
|
|
|
12
|
-
This
|
|
12
|
+
This guide binds the author and reviewer in the consuming repository.
|
|
13
|
+
Publishing and merge authorization come from that repository's operating model.
|
|
13
14
|
|
|
14
15
|
- **The agent** runs the Quick checklist below as part of `CHORE(close)` and the §10 pre-PR gate, opens the PR via `gh pr create`, and answers `orly-babysit-prs` review feedback. The agent is the primary enforcer.
|
|
15
|
-
- **
|
|
16
|
+
- **The human author** follows the same checklist when working without an agent.
|
|
16
17
|
- **A reviewer** (human or `/review`) checks the PR against this doc adversarially. A red box on the checklist that's not justified in the PR description is grounds to block merge.
|
|
17
18
|
|
|
18
19
|
When this doc says "you" it means the agent or the human author — same rules either way. When it says "MUST" it means a missing or wrong implementation blocks merge; "SHOULD" means deviate only with a one-line rationale in the PR description.
|
|
@@ -21,14 +22,16 @@ When this doc says "you" it means the agent or the human author — same rules e
|
|
|
21
22
|
|
|
22
23
|
## Quick checklist — adding an endpoint
|
|
23
24
|
|
|
24
|
-
Run this checklist
|
|
25
|
+
Run this checklist at the repository's review boundary before creating a Pull
|
|
26
|
+
Request (PR). Every applicable item needs evidence or an owner-approved
|
|
27
|
+
exception; an unchecked item cannot silently become a pass.
|
|
25
28
|
|
|
26
29
|
- [ ] **URL design** — plural noun resource, hierarchical path, no verbs (§1); operation-style `:verb` declared as one of the three allowed categories (§1)
|
|
27
30
|
- [ ] **Path params + trailing slash** — `{resource_id}` matches body field name; no trailing slash (§1)
|
|
28
31
|
- [ ] **HTTP method** chosen by semantics; PATCH idempotency guarantee stated; `Idempotency-Key` honored if applicable (§2)
|
|
29
32
|
- [ ] **Long-running ops** use the canonical `202 + /v1/operations/{id}` shape (§2)
|
|
30
33
|
- [ ] **Request body shape** matches the path (no path-param IDs in body) (§3)
|
|
31
|
-
- [ ] **Pagination** uses
|
|
34
|
+
- [ ] **Pagination** uses keyset cursors with shared, declared default and maximum bounds (§3)
|
|
32
35
|
- [ ] **List envelope** is exactly `{items, total: int|null, next_cursor: string|null}` — no synonyms (§3)
|
|
33
36
|
- [ ] **Bulk endpoints** use `207` with the canonical per-item shape (§3)
|
|
34
37
|
- [ ] **Null vs omit** — absent optionals omitted, `null` reserved for "explicitly cleared" (§3)
|
|
@@ -37,10 +40,10 @@ Run this checklist as part of `CHORE(close)` (per `~/.claude/CLAUDE.md` lifecycl
|
|
|
37
40
|
- [ ] **Status codes** — 409 includes `current_state`; 412 includes `etag`; 429 includes `Retry-After` + `X-RateLimit-*` (§4)
|
|
38
41
|
- [ ] **ETag/`If-Match`** wired for any resource with realistic concurrent edits (§4)
|
|
39
42
|
- [ ] **Error responses** use the registry; `detail` follows hygiene rules (no IDs, no SQL, no paths, ≤200 chars) (§5)
|
|
40
|
-
- [ ] **OpenAPI document**
|
|
41
|
-
- [ ] **Route registered** in
|
|
42
|
-
- [ ] **Handler signature**
|
|
43
|
-
- [ ] **
|
|
43
|
+
- [ ] **OpenAPI document** matches the repository's canonical source and declared generation or validation checks (§6)
|
|
44
|
+
- [ ] **Route registered** in the repository's actual router and discovery graph (§7)
|
|
45
|
+
- [ ] **Handler signature** follows its framework and uses the inputs it reads (§8)
|
|
46
|
+
- [ ] **Authentication and ownership** are proved on the served route before data access (§7–§8)
|
|
44
47
|
- [ ] **Versioning** — added/renamed/removed surface listed in PR description; deprecation uses `Deprecation` + `Sunset` headers; new response fields declare `x-stability` (§9)
|
|
45
48
|
- [ ] **Tests** — happy path + one error per refusal + idempotency double-PATCH + `Idempotency-Key` replay (where applicable) + ETag mismatch (§10)
|
|
46
49
|
- [ ] **Logging** — sensitive ID values are DEBUG-only or carry `// log-id-allowed:` comment; secret-shaped fields are write-only or one-time-read (§11)
|
|
@@ -215,7 +218,15 @@ GET /products?status=active&sort=-created_at&starting_after=01HZQ...&limit=50
|
|
|
215
218
|
- **Time ranges:** `?created_after=<ts_ms>&created_before=<ts_ms>`. Bracket grammar (`?created_at[gte]=...`) is forbidden.
|
|
216
219
|
- **No boolean explosions.** Don't add `?include_x=true&include_y=true` — use `?include=x,y` with a documented enum of legal values, OR don't expose a knob.
|
|
217
220
|
- **Sorting:** `sort=field` ascending; `sort=-field` descending. Single sort key per request — no multi-key.
|
|
218
|
-
- **Pagination —
|
|
221
|
+
- **Pagination — keyset.** Request: `?starting_after=<resource_id>&limit=<int>`;
|
|
222
|
+
response: `next_cursor: <resource_id> | null`. Send `next_cursor` back as the
|
|
223
|
+
next request's `starting_after`; use shared repository parsing and constants
|
|
224
|
+
for the default and maximum, with bounds tested at the served endpoint.
|
|
225
|
+
<!-- oracle-packs:start product.agentsfleet -->
|
|
226
|
+
- For `agentsfleet`, use `afd_core::paging::cursor`, `Page::parse` and its route
|
|
227
|
+
`Ceiling`, or `afd_validate::Limit::parse`. `DEFAULT_LIMIT` is 50 and
|
|
228
|
+
`MAX_LIMIT` is 100; an empty limit uses the route default.
|
|
229
|
+
<!-- oracle-packs:end -->
|
|
219
230
|
- **Sparse fieldsets / `?include=` / `?fields=`:** not supported in v1. If you need to slim a payload, design a smaller endpoint. Don't invent.
|
|
220
231
|
|
|
221
232
|
### Bulk operations
|
|
@@ -242,7 +253,9 @@ This rule is binding on responses AND requests. SDK consumers branch on `field =
|
|
|
242
253
|
|
|
243
254
|
### IDs
|
|
244
255
|
|
|
245
|
-
-
|
|
256
|
+
- Preserve the repository's documented public identifier format and test its
|
|
257
|
+
parsing at the endpoint boundary. Do not substitute another product's format.
|
|
258
|
+
- `agentsfleet` uses Universally Unique Identifier version 7 (UUIDv7) for public identifiers. <!-- oracle-packs:product.agentsfleet -->
|
|
246
259
|
- Do not expose database serial integers.
|
|
247
260
|
- Sensitive IDs (workspace_id, agent_id) live in the path, not the body. Never log their values at INFO level (§11).
|
|
248
261
|
|
|
@@ -252,6 +265,11 @@ This rule is binding on responses AND requests. SDK consumers branch on `field =
|
|
|
252
265
|
|
|
253
266
|
### Success — return the wire type
|
|
254
267
|
|
|
268
|
+
Return the repository's typed response through its framework's response
|
|
269
|
+
renderer. Share the public response shape with its schema source so field names,
|
|
270
|
+
status and content type stay consistent.
|
|
271
|
+
|
|
272
|
+
<!-- oracle-packs:start product.agentsfleet -->
|
|
255
273
|
```rust
|
|
256
274
|
Ok(Json(FleetDetailResponse::from(&detail)).into_response())
|
|
257
275
|
Ok((StatusCode::CREATED, Json(CreatedResponse { id, key })).into_response())
|
|
@@ -262,6 +280,7 @@ The wire type owns the field names and `IntoResponse` writes the status and
|
|
|
262
280
|
content-type. A response shape belongs in `afd_wire`, not spelled inline in a
|
|
263
281
|
handler, so the same struct is what the OpenAPI document is generated from.
|
|
264
282
|
Build a response by hand only for a Server-Sent Events stream.
|
|
283
|
+
<!-- oracle-packs:end -->
|
|
265
284
|
|
|
266
285
|
### Status codes
|
|
267
286
|
|
|
@@ -323,13 +342,20 @@ For any resource where concurrent edits are realistic (anything mutable that two
|
|
|
323
342
|
|
|
324
343
|
### Use the error registry
|
|
325
344
|
|
|
326
|
-
|
|
345
|
+
Use the repository's error registry and renderer for status, title and public
|
|
346
|
+
documentation links. Handlers supply the code and a safe human-readable detail;
|
|
347
|
+
they do not duplicate the registry's response shape.
|
|
348
|
+
|
|
349
|
+
<!-- oracle-packs:start product.agentsfleet -->
|
|
350
|
+
The `agentsfleet` registry is `rustd/crates/afd_core/src/error_code.rs` and its
|
|
351
|
+
family modules. Its handlers use these refusal constructors:
|
|
327
352
|
|
|
328
353
|
```rust
|
|
329
354
|
Refusal::malformed(DETAIL_WORKSPACE_ID) // the sentence is a constant
|
|
330
355
|
Refusal::coded(FLEET_NOT_FOUND, DETAIL_NOT_FOUND)
|
|
331
356
|
Refusal::preconditioned(error.code(), error.detail(), current)
|
|
332
357
|
```
|
|
358
|
+
<!-- oracle-packs:end -->
|
|
333
359
|
|
|
334
360
|
Never assemble a `Problem` by hand and never write a status and body directly:
|
|
335
361
|
the status, title and documentation link come from the registry entry, and a
|
|
@@ -371,16 +397,20 @@ The title must be safe to render verbatim in a UI toast — think "what would I
|
|
|
371
397
|
- State: `"<noun> already exists"` / `"<noun> not found"` / `"<noun> expired"` — `Agent name already exists`, `token expired`.
|
|
372
398
|
- Format help: `"<param>: use <format>"` — `invalid_since_format: use Go-style duration (15s, 30m, 2h, 7d) or RFC 3339 (YYYY-MM-DDTHH:MM:SSZ)`.
|
|
373
399
|
|
|
374
|
-
When
|
|
400
|
+
When writing a refusal, read the closest existing handler and the repository's
|
|
401
|
+
canonical renderer before choosing the shape.
|
|
375
402
|
|
|
376
403
|
### Internal 500s — direct calls
|
|
377
404
|
|
|
378
|
-
A datastore or service failure
|
|
379
|
-
|
|
405
|
+
A datastore or service failure uses the repository's canonical refusal renderer.
|
|
406
|
+
Name the failed operation in internal diagnostics without exposing its details
|
|
407
|
+
to the caller.
|
|
380
408
|
|
|
409
|
+
<!-- oracle-packs:start product.agentsfleet -->
|
|
381
410
|
```rust
|
|
382
411
|
services.fleet_detail(&context, fleet_id).await.map_err(Refusal::at(FLEET_READ))?
|
|
383
412
|
```
|
|
413
|
+
<!-- oracle-packs:end -->
|
|
384
414
|
|
|
385
415
|
The operation constant is what identifies the failure in logs and telemetry;
|
|
386
416
|
the caller gets the registry's 500 and no internal detail.
|
|
@@ -410,6 +440,11 @@ Don't invent other extensions without amending this doc.
|
|
|
410
440
|
|
|
411
441
|
## §6 — OpenAPI editing
|
|
412
442
|
|
|
443
|
+
Locate the repository's canonical OpenAPI source. Update that source and run
|
|
444
|
+
its declared generation or validation command; do not assume a Rust daemon,
|
|
445
|
+
generated artifact or build target from another product.
|
|
446
|
+
|
|
447
|
+
<!-- oracle-packs:start product.agentsfleet -->
|
|
413
448
|
**The document is generated. There is nothing to hand-edit.**
|
|
414
449
|
|
|
415
450
|
`public/openapi.json` is emitted from the daemon's own handlers — the route
|
|
@@ -449,8 +484,15 @@ generated document, so a description that breaks the wording rules fails
|
|
|
449
484
|
for maintainers rather than for API consumers belongs in a `//` comment beside
|
|
450
485
|
it, which the document does not carry.
|
|
451
486
|
|
|
487
|
+
<!-- oracle-packs:end -->
|
|
452
488
|
## §7 — Registering a route
|
|
453
489
|
|
|
490
|
+
Register the served method and path in the repository's router and discovery
|
|
491
|
+
graph. Prove authentication and resource ownership are enforced before access;
|
|
492
|
+
a helper that no served route mounts is not evidence of authorization.
|
|
493
|
+
|
|
494
|
+
<!-- oracle-packs:start product.agentsfleet -->
|
|
495
|
+
|
|
454
496
|
**The router is built FROM the route table, not beside it.** `Route::all()` is
|
|
455
497
|
walked once at startup and every template it yields is mounted, so a path
|
|
456
498
|
cannot be served under a spelling the table does not carry, and it cannot be
|
|
@@ -582,8 +624,16 @@ When in doubt, mirror an existing handler:
|
|
|
582
624
|
| Signature-proven ingress | `rustd/crates/afd_api_ingress/src/handler/webhook/receive_route.rs` |
|
|
583
625
|
| A runner speaking for itself | `rustd/crates/afd_api_runner/src/handler/runner/lease.rs` |
|
|
584
626
|
|
|
627
|
+
<!-- oracle-packs:end -->
|
|
585
628
|
## §8 — Handler signature rule
|
|
586
629
|
|
|
630
|
+
Follow the repository's framework and read its canonical handler first.
|
|
631
|
+
Use validated inputs and the shared response and error renderers.
|
|
632
|
+
Enforce authentication and ownership through its canonical mechanism, with tests
|
|
633
|
+
against the actual served route; do not duplicate mounted checks by habit.
|
|
634
|
+
|
|
635
|
+
<!-- oracle-packs:start product.agentsfleet -->
|
|
636
|
+
|
|
587
637
|
A handler is an axum handler. The router built it into a stack that has already
|
|
588
638
|
admitted the request, proven the caller, checked the capability and confirmed
|
|
589
639
|
ownership, so a handler receives what it needs as extractors and constructs
|
|
@@ -612,7 +662,14 @@ pub async fn my_endpoint<D: Services>(
|
|
|
612
662
|
envelope is built for you.
|
|
613
663
|
- **Bounds are declared on the request type**, with `garde`, not re-spelled per
|
|
614
664
|
handler. The refusal sentence a field earns is mapped from the path `garde`
|
|
615
|
-
reports
|
|
665
|
+
reports, through a `const` `afd_validate::Sentences` table beside the
|
|
666
|
+
handler (`PathTable<Variant>` when a crate answers with its own error
|
|
667
|
+
variant). A rule garde lacks — `finite`, `nul_free`, `ascii_digits`,
|
|
668
|
+
`charset` — comes from `afd_validate`, never a one-off check.
|
|
669
|
+
- **A parser a bound protects takes `&garde::Valid<T>`.** garde runs every
|
|
670
|
+
rule on a field with no short-circuit, so a bound and a parser on one field
|
|
671
|
+
would still hand the parser oversized input; the bound goes on a struct and
|
|
672
|
+
the parser accepts only the proved value.
|
|
616
673
|
- **Never authenticate inside a handler.** The guard on the route's row did it.
|
|
617
674
|
Never call an ownership check by hand either; the template mounted it.
|
|
618
675
|
- **Refusal sentences live beside the parser that produces them**, as
|
|
@@ -621,12 +678,15 @@ pub async fn my_endpoint<D: Services>(
|
|
|
621
678
|
### What NOT to do
|
|
622
679
|
|
|
623
680
|
- ❌ Reading a query string directly for `limit` or `starting_after` — use
|
|
624
|
-
`afd_core::paging`.
|
|
681
|
+
`afd_core::paging`, or `afd_validate::Limit` with the route's `Ceiling`.
|
|
682
|
+
- ❌ A hand-written function from a `garde::Report` to a sentence — declare a
|
|
683
|
+
`Sentences` table.
|
|
625
684
|
- ❌ Building a `Problem` by hand — construct it from the declared error code so
|
|
626
685
|
the status, title and documentation link come from the registry (§5).
|
|
627
686
|
- ❌ A second unique spelling of a capability check inside the handler body.
|
|
628
687
|
- ❌ Re-parsing a path parameter the extractor already typed.
|
|
629
688
|
|
|
689
|
+
<!-- oracle-packs:end -->
|
|
630
690
|
## §9 — Versioning
|
|
631
691
|
|
|
632
692
|
URI-based: `/v1/...`. All current endpoints sit under `/v1`. Bump to `/v2` only when a breaking change is unavoidable; default to additive evolution within `/v1`.
|
|
@@ -697,11 +757,10 @@ Every PR that changes the HTTP surface MUST open its description with a "Surface
|
|
|
697
757
|
|
|
698
758
|
Before opening a PR touching any handler:
|
|
699
759
|
|
|
700
|
-
- [ ]
|
|
701
|
-
- [ ] `zig build test` passes
|
|
760
|
+
- [ ] Declared build and unit commands have observed successful results
|
|
702
761
|
- [ ] the declared `verify.unit` command passes — the route-scope match and its tests cover the auth gate matrix
|
|
703
762
|
- [ ] the repository's integration suite passes end to end against real datastores, where it declares one
|
|
704
|
-
- [ ]
|
|
763
|
+
- [ ] Applicable platform targets and test graphs match the repository's declared matrix
|
|
705
764
|
- [ ] the declared `verify.lint` command passes — every language gate the repository declares
|
|
706
765
|
- [ ] Handler file ≤ 350 lines; split if it grows
|
|
707
766
|
- [ ] Integration test covers the happy path AND at least one error path per refusal the handler can return
|
|
@@ -729,12 +788,18 @@ Before opening a PR touching any handler:
|
|
|
729
788
|
|
|
730
789
|
## §12 — Performance
|
|
731
790
|
|
|
732
|
-
|
|
791
|
+
Use the consuming repository's declared performance budgets and benchmark lane.
|
|
792
|
+
Measure applicable latency percentiles, memory and query bounds under the load
|
|
793
|
+
profile the endpoint is expected to serve.
|
|
794
|
+
|
|
795
|
+
<!-- oracle-packs:start product.agentsfleet -->
|
|
796
|
+
`agentsfleet` targets (measured by its declared benchmark lane):
|
|
733
797
|
|
|
734
798
|
- p99 latency < 200 ms
|
|
735
799
|
- p95 latency < 150 ms
|
|
736
800
|
- Zero allocator leaks (`std.testing.allocator` integration tests pass)
|
|
737
801
|
- No unbounded query loops. Pagination caps live in §3 (default `limit=50`, max `limit=100`).
|
|
802
|
+
<!-- oracle-packs:end -->
|
|
738
803
|
|
|
739
804
|
If your endpoint can't meet these in a normal load profile, the spec's "Performance Considerations" section MUST contain ALL of:
|
|
740
805
|
|
package/docs/RULE_ENFORCEMENT.md
CHANGED
|
@@ -6,15 +6,15 @@ regenerates this file and fails on any difference. To update it, run
|
|
|
6
6
|
|
|
7
7
|
| Rule document | enforced by | judged | acknowledged | classified | trigger |
|
|
8
8
|
|---|---|--:|--:|--:|---|
|
|
9
|
-
| `docs/LOGGING_STANDARD.md` | `LOG` → `logging.sh` |
|
|
10
|
-
| `docs/REST_API_DESIGN_GUIDELINES.md` | — | 0 | 0 | 0/
|
|
11
|
-
| `docs/SCHEMA_CONVENTIONS.md` | — | 0 | 0 | 0/
|
|
9
|
+
| `docs/LOGGING_STANDARD.md` | `LOG` → `logging.sh` | 10 | 13 | 28/28 | mechanical |
|
|
10
|
+
| `docs/REST_API_DESIGN_GUIDELINES.md` | — | 0 | 0 | 0/67 | mechanical |
|
|
11
|
+
| `docs/SCHEMA_CONVENTIONS.md` | — | 0 | 0 | 0/17 | mechanical |
|
|
12
12
|
| `docs/DOCUMENTATION_RULES.md` | — | 0 | 0 | 0/22 | latent |
|
|
13
13
|
| `docs/LIFECYCLE_PATTERNS.md` | — | 0 | 0 | 0/22 | mechanical |
|
|
14
|
-
| `docs/CHANGELOG_VOICE.md` | — | 0 | 0 | 0/
|
|
14
|
+
| `docs/CHANGELOG_VOICE.md` | — | 0 | 0 | 0/3 | latent |
|
|
15
15
|
| `docs/VERIFY_TIERS.md` | — | 0 | 0 | 0/4 | uncited |
|
|
16
|
-
| `docs/greptile-learnings/RULES.md` | — | 0 | 0 | 0/
|
|
17
|
-
| **corpus** | | | | **
|
|
16
|
+
| `docs/greptile-learnings/RULES.md` | — | 0 | 0 | 0/115 | mechanical |
|
|
17
|
+
| **corpus** | | | | **28/278** | |
|
|
18
18
|
|
|
19
19
|
## How to read this
|
|
20
20
|
|