clearotron 0.4.0-beta.0 → 0.4.0-beta.2
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/.env.example +9 -0
- package/INSTALL.md +4 -31
- package/README.md +5 -5
- package/bin/brandowner.mjs +1 -1
- package/bin/onboard.mjs +18 -74
- package/bin/start.mjs +58 -14
- package/bin/update.mjs +10 -2
- package/build-info.json +2 -2
- package/demo/full-country-search/run/_driver/search-policy.json +1 -1
- package/demo/full-country-search/run/status.json +1 -1
- package/demo/global-preliminary-search/run/_driver/search-policy.json +1 -1
- package/demo/global-preliminary-search/run/status.json +1 -1
- package/demo/knockout-search/run/_driver/search-policy.json +1 -1
- package/demo/knockout-search/run/status.json +1 -1
- package/demo/multi-country-focus-search/run/_driver/search-policy.json +1 -1
- package/demo/multi-country-focus-search/run/status.json +1 -1
- package/docs/README.md +1 -0
- package/docs/SECURITY-OWASP.md +298 -0
- package/docs/SECURITY.md +18 -13
- package/docs/architecture/02-architecture.md +5 -5
- package/docs/architecture/03-run-lifecycle.md +28 -29
- package/docs/architecture/04-configuration-reference.md +5 -10
- package/docs/architecture/05-config-governance.md +5 -7
- package/docs/architecture/06-operations-runbook.md +0 -12
- package/docs/architecture/07-quality-and-audit.md +12 -13
- package/docs/architecture/09-security-and-data.md +9 -4
- package/driver/CHANGELOG.md +70 -0
- package/driver/ask-ledger.mjs +4 -2
- package/driver/authority-trees.mjs +90 -8
- package/driver/band-shape.mjs +13 -13
- package/driver/blind-frame-model.mjs +1 -1
- package/driver/case-law-ledger.mjs +19 -3
- package/driver/claim-liveness.mjs +30 -1
- package/driver/clearance-variants-record.mjs +10 -3
- package/driver/common-law-receipts.mjs +64 -14
- package/driver/commonlaw-carry.mjs +2 -2
- package/driver/compare.mjs +2 -2
- package/driver/connotation-search.mjs +33 -104
- package/driver/contract-arm2-baseline.json +6 -5
- package/driver/contract-e3-backlog.mjs +62 -62
- package/driver/contract-vocabulary.mjs +38 -31
- package/driver/coverage-form-io.mjs +13 -1
- package/driver/coverage-form.mjs +42 -4
- package/driver/coverage-ledger.mjs +3 -5
- package/driver/cross-check-wait.mjs +43 -0
- package/driver/declination-call.mjs +34 -10
- package/driver/declination-tool.mjs +27 -15
- package/driver/deferral-row.mjs +139 -0
- package/driver/degraded-parts.mjs +377 -0
- package/driver/deliver-trigger.sh +1 -1
- package/driver/demo-container.mjs +4 -1
- package/driver/dev-portal.mjs +5 -5
- package/driver/dispatch-record.mjs +2 -2
- package/driver/driver.config.mjs +193 -96
- package/driver/e2e/README.md +1 -1
- package/driver/effective-scope.mjs +58 -2
- package/driver/engine/anthropic-agent.mjs +103 -27
- package/driver/engine/auth.mjs +2 -2
- package/driver/engine/child-record.mjs +11 -0
- package/driver/engine/cli-version.mjs +4 -3
- package/driver/engine/common.mjs +17 -2
- package/driver/engine/deny-authority-write.mjs +3 -1
- package/driver/engine/engine-env.mjs +174 -0
- package/driver/engine/engine-spawn.mjs +179 -0
- package/driver/engine/mcp/band-server.mjs +1 -1
- package/driver/engine/mcp/clarivate-server.mjs +2 -1
- package/driver/engine/mcp/codex-config.mjs +112 -3
- package/driver/engine/mcp/corsearch-server.mjs +1 -0
- package/driver/engine/mcp/declination-server.mjs +9 -8
- package/driver/engine/mcp/dispositions-server.mjs +2 -1
- package/driver/engine/mcp/euipo-server.mjs +1 -0
- package/driver/engine/mcp/fetch-server.mjs +14 -11
- package/driver/engine/mcp/free-tier-server.mjs +1 -1
- package/driver/engine/mcp/gather-config.mjs +23 -11
- package/driver/engine/mcp/perplexity-server.mjs +97 -17
- package/driver/engine/mcp/probe-server.mjs +43 -21
- package/driver/engine/mcp/public-fetch.mjs +195 -0
- package/driver/engine/mcp/recording-server.mjs +79 -14
- package/driver/engine/mcp/signa-server.mjs +1 -0
- package/driver/engine/mcp/supplemental.mjs +14 -14
- package/driver/engine/mcp/unit-note-server.mjs +50 -1
- package/driver/engine/mcp/uspto-local-server.mjs +1 -0
- package/driver/engine/openai-agent.mjs +109 -28
- package/driver/engine/probe.mjs +152 -19
- package/driver/enqueue-schema.mjs +5 -5
- package/driver/feedback-issues.mjs +1 -1
- package/driver/feedback-store.mjs +1 -1
- package/driver/findings-model.mjs +67 -16
- package/driver/flag-snapshot.mjs +1 -1
- package/driver/floor-duty.mjs +23 -7
- package/driver/form-neighbourhood.mjs +52 -17
- package/driver/frame-diff-model.mjs +3 -3
- package/driver/framework-method.mjs +304 -0
- package/driver/gateway.mjs +49 -21
- package/driver/hand-off-exits.mjs +129 -0
- package/driver/jx-lanes.mjs +1 -1
- package/driver/jx.mjs +8 -5
- package/driver/knockout-assess-record.mjs +7 -1
- package/driver/knockout-frame-record.mjs +96 -34
- package/driver/knockout-review-record.mjs +7 -2
- package/driver/log.mjs +2 -2
- package/driver/matter-frame-record.mjs +31 -2
- package/driver/methodology-witness.mjs +6 -3
- package/driver/named-band.mjs +1 -1
- package/driver/owner-use-check.mjs +45 -10
- package/driver/package.json +1 -1
- package/driver/partial-payload-baseline.json +4 -0
- package/driver/phase0.mjs +2 -2
- package/driver/pipeline-knockout.mjs +256 -129
- package/driver/pipeline.mjs +417 -614
- package/driver/placement-carry.mjs +22 -3
- package/driver/placement-form-io.mjs +18 -4
- package/driver/placement-form.mjs +53 -4
- package/driver/placement-union.mjs +32 -5
- package/driver/portal-report.mjs +3 -3
- package/driver/portal-service.mjs +6 -5
- package/driver/portal-static.mjs +11 -18
- package/driver/predelivery-lint.mjs +10 -10
- package/driver/profile-page.html +5 -5
- package/driver/profiles.mjs +5 -5
- package/driver/progress.mjs +6 -4
- package/driver/provider-usage.mjs +25 -2
- package/driver/publish/index.mjs +97 -25
- package/driver/publish/knockout.mjs +136 -14
- package/driver/publish/profiles-page.mjs +2 -0
- package/driver/publish/publish-inputs.mjs +10 -4
- package/driver/publish/render-knockout.mjs +48 -21
- package/driver/publish/render.mjs +13 -8
- package/driver/publish/report-data.mjs +2 -0
- package/driver/publish/search-depth.mjs +77 -4
- package/driver/publish/templates/report.css +1 -1
- package/driver/publish/xlsx.mjs +34 -15
- package/driver/reasoning-tripwires.mjs +2 -160
- package/driver/recall-receipt.mjs +27 -0
- package/driver/recall-reconciliation.mjs +1 -1
- package/driver/record-carry.mjs +14 -14
- package/driver/recording-agreement.mjs +2 -2
- package/driver/reference-score.mjs +169 -47
- package/driver/register-count.mjs +61 -4
- package/driver/register-digest-record.mjs +14 -1
- package/driver/register-plan.mjs +161 -80
- package/driver/register-records.mjs +37 -4
- package/driver/registration-scripts.mjs +22 -0
- package/driver/registry-fidelity.mjs +4 -4
- package/driver/repair-composers.mjs +23 -7
- package/driver/repair-contract.mjs +1 -1
- package/driver/repairs.mjs +5 -2
- package/driver/reviewer-open-points.mjs +33 -0
- package/driver/rule-shape.mjs +8 -8
- package/driver/run-economics.mjs +3 -3
- package/driver/run-integrity.mjs +2 -2
- package/driver/runner.mjs +17 -5
- package/driver/scope-facts.mjs +89 -12
- package/driver/score-redaction.mjs +247 -0
- package/driver/screen-gate.mjs +1 -1
- package/driver/search-policy.mjs +17 -0
- package/driver/skills/README.md +2 -2
- package/driver/skills/blind-frame/SKILL.md +2 -2
- package/driver/skills/clearance-common-law/SKILL.md +29 -36
- package/driver/skills/clearance-common-law/perplexity-prompts.md +8 -30
- package/driver/skills/clearance-register/SKILL.md +15 -16
- package/driver/skills/clearance-register/digest.md +15 -31
- package/driver/skills/clearance-register/register-recipes.md +14 -56
- package/driver/skills/clearance-register/unit.md +37 -48
- package/driver/skills/clearance-search/SKILL.md +6 -8
- package/driver/skills/clearance-search/delivery-contract.md +0 -7
- package/driver/skills/clearance-search/firm-wide-reasoning.md +5 -4
- package/driver/skills/clearance-search/phase2-execution.md +5 -6
- package/driver/skills/clearance-search/report-prose.md +5 -5
- package/driver/skills/clearance-search/risk-framework-triage.md +2 -2
- package/driver/skills/clearance-search/synthesis-rules.md +9 -9
- package/driver/skills/clearance-search/template-formatting.md +2 -2
- package/driver/skills/clearance-variants/SKILL.md +8 -8
- package/driver/skills/clearance-variants/transliteration-scripts.md +2 -2
- package/driver/skills/frame-diff/SKILL.md +2 -2
- package/driver/skills/knockout-assess/SKILL.md +40 -10
- package/driver/skills/knockout-frame/SKILL.md +42 -10
- package/driver/skills/matter-frame/SKILL.md +12 -5
- package/driver/skills/matter-frame/watchlist-reference.md +1 -1
- package/driver/skills/narrative-refutation/SKILL.md +5 -3
- package/driver/skills/placement-inquiry/SKILL.md +5 -1
- package/driver/stage-context.mjs +27 -6
- package/driver/stages-knockout.mjs +92 -79
- package/driver/stages.mjs +111 -68
- package/driver/stray-artifacts.mjs +9 -5
- package/driver/suite-census.json +696 -150
- package/driver/synthesis-record.mjs +26 -4
- package/driver/systemd/README.md +5 -6
- package/driver/systemd/clearotron-client-mcp.service +24 -0
- package/driver/systemd/clearotron-mcp-face.service +24 -0
- package/driver/systemd/clearotron-portal.service +24 -0
- package/driver/systemd/clearotron-worker.service +29 -0
- package/driver/tokens.mjs +10 -9
- package/driver/turnaround-bands.mjs +1 -1
- package/driver/unit-inventory.mjs +24 -43
- package/driver/variant-manifest-model.mjs +22 -3
- package/driver/verify-knockout.mjs +163 -4
- package/driver/verify.mjs +42 -16
- package/driver/web-grid.mjs +150 -0
- package/driver/whatif-memo-run.mjs +1 -1
- package/driver/withheld-families.mjs +113 -4
- package/driver/worker-heartbeat.mjs +13 -2
- package/mcp-server/CHANGELOG.md +8 -0
- package/mcp-server/README.md +1 -1
- package/mcp-server/lib/knockout.mjs +1 -1
- package/mcp-server/lib/ops.mjs +10 -10
- package/mcp-server/lib/scrub.mjs +1 -1
- package/mcp-server/lib/trace.mjs +3 -2
- package/mcp-server/package.json +1 -1
- package/mcp-server/server.mjs +3 -3
- package/package.json +1 -1
- package/portal-ui/dist/assets/{index-DVtz44vH.js → index-BPAUjcI0.js} +3 -2
- package/portal-ui/dist/assets/{index-5CCwiJG7.css → index-D2wrw9cH.css} +18 -2
- package/portal-ui/dist/assets/plus-jakarta-sans-BUCHxqJ-.woff2 +0 -0
- package/portal-ui/dist/index.html +2 -15
- package/portal-ui/package.json +1 -1
- package/providers/_shared/README.md +1 -1
- package/providers/_shared/answer-memory.mjs +199 -0
- package/providers/_shared/enumerate.mjs +155 -50
- package/providers/_shared/execute-plan.mjs +62 -16
- package/providers/_shared/ledger-path.mjs +1 -1
- package/providers/_shared/ledger.mjs +48 -6
- package/providers/_shared/plan-guards.mjs +7 -0
- package/providers/_shared/script-form.mjs +24 -5
- package/providers/_shared/term-shape.mjs +5 -5
- package/providers/clarivate/src/capabilities.js +11 -0
- package/providers/clarivate/src/core.js +193 -18
- package/providers/corsearch/README.md +1 -2
- package/providers/corsearch/src/core.js +2 -2
- package/providers/jx-subclass/lookup.mjs +1 -1
- package/providers/oauth-mcp-bridge/CHANGELOG.md +8 -0
- package/providers/oauth-mcp-bridge/README.md +8 -7
- package/providers/oauth-mcp-bridge/bridge.mjs +21 -5
- package/providers/oauth-mcp-bridge/package.json +1 -1
- package/providers/oauth-mcp-bridge/systemd/courtlistener-mcp.service +1 -1
- package/providers/oauth-mcp-bridge/warm-server.mjs +16 -5
- package/providers/perplexity/src/core.js +246 -21
- package/providers/signa/src/capabilities.js +24 -0
- package/providers/signa/src/core.js +93 -25
- package/scripts/README.md +2 -1
- package/scripts/added-reference-check.mjs +2 -1
- package/scripts/backup-recall-stores.mjs +5 -5
- package/scripts/demo-evidence.mjs +2 -1
- package/scripts/deprecate-below.mjs +114 -2
- package/scripts/drive-env-check.mjs +2 -1
- package/scripts/e2e-first-time.mjs +469 -0
- package/scripts/e2e-scenario-ops.mjs +441 -0
- package/scripts/e2e.mjs +104 -16
- package/scripts/env-audit.mjs +8 -0
- package/scripts/freeze-example-run.mjs +7 -7
- package/scripts/generated-files-are-current.mjs +2 -1
- package/scripts/hand-off-exits-probe.mjs +75 -0
- package/scripts/import-cycle-check.mjs +2 -1
- package/scripts/merge-shape-check.mjs +2 -1
- package/scripts/package-size-budget.mjs +2 -1
- package/scripts/record-carry-probe.mjs +1 -1
- package/scripts/release-entry-catch-up.mjs +77 -8
- package/scripts/release-install-check.mjs +4 -1
- package/scripts/release-note-required.mjs +139 -9
- package/scripts/release-rehearsal-version.mjs +60 -0
- package/scripts/release-sbom.mjs +104 -0
- package/scripts/release-visible-check.mjs +7 -5
- package/scripts/render-check.mjs +5 -2
- package/scripts/report-offline-render-check.mjs +169 -0
- package/scripts/score.mjs +79 -8
- package/scripts/strip-titles-and-attributions.mjs +2 -1
- package/scripts/strip-tracker-citations.mjs +2 -1
- package/scripts/test-full.mjs +2 -1
- package/scripts/test-run.mjs +10 -3
- package/scripts/third-party-notices.mjs +3 -1
- package/scripts/travelling-predicates.mjs +1 -1
- package/scripts/writing-standard-check.mjs +2 -1
- package/shared/brand-fonts.mjs +59 -0
- package/shared/brand.mjs +6 -6
- package/shared/browser-temp-root.mjs +3 -2
- package/shared/doctrine-overlay.mjs +1 -1
- package/shared/driver-dir.mjs +47 -11
- package/shared/fonts/OFL-fira-code.txt +93 -0
- package/shared/fonts/OFL-plus-jakarta-sans.txt +93 -0
- package/shared/fonts/README.md +37 -0
- package/shared/fonts/fira-code.woff2 +0 -0
- package/shared/fonts/plus-jakarta-sans.woff2 +0 -0
- package/shared/names-in-force.mjs +2 -0
- package/shared/npm-cli.mjs +23 -0
- package/shared/os-advice.mjs +14 -2
- package/shared/path-seps.mjs +42 -0
- package/shared/process-table.mjs +71 -3
- package/shared/reference-guard-classes.mjs +30 -6
- package/shared/root-doc-commands.mjs +6 -2
- package/shared/running-start.mjs +24 -7
- package/shared/scope.mjs +2 -2
- package/shared/wsl.mjs +1 -1
- package/driver/known-conflicts.mjs +0 -327
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
# Security mapping: OWASP risks for AI applications
|
|
2
|
+
|
|
3
|
+
*Each risk on OWASP's two lists for AI systems, what Clearotron does about it, and the file on `main`
|
|
4
|
+
where that lives. Where nothing does, the row says so and why.*
|
|
5
|
+
|
|
6
|
+
The two lists are the [OWASP Top 10 for LLM Applications 2025](https://genai.owasp.org/llm-top-10/) and
|
|
7
|
+
the [OWASP Top 10 for Agentic Applications 2026](https://genai.owasp.org/resource/owasp-top-10-for-agentic-applications-for-2026/).
|
|
8
|
+
Who may see which runs, and how a key is checked, is stated once in [SECURITY.md](SECURITY.md). This page
|
|
9
|
+
links there rather than repeating it.
|
|
10
|
+
|
|
11
|
+
## How a clearance uses AI
|
|
12
|
+
|
|
13
|
+
A clearance runs as a series of stages. For each stage the driver, which is ordinary code, starts one AI
|
|
14
|
+
program: Anthropic's Claude Code or OpenAI's Codex. The stage gets a written task, the tools named for
|
|
15
|
+
that stage, and its run folder. Code checks every file a stage writes before any other stage reads it.
|
|
16
|
+
The register searches are fixed in a plan before the register stages run, and code runs them. Code also
|
|
17
|
+
renders the report, from the checked files.
|
|
18
|
+
|
|
19
|
+
## OWASP Top 10 for LLM Applications 2025
|
|
20
|
+
|
|
21
|
+
### LLM01:2025 Prompt Injection
|
|
22
|
+
|
|
23
|
+
**Here.** Stages read web pages, marketplace listings and register records, and any of them can carry
|
|
24
|
+
text written to steer the model.
|
|
25
|
+
|
|
26
|
+
**What Clearotron does.** Each stage's tools are granted by name. The case-law stage is the exception: it is granted every tool its two case-law services offer. A tool outside that
|
|
27
|
+
grant that needs permission is refused. A Claude stage is offered no tool that runs a command. A Codex stage keeps its shell inside Codex's own sandbox, and Codex approves tool
|
|
28
|
+
calls only for the tool servers Clearotron starts for that stage. The AI program starts with a named list
|
|
29
|
+
of settings rather than the install's settings file, so the key that signs access keys is not in it.
|
|
30
|
+
Codex's page-fetching tool refuses loopback, private, link-local and cloud-metadata addresses. It checks
|
|
31
|
+
the address a name resolves to, and checks again on every redirect.
|
|
32
|
+
|
|
33
|
+
**Where.** `driver/engine/mcp/gather-config.mjs` (the tools each stage holds),
|
|
34
|
+
`driver/engine/anthropic-agent.mjs` (`COMMAND_TOOLS`), `driver/engine/mcp/codex-config.mjs`,
|
|
35
|
+
`driver/engine/engine-env.mjs`, `driver/engine/mcp/public-fetch.mjs`.
|
|
36
|
+
|
|
37
|
+
**Not covered.** Content from the web is not marked as untrusted in the text a stage reads. That text is
|
|
38
|
+
what the engine reasons from, so changing it is a design decision of its own.
|
|
39
|
+
|
|
40
|
+
### LLM02:2025 Sensitive Information Disclosure
|
|
41
|
+
|
|
42
|
+
**Here.** A report, the portal or a connected assistant shows one company's clearances to another, or
|
|
43
|
+
shows the engine's internals to a company's people.
|
|
44
|
+
|
|
45
|
+
**What Clearotron does.** Every read passes one authorization check, and a person sees only what their
|
|
46
|
+
grant names. A key bound to one run reads that run and writes nothing. The copy of a report a company
|
|
47
|
+
receives drops the staff-only notes. No real company's data is in this repository; run data lives
|
|
48
|
+
in folders the operator owns. CI scans the tree and the built bundle for secrets.
|
|
49
|
+
|
|
50
|
+
**Where.** [SECURITY.md](SECURITY.md) (the access model), `shared/scope.mjs`, `driver/portal-report.mjs`,
|
|
51
|
+
`.gitleaks.toml`, `.github/workflows/ci.yml`.
|
|
52
|
+
|
|
53
|
+
**Not covered.** A company's clearances are kept until the operator deletes them: Clearotron sets no
|
|
54
|
+
retention period, because how long they are held is the operator's policy.
|
|
55
|
+
|
|
56
|
+
### LLM03:2025 Supply Chain
|
|
57
|
+
|
|
58
|
+
**Here.** A compromised npm package, GitHub Action or engine program.
|
|
59
|
+
|
|
60
|
+
**What Clearotron does.** Dependabot updates the npm packages and the GitHub Actions. Each release is
|
|
61
|
+
published to npm through trusted publishing, with provenance that ties the package to the commit and the
|
|
62
|
+
build that produced it. A stable release is not published while a code-scanning alert is open. Setup
|
|
63
|
+
installs, and `clearotron doctor` accepts, only an engine program at or above the version this release
|
|
64
|
+
needs.
|
|
65
|
+
|
|
66
|
+
**Where.** `.github/dependabot.yml`, `.github/workflows/release.yml`,
|
|
67
|
+
`scripts/release-code-scanning-check.mjs`, `driver/driver.config.mjs` (`ENGINE_BINARIES`, each program's
|
|
68
|
+
`floor`).
|
|
69
|
+
|
|
70
|
+
### LLM04:2025 Data and Model Poisoning
|
|
71
|
+
|
|
72
|
+
**Here.** Tampering with what the model learns from, so that it concludes wrongly.
|
|
73
|
+
|
|
74
|
+
**What Clearotron does.** Clearotron trains and fine-tunes no model. The instructions every stage reads
|
|
75
|
+
are versioned in this repository. On the Claude engine a check refuses any write by a stage into those
|
|
76
|
+
instructions, into the company profiles, or into the run's own control folder.
|
|
77
|
+
|
|
78
|
+
**Where.** `driver/skills/` (the instructions), `driver/engine/deny-authority-write.mjs`,
|
|
79
|
+
`driver/authority-trees.mjs`.
|
|
80
|
+
|
|
81
|
+
**Not covered.** Codex has no such check. A Codex stage can write anywhere in its run folder, the control
|
|
82
|
+
folder included, because Codex offers no hook at the moment of a write.
|
|
83
|
+
|
|
84
|
+
### LLM05:2025 Improper Output Handling
|
|
85
|
+
|
|
86
|
+
**Here.** Model output passed on to something that runs or renders it unchecked.
|
|
87
|
+
|
|
88
|
+
**What Clearotron does.** A stage's output is a file, and code checks it against that stage's contract
|
|
89
|
+
before anything uses it. A file that fails is retried or fails the stage; it is never passed on. The
|
|
90
|
+
report is rendered by code from checked files, and no file a stage writes runs on the install's machine.
|
|
91
|
+
The common-law search asks the research service to run a search program, on that service's own servers.
|
|
92
|
+
|
|
93
|
+
**Where.** `driver/gateway.mjs` (`runStage`), `driver/stages.mjs` (each stage's contract),
|
|
94
|
+
`driver/publish/`.
|
|
95
|
+
|
|
96
|
+
### LLM06:2025 Excessive Agency
|
|
97
|
+
|
|
98
|
+
**Here.** A stage that can do more than its task needs: run commands, spend, write where it should not.
|
|
99
|
+
|
|
100
|
+
**What Clearotron does.** Tools are granted per stage, by name. The case-law stage is the exception: it is granted every tool its two case-law services offer. A Claude
|
|
101
|
+
stage is offered no command tool.
|
|
102
|
+
Register searches beyond the fixed plan go through a proposal that code checks and runs. A key issued for
|
|
103
|
+
automation can be limited to named actions. A what-if requested by a company's people is queued for a
|
|
104
|
+
separate process rather than run by the door that received it.
|
|
105
|
+
|
|
106
|
+
**Where.** `driver/engine/mcp/gather-config.mjs`, `driver/engine/anthropic-agent.mjs`,
|
|
107
|
+
`driver/engine/mcp/supplemental.mjs`, `shared/scope.mjs`, `driver/whatif-worker.mjs`.
|
|
108
|
+
|
|
109
|
+
**Not covered.** As ASI02: the Claude program also offers a stage built-in tools that act without asking.
|
|
110
|
+
|
|
111
|
+
### LLM07:2025 System Prompt Leakage
|
|
112
|
+
|
|
113
|
+
**Here.** The instructions given to the model leak, and with them anything secret they hold.
|
|
114
|
+
|
|
115
|
+
**What Clearotron does.** The instructions are published in this repository and hold no credential.
|
|
116
|
+
Credentials reach the tool servers through their environment, never through text a model reads.
|
|
117
|
+
|
|
118
|
+
**Where.** `driver/skills/`, `driver/engine/engine-env.mjs`.
|
|
119
|
+
|
|
120
|
+
### LLM08:2025 Vector and Embedding Weaknesses
|
|
121
|
+
|
|
122
|
+
**Not applicable.** Clearotron keeps no vector store and computes no embeddings. The one search over
|
|
123
|
+
finished runs is a word search.
|
|
124
|
+
|
|
125
|
+
**Where.** `mcp-server/lib/lexsearch.mjs`.
|
|
126
|
+
|
|
127
|
+
### LLM09:2025 Misinformation
|
|
128
|
+
|
|
129
|
+
**Here.** A report states a conflict that is not there, or misses one that is.
|
|
130
|
+
|
|
131
|
+
**What Clearotron does.** Register counts come from the register, never from the model, and a register
|
|
132
|
+
finding names the register record it rests on. A search that could not run is listed in the report as a gap,
|
|
133
|
+
never reported as a clean result. Before a report is published, separate stages argue against its
|
|
134
|
+
conclusions.
|
|
135
|
+
|
|
136
|
+
**Where.** `driver/register-plan.mjs`, `providers/_shared/execute-plan.mjs`, `driver/stages.mjs`,
|
|
137
|
+
[architecture/07-quality-and-audit.md](architecture/07-quality-and-audit.md).
|
|
138
|
+
|
|
139
|
+
### LLM10:2025 Unbounded Consumption
|
|
140
|
+
|
|
141
|
+
**Here.** A run that consumes model time or money without limit.
|
|
142
|
+
|
|
143
|
+
**What Clearotron does.** Each stage runs under a stall watchdog and a hard time limit, and a failing
|
|
144
|
+
stage stops retrying once a retry would repeat the same failure. An install runs a set number of
|
|
145
|
+
clearances at a time. The connector doors limit requests per identity.
|
|
146
|
+
|
|
147
|
+
**Where.** `driver/engine/common.mjs`, `driver/engine/anthropic-agent.mjs`, `driver/gateway.mjs`,
|
|
148
|
+
`mcp-server/lib/http-handler.mjs`.
|
|
149
|
+
|
|
150
|
+
**Not covered.** There is no spend ceiling on a search. By policy, no model is given a time, token or cost
|
|
151
|
+
budget.
|
|
152
|
+
|
|
153
|
+
## OWASP Top 10 for Agentic Applications 2026
|
|
154
|
+
|
|
155
|
+
### ASI01 Agent Goal Hijack
|
|
156
|
+
|
|
157
|
+
**Here.** Text a stage reads redirects it to a goal that is not the clearance.
|
|
158
|
+
|
|
159
|
+
**What Clearotron does.** The controls under LLM01 above. The stage's task is also fixed by the driver,
|
|
160
|
+
and code checks what the stage hands back against that task's contract.
|
|
161
|
+
|
|
162
|
+
**Where.** As LLM01, and `driver/stages.mjs`.
|
|
163
|
+
|
|
164
|
+
**Not covered.** As LLM01: web content is not marked as untrusted.
|
|
165
|
+
|
|
166
|
+
### ASI02 Tool Misuse
|
|
167
|
+
|
|
168
|
+
**Here.** A stage uses a legitimate tool for something its task does not need.
|
|
169
|
+
|
|
170
|
+
**What Clearotron does.** Each stage is granted its tools by name. The case-law stage is the exception: it is granted every tool its two case-law services offer. A tool outside
|
|
171
|
+
that grant that needs permission is refused. Codex's approval covers only the tool servers Clearotron starts for the stage, and
|
|
172
|
+
Codex's fetch tool refuses internal addresses. Register
|
|
173
|
+
calls follow the fixed plan or a proposal code checks. Every tool call is written to the run's tool-call
|
|
174
|
+
log, and each stage's attempt record counts the calls made and the calls refused.
|
|
175
|
+
|
|
176
|
+
**Where.** `driver/engine/mcp/gather-config.mjs`, `driver/engine/mcp/codex-config.mjs`,
|
|
177
|
+
`driver/engine/mcp/public-fetch.mjs`, `driver/engine/mcp/stdio-server.mjs` (the tool-call log),
|
|
178
|
+
`driver/gateway.mjs` (`toolGauge`).
|
|
179
|
+
|
|
180
|
+
**Not covered.** The Claude program also offers every stage some of its built-in tools that need no
|
|
181
|
+
permission: starting a subagent, which keeps the stage's restrictions; scheduling a task on the operator's
|
|
182
|
+
Claude account; messaging the account's other sessions; and sending a notification. Clearotron does not
|
|
183
|
+
remove them.
|
|
184
|
+
|
|
185
|
+
### ASI03 Identity and Privilege Abuse
|
|
186
|
+
|
|
187
|
+
**Here.** A stage acts with more authority than its task, or takes a credential it can reuse.
|
|
188
|
+
|
|
189
|
+
**What Clearotron does.** The AI program starts with a named list of settings, and the key that signs
|
|
190
|
+
access keys is not on it. The worker that starts the AI program does not hold that key either, whether
|
|
191
|
+
the install runs in a terminal or under systemd. Access keys are scoped to a run, a company or named
|
|
192
|
+
actions, and one check enforces the scope. On Claude, a stage's file tools can read nothing outside its run folder, its
|
|
193
|
+
instruction folders and any folder the machine's own Claude settings add. On Codex with its sandbox on, a stage's commands can read nothing outside its run folder, its instruction folders, the temporary
|
|
194
|
+
folders, and the system and program files a command needs to run.
|
|
195
|
+
|
|
196
|
+
**Where.** `driver/engine/engine-env.mjs`, `bin/start.mjs` (`SIGNING_KEY_NAMES`),
|
|
197
|
+
`driver/systemd/clearotron-worker.service`, `shared/scope.mjs`, `driver/engine/anthropic-agent.mjs`
|
|
198
|
+
(`READ_FENCE`), `driver/engine/mcp/codex-config.mjs` (`fenceToml`).
|
|
199
|
+
|
|
200
|
+
**Not covered.** With Codex's sandbox off, a stage's commands run with every permission of the install's
|
|
201
|
+
account and can read any file it can, the settings file included. With it on, the temporary folders are
|
|
202
|
+
shared by every stage of the install, so a stage's commands can read what another stage left there.
|
|
203
|
+
|
|
204
|
+
### ASI04 Agentic Supply Chain Vulnerabilities
|
|
205
|
+
|
|
206
|
+
**Here.** A tool server or engine component that a stage trusts is compromised.
|
|
207
|
+
|
|
208
|
+
**What Clearotron does.** The tool servers a stage uses are Clearotron's own code in this repository. Two
|
|
209
|
+
of them are bridges Clearotron starts to the case-law services CourtListener and Legal Data Hunter, and
|
|
210
|
+
they pass through the tools those services define. On Codex, the configuration written for each turn lists
|
|
211
|
+
only the servers granted to that stage. The supply-chain controls under LLM03 apply here too.
|
|
212
|
+
|
|
213
|
+
**Where.** `driver/engine/mcp/`, `providers/oauth-mcp-bridge/bridge.mjs`,
|
|
214
|
+
`driver/engine/mcp/codex-config.mjs`.
|
|
215
|
+
|
|
216
|
+
### ASI05 Unexpected Code Execution
|
|
217
|
+
|
|
218
|
+
**Here.** A stage is talked into running code.
|
|
219
|
+
|
|
220
|
+
**What Clearotron does.** A Claude stage has no tool that runs a command: Bash, PowerShell and Monitor
|
|
221
|
+
are removed by name from every stage. A Codex stage runs its commands inside Codex's own sandbox. They can read nothing outside the stage's own folders, the temporary folders, and the system and program
|
|
222
|
+
files a command needs to run, and write nothing outside its run folder and the temporary folders. Before a search is paid for, a
|
|
223
|
+
check runs one turn through the engine with the settings the search will use.
|
|
224
|
+
|
|
225
|
+
**Where.** `driver/engine/anthropic-agent.mjs` (`COMMAND_TOOLS`), `driver/engine/openai-agent.mjs`
|
|
226
|
+
(`buildCodexArgs`), `driver/engine/mcp/codex-config.mjs` (`fenceToml`), `driver/engine/probe.mjs`.
|
|
227
|
+
|
|
228
|
+
**Not covered.** Where Codex's sandbox cannot start on a machine, the setting
|
|
229
|
+
`CLEAROTRON_CODEX_SANDBOX_BYPASS=1` runs Codex without it, and a stage's commands then run with every
|
|
230
|
+
permission of the install's account. The engine check says when a machine needs it.
|
|
231
|
+
|
|
232
|
+
### ASI06 Memory and Context Poisoning
|
|
233
|
+
|
|
234
|
+
**Here.** Poisoned content persists and steers later work.
|
|
235
|
+
|
|
236
|
+
**What Clearotron does.** The engine keeps no memory of its own: every stage starts from its task and its
|
|
237
|
+
run folder, and a retried stage resumes only its own session. What does persist between runs is each
|
|
238
|
+
company's configuration, its profile, risk framework and background notes, which every run reads and which
|
|
239
|
+
only people with Manage can edit in the portal. On the Claude engine a stage cannot write to it.
|
|
240
|
+
|
|
241
|
+
**Where.** `driver/gateway.mjs` (`runStage`), `driver/profiles.mjs`, [SECURITY.md](SECURITY.md) (who
|
|
242
|
+
holds Manage), `driver/engine/deny-authority-write.mjs`.
|
|
243
|
+
|
|
244
|
+
**Not covered.** As LLM01: web content that a stage reads, and that a later stage reads in its output, is
|
|
245
|
+
not marked as untrusted.
|
|
246
|
+
|
|
247
|
+
### ASI07 Insecure Inter-Agent Communication
|
|
248
|
+
|
|
249
|
+
**Not applicable in its usual sense.** Stages do not message each other. The driver passes files from one
|
|
250
|
+
stage to the next, and checks each one first.
|
|
251
|
+
|
|
252
|
+
**Where.** `driver/gateway.mjs`, `driver/stages.mjs`.
|
|
253
|
+
|
|
254
|
+
### ASI08 Cascading Failures
|
|
255
|
+
|
|
256
|
+
**Here.** One failed stage corrupts the stages after it.
|
|
257
|
+
|
|
258
|
+
**What Clearotron does.** Code checks each stage's output before the next stage reads it. A stage whose
|
|
259
|
+
retries fail the same way twice stops retrying, and a stage whose every tool call was refused stops after
|
|
260
|
+
one attempt. The engine check before a search refuses a machine that would fail every stage.
|
|
261
|
+
|
|
262
|
+
**Where.** `driver/gateway.mjs`, `driver/engine/probe.mjs`, `driver/engine/tool-refusal.mjs`.
|
|
263
|
+
|
|
264
|
+
### ASI09 Human-Agent Trust Exploitation
|
|
265
|
+
|
|
266
|
+
**Here.** A reader trusts a confident report more than its evidence supports.
|
|
267
|
+
|
|
268
|
+
**What Clearotron does.** A register finding names the register record it rests on, and every search that
|
|
269
|
+
could not run is listed in the report.
|
|
270
|
+
|
|
271
|
+
**Where.** `driver/publish/`, `driver/register-plan.mjs`.
|
|
272
|
+
|
|
273
|
+
### ASI10 Rogue Agents
|
|
274
|
+
|
|
275
|
+
**Here.** An agent that keeps running, spreads, or acts outside its task.
|
|
276
|
+
|
|
277
|
+
**What Clearotron does.** No agent outlives its stage. Each stage is one process under a watchdog and a
|
|
278
|
+
hard time limit, and the driver stops its whole process group. The driver records every program it
|
|
279
|
+
starts. On the Claude engine a stage cannot write into the instructions it runs from.
|
|
280
|
+
|
|
281
|
+
**Where.** `driver/engine/anthropic-agent.mjs`, `driver/engine/common.mjs`,
|
|
282
|
+
`driver/engine/child-record.mjs`, `driver/engine/deny-authority-write.mjs`.
|
|
283
|
+
|
|
284
|
+
**Not covered.** As LLM04: on Codex, no check refuses a stage's write inside its run folder.
|
|
285
|
+
|
|
286
|
+
## Repository protections
|
|
287
|
+
|
|
288
|
+
Measured on 2026-09-23 with the GitHub API.
|
|
289
|
+
|
|
290
|
+
| Protection | State |
|
|
291
|
+
|---|---|
|
|
292
|
+
| Secret scanning | On |
|
|
293
|
+
| Push protection | On |
|
|
294
|
+
| CodeQL (Actions, JavaScript and TypeScript) | Configured, and a required check on `main` |
|
|
295
|
+
| Code scanning before a stable release | A stable is not published while an alert is open |
|
|
296
|
+
| Private vulnerability reporting | On |
|
|
297
|
+
| npm provenance | Every release, through trusted publishing |
|
|
298
|
+
| Required checks on `main` | Six; force pushes and branch deletion refused |
|
package/docs/SECURITY.md
CHANGED
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
What protects what, where it is enforced in code, and what the operator must do. Every statement
|
|
6
6
|
here corresponds to shipped behavior; when hardening changes, change this file in the same PR.
|
|
7
7
|
|
|
8
|
+
Each risk on OWASP's two lists for AI systems, and what Clearotron does about it:
|
|
9
|
+
[SECURITY-OWASP.md](SECURITY-OWASP.md).
|
|
10
|
+
|
|
8
11
|
## Surfaces
|
|
9
12
|
|
|
10
13
|
| Surface | Trust | Guard |
|
|
@@ -12,7 +15,7 @@ here corresponds to shipped behavior; when hardening changes, change this file i
|
|
|
12
15
|
| stdio MCP (`mcp-server/server.mjs`) | local/full ("ops") | OS user boundary — run it AS the operator account; it is the only surface on which `what_if_run` EXECUTES (`visibleTools` keeps what-if out of the HTTP listing for ops, but the CallTool chokepoint gates on `authorize()` alone, which admits it for any ops token not `--verbs`-scoped) |
|
|
13
16
|
| Client MCP (`mcp-server/http-server-client.mjs`) | a company's signed-in person / their access key | `what_if_run` from an `account` principal ENQUEUES rather than executes (ruling 2026-08-27) — it never imports the engine, and `driver/whatif-worker.mjs` spawns the sandbox from an OS service process. A confirmation token is unsigned, so the call must ALSO name its `runId`: the grant check keys on it, and `whatIfEnqueue` refuses a token naming a different run. The `model` argument is refused on this face. |
|
|
14
17
|
| HTTP MCP (`mcp-server/http-server.mjs`) | authenticated remote | auth-BEFORE-data; fail-closed construction; inner scoped tokens |
|
|
15
|
-
|
|
|
18
|
+
| Run-bound keys | a report recipient an operator issues one to | a `user` key from `mint-token.mjs`, read-only and bound to one run; the plain-language report tools (`clientSafe`) only |
|
|
16
19
|
| Dev portal (`driver/dev-portal.mjs`) | dev only | loopback-only (throws on any other host); never production serving |
|
|
17
20
|
|
|
18
21
|
## Authentication (the outer gate — both faces)
|
|
@@ -121,10 +124,9 @@ with access to everything.
|
|
|
121
124
|
what the mechanism guarantees.*
|
|
122
125
|
|
|
123
126
|
- One OPERATOR issuance path: `mint-token.mjs` (prints once, stores nothing; `sub` names the
|
|
124
|
-
principal in every audit line; the `jti` printed at mint time is the revocation handle).
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
company-capped ops token in memory at every start. Neither prints, and neither is written down.
|
|
127
|
+
principal in every audit line; the `jti` printed at mint time is the revocation handle). Three other callers share the same `mintToken`: `clearotron start` mints the portal's verb-scoped,
|
|
128
|
+
company-capped ops token in memory at every start, and neither prints nor stores it; `clearotron connect`
|
|
129
|
+
and the portal's connect screen each mint a person's key for their own assistant.
|
|
128
130
|
- **Revocation**: denylist file checked on every verification; missing file = nothing revoked (the
|
|
129
131
|
denylist can never take all auth down). **Rotation**: two-secret window, flag-day-free.
|
|
130
132
|
- **Rate limits**: per-identity bucket on every request plus a separate lower per-principal bucket
|
|
@@ -132,9 +134,10 @@ what the mechanism guarantees.*
|
|
|
132
134
|
|
|
133
135
|
## Audit
|
|
134
136
|
|
|
135
|
-
Every HTTP tool call appends
|
|
136
|
-
|
|
137
|
-
|
|
137
|
+
Every HTTP tool call appends one line to an append-only JSONL (`TRADEMARK_MCP_AUDIT_LOG`) when the call
|
|
138
|
+
finishes: `{ts, email, sub, method, tool, runId, status, door}`, where `status` is the outcome. It is
|
|
139
|
+
written after scope resolution, so it names the principal. A request refused before any tool runs is
|
|
140
|
+
written too, with the status `refused`. Writing it is best-effort and never blocks a request.
|
|
138
141
|
|
|
139
142
|
## Data plane
|
|
140
143
|
|
|
@@ -143,7 +146,8 @@ principal) and before dispatch; it is best-effort and never blocks a request.
|
|
|
143
146
|
companies only. Run data lives in operator-owned directories outside git (`CLEAROTRON_REPORTS_DIR`,
|
|
144
147
|
workspace root, outbox), backed up by the operator, never committed.
|
|
145
148
|
- Secrets enter only via environment (`.env` on the host); the repo carries `.env*.example` files
|
|
146
|
-
with placeholders. CI runs a secret scan (gitleaks) on every
|
|
149
|
+
with placeholders. CI runs a secret scan (gitleaks) over the tree and the built bundle on every pull request and every
|
|
150
|
+
push to `main`.
|
|
147
151
|
- Dev instances are isolated by CONFIGURATION and nothing else: a test instance and a live one are the
|
|
148
152
|
same code with different environment — no build flag, no profile constant, no mode switch in the
|
|
149
153
|
source — so the separation holds exactly as far as the operator gives it its own
|
|
@@ -160,7 +164,9 @@ Each pipeline stage shells the configured engine binary as the operator account
|
|
|
160
164
|
picks the adapter install-wide (`anthropic-agent` spawns `claude -p`, `openai-agent` spawns
|
|
161
165
|
`codex exec` with a per-run `CODEX_HOME`), with no per-stage engine and no fallback between them —
|
|
162
166
|
with run-scoped `--add-dir` access and per-provider gather MCP servers whose credentials come from the
|
|
163
|
-
environment.
|
|
167
|
+
environment. The program starts with a named list of settings rather than the whole environment, so the
|
|
168
|
+
key that signs access keys never reaches it (`driver/engine/engine-env.mjs`). A stage on Claude is
|
|
169
|
+
offered no tool that runs a command; a stage on Codex runs its commands inside Codex's own sandbox. Stage outputs are judged by file-truth validators — the engine's own success claims
|
|
164
170
|
are never trusted. Delivery is a self-contained packet couriered by the integrator; the engine sends
|
|
165
171
|
no messages and holds no channel credentials.
|
|
166
172
|
|
|
@@ -178,9 +184,8 @@ no messages and holds no channel credentials.
|
|
|
178
184
|
## Reporting
|
|
179
185
|
|
|
180
186
|
**[`../SECURITY.md`](../SECURITY.md) is the disclosure path** — the channel, what is in scope, and
|
|
181
|
-
what to expect. It is the only file that names the
|
|
182
|
-
|
|
183
|
-
ever moves.
|
|
187
|
+
what to expect. It is the only file that names the channels, so there is one place to change if one ever
|
|
188
|
+
moves.
|
|
184
189
|
|
|
185
190
|
If you run your own deployment, reports about *your* configuration — your auth proxy, your TLS, your
|
|
186
191
|
keys — go to you. This file describes what the code guarantees; it cannot speak for how a given
|
|
@@ -214,9 +214,9 @@ mode via `CLEAROTRON_AI_BILLING=api-key` — the scale setting ([04](04-configur
|
|
|
214
214
|
|
|
215
215
|
**The second engine** (`engine/openai-agent.mjs`) spawns `codex exec` per stage on the shared
|
|
216
216
|
`engine/common.mjs` substrate: prompt on stdin, `--json` event stream, `--skip-git-repo-check` with a neutral non-repo
|
|
217
|
-
cwd, `--
|
|
218
|
-
|
|
219
|
-
`auth.json`. It is single-provider like the anthropic engine — one run's stages all execute as GPT —
|
|
217
|
+
cwd, `--add-dir <runDir>`, and a per-run `CODEX_HOME` holding a rendered `config.toml` (MCP servers,
|
|
218
|
+
developer instructions and, with Codex's sandbox on, a permission profile that limits what the stage's
|
|
219
|
+
commands can read and write) plus, under subscription billing, a seeded `auth.json`. It is single-provider like the anthropic engine — one run's stages all execute as GPT —
|
|
220
220
|
so telemetry's model provenance needs no cross-provider bookkeeping. Its abstract tiers all resolve
|
|
221
221
|
to one model id by default; [04](04-configuration-reference.md) records why, and why lowering them
|
|
222
222
|
is not a cost saving.
|
|
@@ -254,7 +254,7 @@ primitive is a filesystem primitive chosen for its atomicity:
|
|
|
254
254
|
| pid+starttime sidecars | claim liveness, slot ownership | survives pid reuse; positive-evidence death only |
|
|
255
255
|
|
|
256
256
|
The run directory ([03 §7](03-run-lifecycle.md#7--run-directory-anatomy)) is the unit of truth;
|
|
257
|
-
the queue dirs, the
|
|
257
|
+
the queue dirs, the outbox, and the publish pool are the only shared
|
|
258
258
|
locations, and each has a single writer role. This is why horizontal
|
|
259
259
|
scaling is credible: a second driver on a second host needs sharded queues and a shared pool,
|
|
260
260
|
nothing else.
|
|
@@ -286,7 +286,7 @@ All paths relative to [`driver/`](../../driver/). The load-bearing seven are mar
|
|
|
286
286
|
| `rule-shape.mjs` · `reasoning-tripwires.mjs` · `gate-metrics.mjs` | Anti-threshold guard, integrity tripwires (observe-only), gate telemetry. |
|
|
287
287
|
| `predelivery-lint.mjs` · `close-verify.mjs` · `screen-gate.mjs` | Pre-delivery checks, envelope close verification, screen-gate detection. |
|
|
288
288
|
| `common-law-receipts.mjs` · `engagement-receipt.mjs` · `scope-ledger.mjs` | Receipt models for the marketplace grid, engagement, scope. |
|
|
289
|
-
| `senior-rights.mjs` · `own-rights.mjs` · `use-check.mjs`
|
|
289
|
+
| `senior-rights.mjs` · `own-rights.mjs` · `use-check.mjs` | Rights closure, self-exclusion, use analysis. |
|
|
290
290
|
| `publish/` | Deterministic publication: HTML render, Excel audit workbook, pool admin, regions. |
|
|
291
291
|
| `repairs.mjs` · `repair-digest.mjs` | Recovery decisions, repair budgets, repair digests. |
|
|
292
292
|
| `tokens.mjs` · `provider-usage.mjs` · `progress.mjs` · `status-snapshot.mjs` · `run-activity.mjs` | Token rollup (successor to the deleted `cost.mjs`), billing-grade provider ledger, status surfaces. |
|
|
@@ -178,7 +178,7 @@ seeding. Frozen sidecars are never silently re-derived; a corrupt one crashes lo
|
|
|
178
178
|
flowchart TD
|
|
179
179
|
subgraph HEAD["Phase 1-2 head (fatal)"]
|
|
180
180
|
MF[matter-frame] --> PV[clearance-variants]
|
|
181
|
-
PV --> DER["code derivations:<br/>scope ledger · form neighbourhood ·<br/>register plan freeze
|
|
181
|
+
PV --> DER["code derivations:<br/>scope ledger · form neighbourhood ·<br/>register plan freeze"]
|
|
182
182
|
end
|
|
183
183
|
DER --> GRID["grid spec dictated by code<br/>(terms × platforms × connotation; A1 split)"]
|
|
184
184
|
subgraph GATHER["Gather fan-out (concurrency = CLEAROTRON_GATHER_CONCURRENCY)"]
|
|
@@ -189,18 +189,17 @@ flowchart TD
|
|
|
189
189
|
GRID --> GATHER
|
|
190
190
|
GATHER --> FANIN{{"fan-in barrier (code):<br/>quarantines · must() · half-merge ·<br/>named-band gate · taint chain ·<br/>plan⇄band identity join · grid-ledger gate"}}
|
|
191
191
|
FANIN --> CLOSURE["coverage closure pass<br/>(one supplementary sweep, non-fatal)"]
|
|
192
|
-
CLOSURE --> PI[placement-inquiry] --> RD[register-digest]
|
|
192
|
+
CLOSURE --> FD["frame-diff vs blind frame<br/>+ bounded reopen (non-fatal block)"] --> PI[placement-inquiry] --> RD[register-digest]
|
|
193
193
|
RD --> SK["skeptic (non-fatal)"]
|
|
194
194
|
SK --> ESC{"ESCALATE: axis tokens?"}
|
|
195
195
|
ESC -- yes --> RERUN["re-run flagged axes warm ·<br/>byte-diff · one re-digest"] --> ENV
|
|
196
196
|
ESC -- no --> ENV["deadline envelope:<br/>close deferred floors if time allows"]
|
|
197
197
|
ENV --> SG{{"screen-gate: dropped LIVE mark<br/>without fetched record?<br/>fetch → re-digest → else FATAL"}}
|
|
198
|
-
SG -->
|
|
199
|
-
FD --> SYN[synthesis]
|
|
198
|
+
SG --> SYN[synthesis]
|
|
200
199
|
SYN --> PAR["case-law ∥ narrative-refutation<br/>(case-law non-fatal)"]
|
|
201
200
|
PAR --> VG{"verdict gate:<br/>parseVerdict(review)"}
|
|
202
201
|
VG -- "CONDITIONAL / BLOCKING" --> CORR["corrective re-synthesis (fatal) ·<br/>corrections freshness gate ·<br/>verdict re-check (warm)"] --> VG2{"still BLOCKING?"}
|
|
203
|
-
VG2 -- yes -->
|
|
202
|
+
VG2 -- yes --> DELIV["report DELIVERS (ruling 2026-08-26) ·<br/>runLog verdict-blocking-delivered ·<br/>open points recorded beside the review,<br/>for the reviewing lawyer (ruling 2026-09-24)"] --> CLAMP
|
|
204
203
|
VG2 -- no --> CLAMP
|
|
205
204
|
VG -- CLEAR --> CLAMP["code clamps (raise-only):<br/>legal actions · coverage · frame residual ·<br/>screen gate · register gap · deadline gap"]
|
|
206
205
|
CLAMP --> VS["verdict sidecar _driver/verdict.json<br/>(single label authority; write failure = fatal)"]
|
|
@@ -212,7 +211,7 @@ flowchart TD
|
|
|
212
211
|
PUB --> HANDOFF["delivery packet _driver/delivery.json ·<br/>outbox <runId>.pending · .delivered · archive"]
|
|
213
212
|
|
|
214
213
|
classDef fatal stroke:#c0392b,stroke-width:2px
|
|
215
|
-
class MF,PV,PI,RD,SYN,
|
|
214
|
+
class MF,PV,PI,RD,SYN,VS,CG fatal
|
|
216
215
|
```
|
|
217
216
|
|
|
218
217
|
Reading order for the phases, with what code decides at each:
|
|
@@ -222,8 +221,7 @@ Reading order for the phases, with what code decides at each:
|
|
|
222
221
|
generates the complete mechanical variant floor), freezes the register plan
|
|
223
222
|
(`_driver/register-plan.json`, frozen for the life of *this run* — a resume never re-plans, and a
|
|
224
223
|
fresh run always mints; reproducibility comes from the compiler being pure, not from a store of
|
|
225
|
-
prior plans)
|
|
226
|
-
workspace store become deterministic plan entries (cap 10).
|
|
224
|
+
prior plans).
|
|
227
225
|
2. **Grid dictation** — code writes `_driver/grid-spec.json`: exact terms × platforms, connotation
|
|
228
226
|
queries, batch size, `ledger_required: true`. With ≥2 terms the grid is split across three
|
|
229
227
|
seats — unconditionally since item 8 deleted the rollback switch: halves`a` and `b` take
|
|
@@ -244,29 +242,29 @@ Reading order for the phases, with what code decides at each:
|
|
|
244
242
|
persistent repair ledger (`_driver/repairs.json`) so no ladder is ever bought twice.
|
|
245
243
|
5. **Coverage closure** — one supplementary sweep for closable coverage-limited cells, idempotent
|
|
246
244
|
by receipt; survivors become a front-matter coverage note, not a halt.
|
|
247
|
-
6. **
|
|
245
|
+
6. **Frame-diff + bounded reopen** — the blind frame is diffed against the run's own framing;
|
|
246
|
+
directives (including deterministic mechanical form-gap directives) can reopen register and
|
|
247
|
+
source arms once, under a fetch ceiling (`CLEAROTRON_REOPEN_MAX_FETCH`, default 150), with
|
|
248
|
+
per-directive closure verification. The whole block is non-fatal; unclosed directives demote to
|
|
249
|
+
disclosed deferrals that later clamp the verdict.
|
|
250
|
+
7. **Placement → register-digest** — both fatal. Every digest pass (fresh, escalation, envelope,
|
|
248
251
|
late-bind, stale-repair) goes through the single `runDigest` chokepoint, which drops stale ledgers,
|
|
249
252
|
renders the coverage ledger from the driver-written coverage form the seat submits through
|
|
250
253
|
`record_coverage` — the prose `## Coverage ledger` table and the machine-readable JSON are both
|
|
251
254
|
renders of that one form, so neither can be the thing that drifts (prose parsing survives only as
|
|
252
255
|
the fallback when the derivation throws) — and quarantines rather than ships a ledger that fails
|
|
253
256
|
its validator.
|
|
254
|
-
|
|
257
|
+
8. **Skeptic + escalation** — the skeptic is deliberately non-fatal (a checker outage must not bin
|
|
255
258
|
a completed gather). Escalation is triggered only by structured `ESCALATE: <axis>` tokens; an
|
|
256
259
|
axis whose every owned ledger row is `coverage-limited` is skipped (documented accepted limit);
|
|
257
260
|
flagged axes re-run warm on their winning session keys, byte-diff guards skip unchanged units,
|
|
258
261
|
then exactly one re-digest. A digest lock forbids escalation after synthesis exists on a resume.
|
|
259
|
-
|
|
262
|
+
9. **Deadline envelope** — pure arithmetic: if the deadline leaves room after an estimated close
|
|
260
263
|
cost plus a one-hour delivery reserve, deferred floors get one warm close attempt, verified by
|
|
261
264
|
re-running the detectors; unverifiable closes are disclosed, never claimed.
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
10. **Frame-diff + bounded reopen** — the blind frame is diffed against the run's own framing;
|
|
266
|
-
directives (including deterministic mechanical form-gap directives) can reopen register and
|
|
267
|
-
source arms once, under a fetch ceiling (`CLEAROTRON_REOPEN_MAX_FETCH`, default 150), with
|
|
268
|
-
per-directive closure verification. The whole block is non-fatal; unclosed directives demote to
|
|
269
|
-
disclosed deferrals that later clamp the verdict.
|
|
265
|
+
10. **Screen-gate** — an in-scope *live* mark dropped on goods/field grounds without a fetched
|
|
266
|
+
record is repaired (code fetches the record, one warm re-digest) or the run dies: an
|
|
267
|
+
unexaminable drop is not shippable.
|
|
270
268
|
11. **Synthesis** — fatal. Malformed findings get one warm re-emit naming exactly the defective
|
|
271
269
|
objects; still-malformed findings after the ladder are terminal (the old quarantine-and-continue
|
|
272
270
|
is retired). Schema and actions[] upgrades are demanded warm on runs where synthesis actually ran.
|
|
@@ -275,12 +273,16 @@ Reading order for the phases, with what code decides at each:
|
|
|
275
273
|
verdict is parsed by code; a parse failure is **BLOCKING** (fail-safe). CONDITIONAL/BLOCKING
|
|
276
274
|
triggers corrective re-synthesis (fatal if it fails), a freshness gate proving the named
|
|
277
275
|
corrections reached `findings.json`, and a warm verdict re-check. A still-BLOCKING verdict
|
|
278
|
-
after the degenerate-artifact repair
|
|
279
|
-
|
|
276
|
+
after the degenerate-artifact repair does **not** fail the run. Ruling 2026-08-26, verbatim:
|
|
277
|
+
"Deliver always, with open points printed. The refusal on a blocking review goes." The run
|
|
278
|
+
logs `verdict-blocking-delivered` and carries on to the clamps. Ruling 2026-09-24 settled
|
|
279
|
+
where the points go: reviewer notes never reach the client page, and a report the reviewer
|
|
280
|
+
still refuses ships with its rating and nothing added — the open points are recorded beside
|
|
281
|
+
the review in the run record, for the reviewing lawyer.
|
|
280
282
|
13. **Code clamps** — the coverage floor (`applyCoverageFloor`) only ever *raises* CLEAR to
|
|
281
283
|
CONDITIONAL: typed condition actions, the lawyer's explicit `coverage_judgment.sufficient ===
|
|
282
|
-
false`, frame residuals, screen-gate gaps, register gaps (from the taint-relabelled ledger)
|
|
283
|
-
|
|
284
|
+
false`, frame residuals, screen-gate gaps, register gaps (from the taint-relabelled ledger).
|
|
285
|
+
Execution facts clamp in code regardless of the model's self-report. The
|
|
284
286
|
**verdict sidecar** (`_driver/verdict.json`) then becomes the single verdict authority for
|
|
285
287
|
everything downstream; failing to write it is fatal.
|
|
286
288
|
14. **Delivery phase** — report overview (fatal), per-finding report cards (fan-out, individually
|
|
@@ -292,7 +294,7 @@ Reading order for the phases, with what code decides at each:
|
|
|
292
294
|
reasoning-integrity receipt (observability only, never a gate — an explicit Goodhart guard).
|
|
293
295
|
15. **Client-gate + publish + handoff** — the client gate is evaluated fail-closed *before*
|
|
294
296
|
anything touches the pool. Publish is deterministic code, idempotent via `.published`. Then the
|
|
295
|
-
delivery handoff (§4),
|
|
297
|
+
delivery handoff (§4), `status.json` flip to `delivered`,
|
|
296
298
|
archive (the run dir is renamed into the archive tree), and the `.delivered` sentinel.
|
|
297
299
|
|
|
298
300
|
**Fatal vs note-and-continue.** The full lists live in `pipeline.mjs` (the outer catch), but the shape is:
|
|
@@ -465,7 +467,7 @@ needs is in it:
|
|
|
465
467
|
│ ├── profile.json · framework.json · register-plan.json # frozen per-run config (never re-derived)
|
|
466
468
|
│ ├── grid-spec.json (+ .half-a/b, .supp-*) # code-dictated search specs
|
|
467
469
|
│ ├── coverage-enum.json · plan-execution.json # fail-closed enum sentinel · execution receipt
|
|
468
|
-
│ ├── register-
|
|
470
|
+
│ ├── register-xcheck.json # cross-check receipt (a run before 2026-09-24 may also carry register-recall.json, its recall-search receipt)
|
|
469
471
|
│ ├── register-taint.json · escalation-state.json # taint chain · escalation/envelope outcome
|
|
470
472
|
│ ├── coverage-closure.json · frame-reopen.json # closure + reopen receipts
|
|
471
473
|
│ ├── intake-asks.json · instructed-scope.json # intake derivations (code-authoritative scope)
|
|
@@ -486,7 +488,4 @@ needs is in it:
|
|
|
486
488
|
└── (delivered runs move whole to <archive>/<YYYY-MM>/<slug>/)
|
|
487
489
|
```
|
|
488
490
|
|
|
489
|
-
Outside the run dir, a run touches the
|
|
490
|
-
(`_known-conflicts/<mark>.json` — human-editable; code only adds
|
|
491
|
-
rows, and rewrites exactly one machine field, `terminal`, when a delivered run confirms a leg an
|
|
492
|
-
earlier failed attempt recorded), the outbox (`<runId>.pending`), and the publish pool.
|
|
491
|
+
Outside the run dir, a run touches the outbox (`<runId>.pending`) and the publish pool.
|
|
@@ -85,7 +85,7 @@ does after the stage's full retry ladder fails ([03 §5](03-run-lifecycle.md#5--
|
|
|
85
85
|
| 10 | `frame-diff` | sonnet · low | 600 / — | `frame-diff.md` + `frame-diff.json` | non-fatal (no reopen) |
|
|
86
86
|
| 11 | `synthesis` | `CLEAROTRON_SYNTHESIS_MODEL` \|\| opus · high | 2500 / 900 | `narrative.md` + **`findings.json`** (schema v7 — `FINDINGS_SCHEMA_VERSION`, interpolated into the contract the stage message dictates: `findings`, `coverage`, `mark_assessment`, `four_answers`, `actions`, `coverage_judgment` and `rated_under_framework`, plus `context_notes` / `ask_answers` where they apply) | quasi-fatal: unrepaired finding defects are terminal; corrective re-synthesis is fatal on failure |
|
|
87
87
|
| 12 | `case-law` | sonnet · adaptive | 900 / — | `case-law-findings.md` | non-fatal; conditional on the PRODUCT — `decideCaseLaw` (`pipeline.mjs`) runs it on **every** `full-country-search`, because the case-law and opposition reading is what that product IS and `policy.caseLaw` is set from the product spec. A narrative that turns on a precedent or an opposition is the second, redundant arm there; on any other product that reading is recorded as `declined`, never run |
|
|
88
|
-
| 13 | `narrative-refutation` | opus · high | 900 / 600 | `senior-eye-review.md` (verdict on first line) | fatal |
|
|
88
|
+
| 13 | `narrative-refutation` | opus · high | 900 / 600 | `senior-eye-review.md` (verdict on first line) | fatal: the STAGE failing to produce a review. Its **verdict** is not — a still-BLOCKING verdict delivers (ruling 2026-08-26), see [03](03-run-lifecycle.md) step 12 |
|
|
89
89
|
| 14 | `report-overview` | sonnet · low | 900 / — | `report-overview.md` (shell only; cards + "Only you can close these" are code-built) | fatal |
|
|
90
90
|
| 15 | `report-card` | sonnet · low | 600 / — | `report-cards/<ord>.md` | non-fatal per card (structured-only fallback) |
|
|
91
91
|
| 16 | `doubt-closure` | sonnet · low | 300 / — | `doubt-closure.md` (dictated `SETTLED`/`IMMATERIAL`/`OPEN` lines; code re-verifies every quote) | non-fatal (the open doubts and asks ship `OPEN`, as they would without the stage) |
|
|
@@ -138,12 +138,6 @@ id is what a dispatch row and a token-rollup row carry as the model *asked for*;
|
|
|
138
138
|
the turn is recorded beside it, and the report names that. A version here would be a claim about a
|
|
139
139
|
request nobody made, and wrong the day a newer model of the tier shipped.
|
|
140
140
|
|
|
141
|
-
One consequence, accepted when this was decided: per-model totals are keyed on what was asked for,
|
|
142
|
-
and the native-language lanes call the API directly, where a model id is required and a tier word is
|
|
143
|
-
not accepted. So one model reached by a stage and by those lanes appears under two keys —
|
|
144
|
-
`anthropic/claude-haiku` and `anthropic/claude-haiku-4-5`. They are different requests, and the split
|
|
145
|
-
says so.
|
|
146
|
-
|
|
147
141
|
The bottom four are **legacy names that no stage declares and no engine can run** — they resolve at
|
|
148
142
|
level 1 and then throw at level 2 (below). They are catalogue entries, not available tiers.
|
|
149
143
|
|
|
@@ -199,7 +193,7 @@ timeout shot, warm patch, backoff), the lane-wedge re-dispatch, and the rate-lim
|
|
|
199
193
|
| `CLEAROTRON_OPENAI_MODEL_JUDGMENT` / `CLEAROTRON_OPENAI_MODEL_SWEEP` / `CLEAROTRON_OPENAI_MODEL_CHEAP` | `gpt-5.6-sol` / `gpt-5.6-terra` / `gpt-5.6-luna`. | Maps the driver's abstract `opus`/`sonnet`/`haiku` tiers onto the codex ladder, the way the anthropic engine maps onto its own (ruling 2026-09-02, superseding the single-model mapping). A tier that cannot hold its stage contract announces itself at that stage — `missing:negative-results`, `no_coverage_status_row`, `named_band_missing` in `_driver/<stage>.jsonl` — not at delivery. |
|
|
200
194
|
| ↳ why they are three, and what the old measurement still says | superseded 2026-09-02, not erased | The three defaulted to `sol` alone on a MEASUREMENT, never a placeholder: on 2026-08-11/12, with `SWEEP=gpt-5.6-terra` / `CHEAP=gpt-5.6-luna`, every codex clearance died on structural-output gates — `missing:negative-results`, `no_coverage_status_row`, `named_band_missing` — over 2 scenarios × 3 stage families, **byte-identically on retry**, so no retry budget rescued it. That measurement stands for the code and the codex CLI **of that date**, and it is why the judgment tier keeps `sol`. Three weeks of stage-contract work and several codex minor versions sit between it and the 2026-09-02 ruling that split the three. **The symptom to match against this cause is unchanged**: those same three gates, as a fail row in`_driver/<stage>.jsonl`, inside the first few dispatches of a clearance and identical on every retry — a model incapable of a contract is not flaky at it. It reads as an engine bug when the only fault is this configuration. A cheap-tier experiment still belongs in the three constants in `driver/engine/openai-agent.mjs` where a reviewer sees it, not in an untraceable env line. |
|
|
201
195
|
| `CLEAROTRON_DATABASE` | **REQUIRED — no default.** `corsearch` \| `clarivate` \| `signa` \| `euipo` \| `uspto-local` \| `free-tier` | Active register provider — one per run, set in the environment the deploy carries, in every environment including production. There is **no default**: unset resolves to `null` and every use of it throws, so a run refuses at start rather than calling a vendor nobody chose (the removed `corsearch` fallback named a vendor the deployment did not choose). Three are paid global sweeps; `euipo` (EU) and `uspto-local` (US) are free single-office sources, and `free-tier` composes those two as one register. Choosing a free value makes every territory outside its coverage a disclosed *deferred* row. Unknown ids throw loudly, and the gather layer throws at stage time for any provider without a built MCP server. |
|
|
202
|
-
| `CLEAROTRON_CODEX_SANDBOX_BYPASS` | unset | `1` runs `codex exec` with its own sandbox
|
|
196
|
+
| `CLEAROTRON_CODEX_SANDBOX_BYPASS` | unset | `1` runs `codex exec` with its own sandbox bypassed, for hosts where that sandbox cannot run (setup and `doctor --probe-engine` report it). It removes a defence: with it set, a stage's commands run with every permission of the account Clearotron runs as, not only in the run folder. Codex has no guard against a stage writing into the run's `_driver/` folder, with the sandbox or without it. Set it because the host forces it, never for convenience. |
|
|
203
197
|
|
|
204
198
|
## Environment variable reference
|
|
205
199
|
|
|
@@ -248,6 +242,8 @@ deployment may override (verify live values per deployment).
|
|
|
248
242
|
| `CLEAROTRON_MAX_CLAIM_AGE_MS` | 172800000 (48 h; 0 disables) | Hard ceiling on a claim's age (from the `.pid` sidecar mtime) — beyond it, re-claim regardless of liveness. |
|
|
249
243
|
| `CLEAROTRON_KNOCKOUT_VARIANT_CAP` | unset (⇒ the lane's own cap) | Ceiling on variants a knockout screens per name. Set only to bound an unusually wide batch; absent means the lane decides. |
|
|
250
244
|
| `CLEAROTRON_KNOCKOUT_RECORD_CAP` | unset (⇒ the lane's own cap) | Ceiling on records a knockout fetches per hit. Same shape as the variant cap: absent is the normal state. |
|
|
245
|
+
| `CLEAROTRON_SIGNA_ANSWER_MEMORY` | `off` | On the Signa register, whether a run reuses an answer it already holds instead of asking again. `off` asks every time. `watch` also asks every time, and records whether a held answer would have matched. `on` reuses held answers. |
|
|
246
|
+
| `CLEAROTRON_CLARIVATE_ANSWER_MEMORY` | `on` | On the Clarivate register, whether a run reuses a count, a search, an owner lookup or a record it already holds instead of asking again. `off` asks every time. |
|
|
251
247
|
|
|
252
248
|
### Retries, timeouts, watchdogs
|
|
253
249
|
|
|
@@ -281,10 +277,9 @@ unrecognised policy value that leaves the default behaviour standing.
|
|
|
281
277
|
|
|
282
278
|
| Var | Gates |
|
|
283
279
|
|---|---|
|
|
284
|
-
| `CLEAROTRON_RECALL_PROBES` / `CLEAROTRON_RECALL_TRIPWIRE` | Prior-confirmed-conflict plan probes / recall store reads + regression check. |
|
|
285
280
|
| `CLEAROTRON_PLAN_DISPATCH` (`0` or `off` disables) | Pure-code provider `executePlan` repairs at fan-in and reopen. **Never silently inert:** every entry in `PROVIDERS` ships an `executePlan` adapter, and `preflightCredentials` refuses the run before any spend under one that does not — a credential is not a capability. §5.4 of [05-config-governance.md](05-config-governance.md) still lists `signa` as the exception to that and has not been updated since its two missing tools were mounted. |
|
|
286
281
|
| `CLEAROTRON_FRAME_REOPEN` (+ `CLEAROTRON_FRAME_REOPEN_MAX`, default 1) | The bounded frame-diff reopen. |
|
|
287
|
-
| `CLEAROTRON_REGISTER_GAP_CLAMP` | The registerGap
|
|
282
|
+
| `CLEAROTRON_REGISTER_GAP_CLAMP` | The registerGap verdict clamp arm. |
|
|
288
283
|
| `CLEAROTRON_REOPEN_MAX_FETCH` (default 150) | Detail-fetch ceiling inside the reopen closure pass. |
|
|
289
284
|
| `CLEAROTRON_UNREACHABLE_SENIOR` (`open-item` \| `clamp`, default `open-item`) | Policy when a verdict-driving senior right can't be retrieved. |
|
|
290
285
|
|