Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 32 additions & 5 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -584,13 +584,26 @@ For each language recon cleared, do the AST work and produce a `RepoInventory`:
`@trustabl/agent-reliability-otel-labels` is imported), `run_start` (`<run>.mark_start(...)` /
`<run>.markStart(...)` — receiver required, since it is a method on `Run`),
`tool_span` (`mark_tool_span` / `markToolSpan`) and `run_end` (`mark_run_end`
/ `markRunEnd`). The call names are plausible names for a project's own
/ `markRunEnd`). `run_construct` records a `Run()` / `new Run()` resolved through
the file's own import (never repo-wide: `Run` is too generic a name), with
`ModuleScope` (built once: no enclosing function, a Python class body, a
TypeScript/JavaScript `static` class field, or a Python default parameter; a
non-static TypeScript/JavaScript class field initializer runs per instance and
is exempt, as is a Python `__main__` guard, parenthesized or not) and `RunIDConst`
(a string-literal run id). The call names are plausible names for a project's own
helpers, so they count only when the library is imported somewhere in the
repo; each file's own imports are followed, so a renamed import
(`mark_tool_span as mts`, `markToolSpan as label`) still resolves. Every
signal carries `TestOrigin` when its file classifies as a test
(`pathclass.Classify`). That gate is repo-wide, not per-file: a `Run` is
routinely built in one module and started in another that imports nothing.
(`mark_tool_span as mts`, `markToolSpan as label`) still resolves. That gate
is repo-wide, not per-file: a `Run` is routinely built in one module and
started in another that imports nothing. Every signal carries `TestOrigin`
when its file classifies as a test (`pathclass.Classify`).
`tool_span` signals carry `FailureSafe` (inside `finally` / `except` /
`catch` before the enclosing function, in a named error callback, or in a
function passed to `.finally(` / `.catch(`), `HookUnknown` (an `on_tool_end`
method of a `RunHooks` / `AgentHooks` subclass, whose failure behaviour is
unverified), `AttemptConst` (an integer-literal `attempt`) and the literal
`SideEffect`. `run_end` signals carry `ErrorPath` (except / catch / error
callback / `.catch(`, never `finally`) and the literal `ExitReason`.
`attr_literal` records a label key written to a span by hand
(`set_attribute` / `setAttribute` first argument, or a key of the literal
passed to `set_attributes` / `setAttributes`), collected whether or not the
Expand Down Expand Up @@ -625,6 +638,20 @@ For each language recon cleared, do the AST work and produce a `RepoInventory`:
do not count). The predicates prove the calls exist, not that labels land:
with no current span each call is a silent no-op.

Four more repo-scope predicates back `OBS-009..012`, which check that the
labels written are right, not only present: `repo_otel_labels_run_shared`
(a `run_construct` with `ModuleScope` or `RunIDConst`),
`repo_otel_labels_tool_span_failure_unsafe` (tool-span labels exist, none is
`FailureSafe`; `HookUnknown` labels are left out),
`repo_otel_labels_attempt_constant` (every tool-span label has
`AttemptConst`) and `repo_otel_labels_run_end_success_only` (no run end has
`ErrorPath`, a literal `"error"`, or a variable reason). All four drop
test-file signals, and one correct call credits the repo. A repo finding
whose rule asserts one of them carries the offending call's file and line
(`otelLabelsEvidence` in `rule_detector.go`); every other repo finding keeps
an empty location. Hand-written `trustabl.*` keys credit the `OBS-006..008`
ladder but are not read by these four.

- **DiscoverSubagents** (`subagents.go`) — **hybrid** discovery in two passes.
Pass 1 reads every `.claude/agents/*.md` component (matched at any path depth
— monorepos that nest agent projects under `agent/.claude/agents/` or
Expand Down
7 changes: 7 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,13 @@ When changing a rule (add / remove / edit severity, confidence, match, text):
> OTel GenAI semconv is still Development with renamed keys), and **rank 4** (run-level correlation id — session / `group_id` — needs a
> run-call kwarg predicate, tracked with the HTTP-entrypoint design ticket). See `COVERAGE.md`.
>
> **agent-reliability-otel-labels correctness, Batch 1 (2026-10-08, `schema_version` 26 → 27):** the fixture now holds **347** rules
> (343 + 4; re-derive, do not trust this figure). Built in parallel with LC-116 (21 → 22) and the `agent_config` pack (22 → 26), which merged first, so this batch takes 27. **OBS-009** (shared `Run`) / **OBS-010** (tool span labelled only on success) /
> **OBS-011** (constant `attempt`) / **OBS-012** (run end only on success) read new facts on `OtelLabelsSignal`; test-file
> signals never count and findings point at the offending call. Hand-written `trustabl.*` keys now credit OBS-006..008.
> Spec: `.superpowers/specs/2026-10-04-otel-labels-correctness-rules-design.md`. Not built: the handoff rule (spec O7),
> the `side_effect` rules (Batch 2). OBS-009..012 must not reach production before library 0.1.1 is published (spec O1): the 0.1.0 README example trips all four.
>
> **agent-reliability-otel-labels batch (2026-10-04, `schema_version` 20 → 21):** the fixture now holds **333** rules
> (330 + 3; re-derive, do not trust this figure). Built in parallel with the HTTPS-only batch, which had already taken
> 19 → 20, so this batch takes 21. **OBS-006** / **OBS-007** / **OBS-008** are a mutually exclusive
Expand Down
Loading
Loading