summaryrefslogtreecommitdiffhomepage
path: root/.dispatch
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-06 22:23:23 +0900
committerAdam Malczewski <[email protected]>2026-06-06 22:23:23 +0900
commit219cf053fad4e48b22590d3178438bf5d67d04e3 (patch)
tree5d04a3105efc793de8ad3b3cf1c584f8b176dc27 /.dispatch
parent2c5bc242a8a99e3b863c247f70b26f5883333677 (diff)
downloaddispatch-219cf053fad4e48b22590d3178438bf5d67d04e3.tar.gz
dispatch-219cf053fad4e48b22590d3178438bf5d67d04e3.zip
docs(harness): author extension-logging rule (close the pending logging gap)
The .dispatch/rules/extension-logging.md rule was '(pending)' in ORCHESTRATOR §3 for the entire life of the observability substrate, so every extension summon was built without logging/self-redaction guidance — leaving most extensions silent (a coverage audit found conversation-store, transport-http, credential-store, tool-read-file, storage-sqlite, auth-apikey, surface-* all with zero logger refs). - Author .dispatch/rules/extension-logging.md (tribal-knowledge only, P6/P7): self-redact your own secrets in your own code (no shared helper; §6 tiers), use injected host.logger/ctx.log, flat scalar attrs, no token-delta logging, one-way logs, edge verbatim capture. - Wire it into ORCHESTRATOR §3 as 'every extension' — include on EVERY extension summon; remove the (pending) note. - Record the coverage audit + remaining instrumentation debt (#1 reconcile.repair span in conversation-store, #2 transport-edge logging) in tasks.md. Future extensions now get logging by construction.
Diffstat (limited to '.dispatch')
-rw-r--r--.dispatch/rules/extension-logging.md24
1 files changed, 24 insertions, 0 deletions
diff --git a/.dispatch/rules/extension-logging.md b/.dispatch/rules/extension-logging.md
new file mode 100644
index 0000000..14dce2d
--- /dev/null
+++ b/.dispatch/rules/extension-logging.md
@@ -0,0 +1,24 @@
+# Rule: extension logging + self-redaction
+
+Use the injected `host.logger` (and the `ctx.log` / span you're handed) — never
+`console.*`, never a hand-rolled logger, never your own correlation ids. `extensionId`
+is auto-stamped by the host: do NOT set it or invent an id scheme.
+
+- **Self-redact your OWN secrets, in your OWN code, at the log call-site.** There is no
+ shared `redact()` and nothing in the kernel does it for you — you alone know what is
+ secret and how to censor it (isolation over DRY). Mask BEFORE the record is built so a
+ raw secret never reaches the sink/journal.
+- **Redaction = partial mask, keep the field present + diffable** (never drop it): reveal
+ first+last real chars with a fixed-width `…redacted…` middle, graduated by length —
+ `≥13`→reveal 3 each side · `11–12`→2 · `8–10`→1 · `≤7`→full mask. Reimplement this
+ locally per extension; declare your own secret fields/headers (e.g. the `authorization`
+ header + any vault-injected body field).
+- **Edge I/O (providers/transports): capture verbatim, post-transform, at the fetch edge**
+ (the bytes that hit the wire = ground truth), self-redacting secret headers/fields. Put
+ large verbatim payloads in the span `body`, not in attributes.
+- **Attributes are flat scalars** (string/number/boolean/null) — nest → stringify. Spans:
+ open at the work's start, `end()` at its finish, so a crashed turn is reconstructable.
+- **Do NOT log token deltas / per-chunk streaming** — high-frequency and redundant (the
+ chunk log already has the final text).
+- **Logs are one-way**: never read another extension's logs; cross-feature reaction is a
+ hook/service, not a log. Logging never blocks or fails a turn — emit and move on.