clearotron 0.3.2-beta.11 → 0.3.2-beta.13
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 +1 -1
- package/CONTRIBUTING.md +6 -5
- package/INSTALL.md +3 -4
- package/README.md +2 -1
- package/bin/clearotron.mjs +14 -0
- package/bin/connect.mjs +68 -3
- package/bin/example.mjs +12 -1
- package/bin/key.mjs +6 -1
- package/bin/onboard.mjs +23 -3
- package/bin/passphrase.mjs +4 -2
- package/bin/start.mjs +18 -6
- package/build-info.json +2 -2
- package/docs/CLIENT-MCP.md +6 -6
- package/docs/DELIVERY.md +3 -3
- package/docs/ONBOARDING.md +1 -1
- package/docs/PORTAL.md +3 -3
- package/docs/RELEASES.md +1 -1
- package/docs/SECURITY.md +1 -1
- package/docs/architecture/04-configuration-reference.md +4 -4
- package/docs/architecture/05-config-governance.md +10 -10
- package/docs/architecture/06-operations-runbook.md +3 -3
- package/docs/architecture/07-quality-and-audit.md +1 -1
- package/docs/architecture/08-development-guide.md +2 -2
- package/docs/architecture/09-security-and-data.md +1 -1
- package/docs/decisions/0002-no-dark-functionality.md +1 -1
- package/docs/decisions/0006-what-the-public-repository-carries.md +3 -3
- package/driver/CHANGELOG.md +29 -0
- package/driver/ask-ledger.mjs +1 -1
- package/driver/band-shape.mjs +1 -1
- package/driver/bundled-demos.mjs +2 -2
- package/driver/card-budget.mjs +2 -2
- package/driver/case-law-ledger.mjs +2 -2
- package/driver/connotation-search.mjs +5 -5
- package/driver/contract-e3-backlog.mjs +13 -13
- package/driver/contract-vocabulary.mjs +5 -5
- package/driver/coverage-form.mjs +2 -2
- package/driver/demo-container.mjs +26 -2
- package/driver/disposition-tool.mjs +2 -2
- package/driver/engine/CONTRACT.md +3 -3
- package/driver/engine/mcp/gather-config.mjs +1 -1
- package/driver/engine/mcp/recording-server.mjs +1 -1
- package/driver/engine/mcp/supplemental.mjs +22 -5
- package/driver/engine/openai-agent.mjs +2 -2
- package/driver/findings-model.mjs +21 -6
- package/driver/gateway.mjs +1 -1
- package/driver/knockout-next-step.mjs +72 -0
- package/driver/named-band.mjs +1 -1
- package/driver/package.json +1 -1
- package/driver/pipeline-knockout.mjs +27 -1
- package/driver/pipeline.mjs +4 -4
- package/driver/placement-union.mjs +1 -1
- package/driver/portal-mcp-client.mjs +1 -1
- package/driver/portal-report.mjs +25 -3
- package/driver/portal-service.mjs +25 -13
- package/driver/predelivery-lint.mjs +9 -4
- package/driver/progress.mjs +37 -1
- package/driver/publish/render-knockout.mjs +14 -9
- package/driver/publish/render.mjs +6 -6
- package/driver/record-discard.mjs +1 -1
- package/driver/register-availability.mjs +1 -1
- package/driver/register-count.mjs +1 -1
- package/driver/register-digest-record.mjs +1 -1
- package/driver/register-plan.mjs +81 -11
- package/driver/report-card-record.mjs +2 -2
- package/driver/result-noun-fields.mjs +3 -1
- package/driver/roster-verdict.mjs +2 -2
- package/driver/search-policy.mjs +1 -1
- package/driver/skeptic-record.mjs +1 -1
- package/driver/stages-knockout.mjs +1 -1
- package/driver/stages.mjs +1 -1
- package/driver/suite-census.json +72 -24
- package/driver/systemd/README.md +1 -1
- package/driver/unit-inventory.mjs +2 -2
- package/driver/verify-knockout.mjs +0 -27
- package/driver/verify.mjs +1 -1
- package/mcp-server/CHANGELOG.md +8 -0
- package/mcp-server/CONNECT.md +8 -8
- package/mcp-server/lib/runs.mjs +1 -1
- package/mcp-server/package.json +1 -1
- package/mcp-server/serve.mjs +27 -0
- package/package.json +1 -1
- package/portal-ui/dist/assets/{index-CtvwLCti.css → index-7Lq-dXDV.css} +12 -9
- package/portal-ui/dist/assets/{index-DXSRxPV_.js → index-w8GFZftk.js} +110 -69
- package/portal-ui/dist/index.html +2 -2
- package/portal-ui/package.json +1 -1
- package/providers/free-tier/src/capabilities.js +2 -2
- package/providers/jx/src/core.js +3 -3
- package/providers/jx/src/turn-envelope.mjs +1 -1
- package/providers/oauth-mcp-bridge/CHANGELOG.md +8 -0
- package/providers/oauth-mcp-bridge/package.json +1 -1
- package/providers/perplexity/README.md +1 -1
- package/providers/signa/src/capabilities.js +2 -2
- package/providers/signa/src/core.js +2 -2
- package/providers/uspto-local/src/core.js +1 -1
- package/providers/uspto-local/src/sync.js +1 -1
- package/scripts/README.md +2 -6
- package/scripts/ask-ai-render-check.mjs +26 -1
- package/scripts/citation-anchor-report.mjs +1 -1
- package/scripts/citation-line-check.mjs +3 -3
- package/scripts/dead-names.mjs +17 -16
- package/scripts/e2e.mjs +1 -1
- package/scripts/env-audit.mjs +7 -1
- package/scripts/env-classify.mjs +1 -1
- package/scripts/pack-publishable.mjs +1 -1
- package/scripts/release-artifact-seal.mjs +2 -2
- package/scripts/repo-writes.mjs +42 -0
- package/scripts/report-sections-render-check.mjs +245 -0
- package/scripts/report-theme-render-check.mjs +31 -3
- package/scripts/settings-render-check.mjs +15 -8
- package/scripts/strip-tracker-citations.mjs +4 -4
- package/scripts/test-run.mjs +108 -6
- package/shared/browser-temp-root.mjs +10 -3
- package/shared/client-door.mjs +38 -6
- package/shared/connect-clients.mjs +2 -0
- package/shared/identifier-scan.mjs +2 -2
- package/shared/invocation.mjs +1 -1
- package/shared/parent-watch.mjs +33 -0
- package/shared/reference-guard-classes.mjs +5 -3
- package/shared/running-start.mjs +14 -3
- package/shared/scope.mjs +22 -3
- package/shared/stdio-connect.mjs +39 -18
- package/shared/writing-standard-classes.mjs +2 -3
|
@@ -97,7 +97,7 @@ product doc.
|
|
|
97
97
|
| **Allowlist** (`{version, grants:[{email, customer}]}`) | T2 | git + PR on the `CLIENT_ACCESS_MAP` file | see §2 row 4 | LIVE, file-only; surfaced read-only at `admin.access` |
|
|
98
98
|
| **Ops tokens** (scope ops/user, verbs, companies, TTL) | T4 | `mint-token.mjs` CLI; jti denylist file | operator-held tokens | LIVE, CLI |
|
|
99
99
|
|
|
100
|
-
## 4b. The install surface names
|
|
100
|
+
## 4b. The install surface names
|
|
101
101
|
|
|
102
102
|
The variables a **user or installer** ever types carry the product’s own prefix. They are listed
|
|
103
103
|
by name in §5 below and in the upgrade table in INSTALL.md.
|
|
@@ -123,14 +123,14 @@ has taken it.
|
|
|
123
123
|
|
|
124
124
|
**`CLEAROTRON_JX_LANES` was held back from the August 2026 rename** — it was RETIRED 2026-07-27
|
|
125
125
|
(`pipeline.mjs` `RETIRED_ENV`, `jx-units.mjs`) and nothing reads it, so renaming a dead name looked like
|
|
126
|
-
handing an operator a name that warns about nothing.
|
|
126
|
+
handing an operator a name that warns about nothing. A decision of 2026-09-04 reversed that: the
|
|
127
127
|
whole namespace carries one prefix, dead names included, because a tree spelled two ways costs more
|
|
128
128
|
than a retired row spelled consistently. The per-lane `CLEAROTRON_NATIVE_LANGUAGE_<code>` switch in the same row **is** live and is
|
|
129
|
-
fail-OPEN: unset means ON (§5.5
|
|
129
|
+
fail-OPEN: unset means ON (§5.5).
|
|
130
130
|
|
|
131
131
|
Variables outside the install surface were left alone by the August rename — `CLEAROTRON_ENGINE_MAX_BUFFER`
|
|
132
|
-
and its siblings were never in that window. **That separate decision was taken on 2026-09-04**: the
|
|
133
|
-
|
|
132
|
+
and its siblings were never in that window. **That separate decision was taken on 2026-09-04**: the rename
|
|
133
|
+
became global and pre-cut, so the internals carry the house prefix too and the public tree never
|
|
134
134
|
shows the old namespace. No compatibility layer, no alias reading, no migration — greenfield, and our own
|
|
135
135
|
boxes rebuild.
|
|
136
136
|
|
|
@@ -207,10 +207,10 @@ move once the same window has been read across more runs.
|
|
|
207
207
|
`CLEAROTRON_BAND_TRUTH_GATE` (**never disable in prod — restores the fabrication**),
|
|
208
208
|
`CLEAROTRON_FRAME_REOPEN` (+`CLEAROTRON_FRAME_REOPEN_MAX`=1, `CLEAROTRON_REOPEN_MAX_FETCH`=150),
|
|
209
209
|
`CLEAROTRON_REGISTER_GAP_CLAMP`, `CLEAROTRON_RECALL_PROBES`, `CLEAROTRON_RECALL_TRIPWIRE`, `CLEAROTRON_WARM_RETRY`,
|
|
210
|
-
`CLEAROTRON_MODEL_WIRE_CHECK` (
|
|
210
|
+
`CLEAROTRON_MODEL_WIRE_CHECK` (fails a turn whose
|
|
211
211
|
provider reports a different model FAMILY than the driver asked for; disarming it silences the refusal
|
|
212
212
|
and never the record: `modelActual`/`modelMismatch` keep landing on every dispatch row), `CLEAROTRON_FORM_REPAIR`
|
|
213
|
-
(
|
|
213
|
+
(repairs a form-class stage failure inside the dispatch, up to twice; disarmed, the defect
|
|
214
214
|
falls through to the retry ladder exactly as it did before, visibly, and is never swallowed as
|
|
215
215
|
"validated fine"). Policy knob: `CLEAROTRON_UNREACHABLE_SENIOR`
|
|
216
216
|
(open-item|clamp). Enumerate: `CLEAROTRON_ENUMERATE_CEILING` (600/OR-stack),
|
|
@@ -359,7 +359,7 @@ systemd, writes no heartbeat, and must keep saying "waiting to start" rather tha
|
|
|
359
359
|
repo** — `git grep process.env.CLIENT_ACCESS` here returns nothing, so they are governed here and
|
|
360
360
|
never appear in the audit).
|
|
361
361
|
|
|
362
|
-
**Which identity source the portal runs
|
|
362
|
+
**Which identity source the portal runs — T4, and it is chosen by name, never inferred.**
|
|
363
363
|
`PORTAL_AUTH_MODE` selects the door: unset or `auth-proxy` (the default for a hosted deployment) means
|
|
364
364
|
any login system in front that authenticates in the browser and forwards a verifiable JWT per request.
|
|
365
365
|
**Any OIDC or JWT proxy is a choice per deployment** — for example Cloudflare Access, which is not a
|
|
@@ -367,7 +367,7 @@ special case in the code; `local` means one address and one passphrase on loopba
|
|
|
367
367
|
exactly the same thing** — normalised where the mode is read rather than by an alias row, because
|
|
368
368
|
`shared/env-aliases.mjs` maps variable NAMES and there is no value-alias mechanism.
|
|
369
369
|
|
|
370
|
-
**Bringing your own login provider
|
|
370
|
+
**Bringing your own login provider — T4.**`PORTAL_OIDC_ISSUER`,
|
|
371
371
|
`PORTAL_JWKS_URL`, `PORTAL_EMAIL_CLAIM` and `PORTAL_AUTH_HEADER` are the portal-side spelling of the four
|
|
372
372
|
values the staff MCP face already reads as `TRADEMARK_MCP_OIDC_ISSUER`, `TRADEMARK_MCP_JWKS_URL`,
|
|
373
373
|
`TRADEMARK_MCP_EMAIL_CLAIM` and `TRADEMARK_MCP_AUTH_HEADER`. `makeAccessVerifier` has always accepted them; the portal
|
|
@@ -432,7 +432,7 @@ synthetic identity would answer before the mandatory key ever ran. The mode is l
|
|
|
432
432
|
travels in a header or the query string), requires `TRADEMARK_MCP_ALLOWED_HOSTS` exactly as the
|
|
433
433
|
authenticated door does, and mirrors its mandatory `CLEAROTRON_ACCESS_FILE`.
|
|
434
434
|
|
|
435
|
-
**The local install sets all of the above itself.**`
|
|
435
|
+
**The local install sets all of the above itself.**`clearotron start` (`bin/start.mjs`) is a supervisor:
|
|
436
436
|
it resolves one set of ports, derives `PORTAL_MCP_URL` and `TRADEMARK_MCP_ALLOWED_HOSTS` from them, mints
|
|
437
437
|
the ops key in memory, and hands each child an explicit environment carrying `CLEAROTRON_NO_ENV_FILE=1`. So
|
|
438
438
|
exactly one process in that tree reads `<repo>/.env` — the supervisor — and nothing a laptop runs needs
|
|
@@ -73,7 +73,7 @@ properties below, each of which was learned the expensive way:
|
|
|
73
73
|
mid-run feeds one expensive run two different skill versions. **Call
|
|
74
74
|
check that nothing is in flight and abort if anything is** — read every queue this
|
|
75
75
|
deployment would drain plus the run-slot locks, and refuse on any of them. `--override
|
|
76
|
-
"<reason>"` is the
|
|
76
|
+
"<reason>"` is the operator's deliberate exception; the reason is printed into the deploy output, and a
|
|
77
77
|
blank one exits 2 rather than passing. This step used to be a line of prose asking a human to
|
|
78
78
|
check, which is not a guard on the night it matters. Then **stop the four trigger units** for
|
|
79
79
|
the deploy window and install an **EXIT trap that restarts them on every exit path**, success or
|
|
@@ -184,7 +184,7 @@ rather than stage compute. That gateway is no longer part of the product, so the
|
|
|
184
184
|
to probe and the file went with them. Nothing invoked it: not `package.json`, not `bin/`, not
|
|
185
185
|
`scripts/`, not a unit, not CI. It was run by hand, and it spent real money when it was.
|
|
186
186
|
|
|
187
|
-
What replaces each half: the free path check is `
|
|
187
|
+
What replaces each half: the free path check is `clearotron doctor` plus the runner's own preflights
|
|
188
188
|
(`preflightEngineBinary`, `preflightCredentials`, `preflightDeploymentUrls`), each of which refuses by
|
|
189
189
|
name before a run dir exists. The billable half has no replacement and needs none — stage compute is
|
|
190
190
|
exercised by real runs and the A/B harness, which is what its own note already said.
|
|
@@ -289,7 +289,7 @@ Copy it, point `CLEAROTRON_ACCESS_FILE` at your copy, sign in as one of its addr
|
|
|
289
289
|
exactly that organisation's companies. Then delete it and write your own — it names nobody real, which also
|
|
290
290
|
means it grants nothing you have.
|
|
291
291
|
|
|
292
|
-
`
|
|
292
|
+
`clearotron start` (§6) writes an empty roster (`{"tenants": {}}`) into its state directory: your own staff
|
|
293
293
|
address is admitted, nobody else is enrolled, and enforcement is already on.
|
|
294
294
|
|
|
295
295
|
### Ops tokens — a credential for the verbs that spend
|
|
@@ -269,7 +269,7 @@ write nothing and 7 that do:
|
|
|
269
269
|
`what_if_run` → one sandboxed stage; `what_if_result` → collect a queued one) — **executing** is
|
|
270
270
|
local stdio only, never remote, for any principal. The confirmation token is a deliberate-action
|
|
271
271
|
handshake, not a crypto boundary; the security boundary is ops scope + local-only execution.
|
|
272
|
-
Since
|
|
272
|
+
Since 2026-08-27 an `account` principal reaches all three, and `what_if_run` on that
|
|
273
273
|
path ENQUEUES into `<runDir>/_experiments/_queue/` rather than shelling — `driver/whatif-worker.mjs`,
|
|
274
274
|
drained by the runner, is what spawns the sandbox. Because the token is unsigned, a call on that path must
|
|
275
275
|
also name its `runId` so the grant check fires, and the enqueue refuses a token naming another run.
|
|
@@ -88,7 +88,7 @@ These are the things a well-meaning refactor breaks. Each is enforced somewhere;
|
|
|
88
88
|
|
|
89
89
|
Mechanically a config change ([04](04-configuration-reference.md#model-tiers-and-resolution)); two
|
|
90
90
|
traps and one law. Traps: an alias not registered in the engine's model map now **refuses the
|
|
91
|
-
dispatch by name** (
|
|
91
|
+
dispatch by name** (it used to run sonnet silently and log the alias you asked for, which is
|
|
92
92
|
the `fable` lesson turned into an error), and `CLEAROTRON_SYNTHESIS_MODEL` is read at module load (fine
|
|
93
93
|
for the oneshot service, stale in long-lived processes). The law: any grade-moving
|
|
94
94
|
change — family, effort, tier remap — ships only through the paid A/B against the reference
|
|
@@ -221,7 +221,7 @@ Four realities to respect:
|
|
|
221
221
|
|
|
222
222
|
- **Exclusion is by filename convention only.** Anything named `*.test.mjs` runs in CI; billable or
|
|
223
223
|
manual harnesses must not match the glob (historical one-off proofs with hard-coded dev paths are
|
|
224
|
-
not kept; the last billable hand-run harness, `selftest.mjs`, was deleted
|
|
224
|
+
not kept; the last billable hand-run harness, `selftest.mjs`, was deleted).
|
|
225
225
|
- **The `||=` env guards leak**: a shell exporting a real register credential or
|
|
226
226
|
`CLEAROTRON_PLAN_DISPATCH=on` is *not* overridden by the harness — run the suite in a clean env.
|
|
227
227
|
(CI is safe.)
|
|
@@ -83,7 +83,7 @@ are no root units; everything is `systemd --user`.
|
|
|
83
83
|
are stripped), and **`account`** (a signed-in person on the client face — the runs of the
|
|
84
84
|
companies they are granted, reached either by the CF sign-in with no token, or by a per-person API
|
|
85
85
|
key, `scope: account`, whose companies are re-read from the grants file on every request rather than
|
|
86
|
-
baked into it. Wider *reach* than a report link and, since
|
|
86
|
+
baked into it. Wider *reach* than a report link and, since a decision of 2026-08-27, more
|
|
87
87
|
*depth* too: the audit chain — the audit trail, the reasoning narrative, the record artifacts, a
|
|
88
88
|
register axis, and the `get_run` / `trace` / `decision_timeline` decision walk. Model identity
|
|
89
89
|
and billed counts stay sealed (`get_telemetry`, `get_provider_usage`), as does the reviewers'
|
|
@@ -60,7 +60,7 @@ Every `CLEAROTRON_*` name read by shipping code declares an effect class, and an
|
|
|
60
60
|
whatever the declaration test enforces. Do not re-derive it by hand; that is how 172, 159 and 352 all
|
|
61
61
|
came to describe the same repository.
|
|
62
62
|
|
|
63
|
-
## Addendum — 2026-08-20, on implementation
|
|
63
|
+
## Addendum — 2026-08-20, on implementation
|
|
64
64
|
|
|
65
65
|
All four switches are deleted, as ruled. One consequence above is narrowed by what the code turned out
|
|
66
66
|
to be, and it is recorded here rather than in a pull request body, because this document is what the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 0006 — What the public repository carries
|
|
2
2
|
|
|
3
|
-
**Accepted 2026-08-17
|
|
3
|
+
**Accepted 2026-08-17.**
|
|
4
4
|
|
|
5
5
|
## Context
|
|
6
6
|
|
|
@@ -74,7 +74,7 @@ announces which mode it is in, once, so a reader of any run can tell which colum
|
|
|
74
74
|
"change the code" is the clause it answers to and this repository's working practice is that agents change
|
|
75
75
|
the code. `CLAUDE.md` is not carried: it was only ever a one-line pointer at `AGENTS.md`, a second copy of
|
|
76
76
|
one subject is a future contradiction ([ADR-0004](0004-documentation-structure.md)), and the de-identified
|
|
77
|
-
public cut names that file specifically.
|
|
77
|
+
public cut names that file specifically. Decided 2026-08-19, on the question raised against the
|
|
78
78
|
recovery — where the two files had been held back because the revert that stripped them recorded no
|
|
79
79
|
decision either way, and `shared/withheld-paths.mjs` did not cover them.
|
|
80
80
|
|
|
@@ -89,7 +89,7 @@ vendor-branded duplicate of it does not, however small.
|
|
|
89
89
|
citations across code, comments, env examples and docs; all but six were rewritten, and the six declared
|
|
90
90
|
are this record's own, where naming what is dropped is the content.
|
|
91
91
|
- **A binding to a withheld document is retired.** `driver/doc-constants.mjs` pinned four prose figures in
|
|
92
|
-
`docs/KNOCKOUT.md` and `docs/REGISTER-HIT-COUNTS.md`; those rows are gone, and the test pinning
|
|
92
|
+
`docs/KNOCKOUT.md` and `docs/REGISTER-HIT-COUNTS.md`; those rows are gone, and the test pinning the
|
|
93
93
|
one-file-states-it-twice case now anchors to the shape rather than to a named document.
|
|
94
94
|
- **Withholding is reversible**, which is why this is a list rather than a `git rm`. This repository keeps
|
|
95
95
|
every word.
|
package/driver/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# clearotron-driver
|
|
2
2
|
|
|
3
|
+
## 0.3.2-beta.13
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fixed: A conditional verdict whose conditions are all kept in the run record no longer shows an empty "conditional on" line. The rating word stands alone.
|
|
8
|
+
- Fixed: A running clearance's card and row show the stage it is in now, including a step back during a correction pass.
|
|
9
|
+
- Fixed: The portal's health check no longer includes an internal error message when the instructions store cannot be read. The message goes to the service log instead.
|
|
10
|
+
- Fixed: `doctor` no longer describes another program on the client door's port as this install's door. It says only that a process holds the port.
|
|
11
|
+
- Fixed: The connect lines name the exact Node your install runs on, and an older Node gets one plain line instead of a crash.
|
|
12
|
+
- Fixed: The demo no longer leaves copies of its samples in your temp directory, including when it is stopped mid-way.
|
|
13
|
+
- Fixed: Running the test suite no longer leaves demo copies in the machine's temporary directory.
|
|
14
|
+
- Fixed: On WSL, the Windows connect line names your Linux distribution, or says plainly to fill it in, instead of leaving it out.
|
|
15
|
+
|
|
16
|
+
## 0.3.2-beta.12
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Fixed: A demo started in the background with `npx` now stops completely when that `npx` is stopped, freeing its three ports and removing its folder.
|
|
21
|
+
- Fixed: The demo lists the door an assistant uses first, and a key refused at the wrong door is told the right door's address.
|
|
22
|
+
- Fixed: A knockout no longer asks the model what to do with each name, so each name's read keeps to the findings and the rating.
|
|
23
|
+
- Fixed: A knockout's per-name read no longer carries a next-step section the model wrote. It is removed before delivery instead of the batch being sent back to rewrite it, so knockouts finish sooner.
|
|
24
|
+
- Fixed: A report produced before this version no longer shows a second section menu inside the portal, unreadable in the dark theme.
|
|
25
|
+
- New: `clearotron connect --base <folder>` connects an assistant to a running demo, minting its key and naming its door in one step.
|
|
26
|
+
- Fixed: `doctor` now says the client door's access log has entries, instead of claiming it is being written.
|
|
27
|
+
- Fixed: The sign-in page names the install's one user, and the passphrase reset, key issue and doctor each say what they are for.
|
|
28
|
+
- Fixed: Once the client's own registered element is set aside, searches added later in the run no longer search it again.
|
|
29
|
+
- Fixed: Running the test suite on a clone whose portal build is out of date no longer rebuilds it and fails the first run.
|
|
30
|
+
- Fixed: Running the test suite no longer writes an access-log line under your home folder, and a stopped demo leaves no empty folders behind.
|
|
31
|
+
|
|
3
32
|
## 0.3.2-beta.11
|
|
4
33
|
|
|
5
34
|
### Patch Changes
|
package/driver/ask-ledger.mjs
CHANGED
|
@@ -170,7 +170,7 @@ function endingForQids(qids, join, ts) {
|
|
|
170
170
|
return null;
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
/** The {ending, handoff} pair for one cross-check directive. Only `recall` is subject to
|
|
173
|
+
/** The {ending, handoff} pair for one cross-check directive. Only `recall` is subject to the
|
|
174
174
|
* discharge rule; every other net keeps the ending it always had. PURE. */
|
|
175
175
|
function recallEnding(name, qid, join, ts) {
|
|
176
176
|
const ending = endingForQids([qid], join, ts);
|
package/driver/band-shape.mjs
CHANGED
|
@@ -769,7 +769,7 @@ export function buildBandShape(band, { targets = [], inScopeClasses = [], crowdC
|
|
|
769
769
|
}
|
|
770
770
|
|
|
771
771
|
const fmtN = (n) => Number(n ?? 0).toLocaleString("en-US");
|
|
772
|
-
const cell = (v) => String(v ?? "").replace(/\|/g, "\\|").replace(/\s+/g, " ").trim() || "—";
|
|
772
|
+
const cell = (v) => String(v ?? "").replace(/\\/g, "\\\\").replace(/\|/g, "\\|").replace(/\s+/g, " ").trim() || "—";
|
|
773
773
|
|
|
774
774
|
// Bounded aggregate table: top rows by count, one honest remainder line — never for the floors.
|
|
775
775
|
function topTable(md, title, cols, entries, cap = 30) {
|
package/driver/bundled-demos.mjs
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
// bundled-demos.mjs — WHICH client bundles this repo ships, read from the directory that ships them.
|
|
4
4
|
//
|
|
5
5
|
// This was a hand-maintained triple. The directory grew a fourth bundle, the triple did not, and the
|
|
6
|
-
// set-equality it feeds could no longer match anything — so the
|
|
7
|
-
// notice a door that has silently fallen back to the bundled roster, returned PASS on
|
|
6
|
+
// set-equality it feeds could no longer match anything — so the roster-fallback detector, whose whole job is to
|
|
7
|
+
// notice a door that has silently fallen back to the bundled roster, returned PASS on exactly that
|
|
8
8
|
// condition. A guard that cannot match reports that it found nothing wrong.
|
|
9
9
|
//
|
|
10
10
|
// The same shape had already produced two FALSE REFUSALS on this check, both from an exact match
|
package/driver/card-budget.mjs
CHANGED
|
@@ -74,13 +74,13 @@ function insertBulletAtSectionHead(text, headingRe, headingLine, bullet, { paren
|
|
|
74
74
|
const m = text.match(headingRe);
|
|
75
75
|
if (m) {
|
|
76
76
|
const at = m.index + m[0].length;
|
|
77
|
-
return `${text.slice(0, at)}\n${bullet}\n${text.slice(at)
|
|
77
|
+
return `${text.slice(0, at)}\n${bullet}\n${text.slice(at)}`;
|
|
78
78
|
}
|
|
79
79
|
if (parentHeadingRe) {
|
|
80
80
|
const p = text.match(parentHeadingRe);
|
|
81
81
|
if (p) {
|
|
82
82
|
const at = p.index + p[0].length;
|
|
83
|
-
return `${text.slice(0, at)}\n${headingLine}\n\n${bullet}\n${text.slice(at)
|
|
83
|
+
return `${text.slice(0, at)}\n${headingLine}\n\n${bullet}\n${text.slice(at)}`;
|
|
84
84
|
}
|
|
85
85
|
return `${text.replace(/\s*$/, "")}\n\n${parentHeadingLine}\n\n${headingLine}\n\n${bullet}\n`;
|
|
86
86
|
}
|
|
@@ -114,8 +114,8 @@ export function parseCaseLawLedger(raw) {
|
|
|
114
114
|
/**
|
|
115
115
|
* The census a reader (and a scenario) asks the ledger for. PURE, and it never judges.
|
|
116
116
|
*
|
|
117
|
-
* `readByTerritory` is the one that answers the depth-dive condition: a dive names ONE territory
|
|
118
|
-
*
|
|
117
|
+
* `readByTerritory` is the one that answers the depth-dive condition: a dive names ONE territory,
|
|
118
|
+
* so "did this dive read anything in its own territory" is a lookup, not an inference.
|
|
119
119
|
*/
|
|
120
120
|
export function caseLawRetrievalCensus(ledger) {
|
|
121
121
|
const queries = ledger?.queries ?? [];
|
|
@@ -1363,7 +1363,7 @@ export function parseDispositionForm(raw) {
|
|
|
1363
1363
|
// EVERY OBLIGATION SHIPS. No head(), no slice(), no "…and N more". The register-digest sibling
|
|
1364
1364
|
// (gateway.mjs deferredSlicesRequiredRows) printed the first six qids per axis and elided the rest, and its
|
|
1365
1365
|
// own doc block records what that cost: "Under advice that is an economy; under a requirement it makes
|
|
1366
|
-
// compliance impossible." Same rule here
|
|
1366
|
+
// compliance impossible." Same rule here: a value a model must copy is complete, or it is
|
|
1367
1367
|
// visibly marked as cut. Nothing below is cut, so nothing below is marked.
|
|
1368
1368
|
/**
|
|
1369
1369
|
* The obligation set as the seat's own to-do list, for the tool result. Returns "" when nothing is owed —
|
|
@@ -1375,7 +1375,7 @@ export function renderConnotationObligations(ob, { ledgerPath = "your half ledge
|
|
|
1375
1375
|
// ── — THE PAGE IS NUMBERED OFF THE SAME FUNCTION THAT RESOLVES THE NUMBER ─────────────────
|
|
1376
1376
|
//
|
|
1377
1377
|
// `obligationRows` is the driver's row list, and a `row_index` is a position into it. Numbering this
|
|
1378
|
-
// page with its own counter would be two derivations of one ordering, which is the mistake
|
|
1378
|
+
// page with its own counter would be two derivations of one ordering, which is the mistake the
|
|
1379
1379
|
// segment display already names in its own comment: "the display and the check cannot disagree, which
|
|
1380
1380
|
// they would the moment either recomputed its own split". So the numbers come from the list itself.
|
|
1381
1381
|
//
|
|
@@ -1610,7 +1610,7 @@ export function renderDispositionTable(rows, ob) {
|
|
|
1610
1610
|
for (const e of ob?.queries ?? []) for (const r of e.results) if (r.id) byId.set(normId(r.id), r);
|
|
1611
1611
|
// — the rows are the FORM's, and a row the seat never ruled on has nothing to render: it is
|
|
1612
1612
|
// outstanding work, which the gate reports as a count, not a table row reading "—".
|
|
1613
|
-
const cell = (s) => String(s ?? "").replace(/\|/g, "\\|").replace(/\s+/g, " ").trim();
|
|
1613
|
+
const cell = (s) => String(s ?? "").replace(/\\/g, "\\\\").replace(/\|/g, "\\|").replace(/\s+/g, " ").trim();
|
|
1614
1614
|
const usable = (rows ?? []).filter((d) => d?.receipt_id && d?.ruling);
|
|
1615
1615
|
// ── — A PARKED ROW IS NOT AN OUTSTANDING ROW, AND THE FILTER ABOVE STOPPED BEING SAFE ─────────
|
|
1616
1616
|
//
|
|
@@ -1683,7 +1683,7 @@ const NO_POLICED_SECTION = "(no PR / reputational / connotation section)";
|
|
|
1683
1683
|
// id that is not among THAT row's own candidates — the driver wrote those ids, so this is a damaged
|
|
1684
1684
|
// form, not outstanding work, and its remedy is different.
|
|
1685
1685
|
// undisposed_cite_too_short deleted — cannot occur; nothing is retyped.
|
|
1686
|
-
// recurrent_uncited_form deleted — the form has no shape for the seat to get wrong.
|
|
1686
|
+
// recurrent_uncited_form deleted — the form has no shape for the seat to get wrong. The old
|
|
1687
1687
|
// cited-but-unbound state was a property of PROSE (right page, wrong query string on the line); a
|
|
1688
1688
|
// form row IS its binding, so the state has no representative.
|
|
1689
1689
|
// no_source_cite deleted — advisory, prose-only, never reached a token.
|
|
@@ -1786,7 +1786,7 @@ export const CONNOTATION_FORM_REASONS = Object.freeze(
|
|
|
1786
1786
|
*
|
|
1787
1787
|
* `quote_unbound` and `form_damaged` are deliberately absent: those rows ARE ruled.
|
|
1788
1788
|
*
|
|
1789
|
-
* `parked`
|
|
1789
|
+
* `parked` is absent for the opposite reason and it is the load-bearing one: a parked row
|
|
1790
1790
|
* is NOT ruled, and it is not outstanding either. Outstanding means "the seat still owes this", and the
|
|
1791
1791
|
* whole point of the park is that the seat has been told to stop — leaving it here would keep the stage
|
|
1792
1792
|
* failing forever on a row nobody may re-send, which is the deterministic death the park introduced.
|
|
@@ -456,7 +456,7 @@ export const E3_BACKLOG = [
|
|
|
456
456
|
where: "driver/stages.mjs:3182",
|
|
457
457
|
surface: "stage-message",
|
|
458
458
|
evidence: "MACHINE FINDINGS (MANDATORY): … a JSON OBJECT {\"schema_version\":<FINDINGS_SCHEMA_VERSION>,\"rated_under_framework\":\"…\",\"findings\":[...],\"coverage\":[...],\"context_notes\":[...],\"actions\":[...],\"ask_answers\":[...]} … Each finding object has EXACTLY these keys: {\"ordinal\",\"mark\",\"owner\",\"band\",\"net\",\"bor",
|
|
459
|
-
reparsedBy: "driver/findings-model.mjs:
|
|
459
|
+
reparsedBy: "driver/findings-model.mjs:844 parseFindingsJson via validators.narrative",
|
|
460
460
|
removedByMove: "NOTHING ON THE #850 PLAN REMOVES THIS",
|
|
461
461
|
},
|
|
462
462
|
// RETIRED 2026-08-16 — synthesis's dictated disposition list, and I am the one who left it standing.
|
|
@@ -479,7 +479,7 @@ export const E3_BACKLOG = [
|
|
|
479
479
|
where: "driver/stages.mjs:3219",
|
|
480
480
|
surface: "stage-message",
|
|
481
481
|
evidence: "- manageable …: {\"category\":\"<EXACTLY one of large-competitor / commercial-partner / troll / well-known-enforcer>\",\"reason\":\"<one-two lines…>\"}",
|
|
482
|
-
reparsedBy: "driver/findings-model.mjs:
|
|
482
|
+
reparsedBy: "driver/findings-model.mjs:844 parseFindingsJson",
|
|
483
483
|
removedByMove: "NOTHING ON THE #850 PLAN REMOVES THIS",
|
|
484
484
|
},
|
|
485
485
|
{
|
|
@@ -488,7 +488,7 @@ export const E3_BACKLOG = [
|
|
|
488
488
|
where: "driver/stages.mjs:3235",
|
|
489
489
|
surface: "stage-message",
|
|
490
490
|
evidence: "- meters: {\"mark_similarity\":{...},\"goods_proximity\":{...},\"use\":{...},\"enforcer\":{...}} — all four present, each {\"token\",\"basis\",\"source\"}. … mark_similarity = high | medium | low. goods_proximity = high | medium | low. enforcer = high | medium | low | unknown. use = confirmed | not-confirmed | un",
|
|
491
|
-
reparsedBy: "driver/findings-model.mjs:
|
|
491
|
+
reparsedBy: "driver/findings-model.mjs:844 parseFindingsJson; driver/verify.mjs:1171 checkFindingsSibling gates meters.*.source; finding_basis_source_missing",
|
|
492
492
|
removedByMove: "NOTHING ON THE #850 PLAN REMOVES THIS",
|
|
493
493
|
},
|
|
494
494
|
{
|
|
@@ -497,7 +497,7 @@ export const E3_BACKLOG = [
|
|
|
497
497
|
where: "driver/stages.mjs:3236",
|
|
498
498
|
surface: "stage-message",
|
|
499
499
|
evidence: "- quadrant: {\"x\",\"y\"} numbers in [0,1]. x = goods/services proximity (0 = distant, 1 = identical). y = mark similarity (0 = distinct, 1 = identical).",
|
|
500
|
-
reparsedBy: "driver/findings-model.mjs:
|
|
500
|
+
reparsedBy: "driver/findings-model.mjs:844 parseFindingsJson",
|
|
501
501
|
removedByMove: "NOTHING ON THE #850 PLAN REMOVES THIS",
|
|
502
502
|
},
|
|
503
503
|
{
|
|
@@ -506,7 +506,7 @@ export const E3_BACKLOG = [
|
|
|
506
506
|
where: "driver/stages.mjs:3237",
|
|
507
507
|
surface: "stage-message",
|
|
508
508
|
evidence: "- source: {\"source_type\",\"resolved_link\"}. source_type EXACTLY one of: register-vendor / register-euipo / common-law-marketplace / common-law-web / case-law",
|
|
509
|
-
reparsedBy: "driver/findings-model.mjs:
|
|
509
|
+
reparsedBy: "driver/findings-model.mjs:844 parseFindingsJson",
|
|
510
510
|
removedByMove: "M1 removes the opaque `resolved_link` URI (ordinal / record-handle selection); the object shape and the source_type enum survive",
|
|
511
511
|
},
|
|
512
512
|
{
|
|
@@ -515,7 +515,7 @@ export const E3_BACKLOG = [
|
|
|
515
515
|
where: "driver/stages.mjs:3238",
|
|
516
516
|
surface: "stage-message",
|
|
517
517
|
evidence: "coverage[]: ONE object per coverage AREA, EXACTLY {\"area\",\"state\",\"note\"}. … state EXACTLY one of: confirmed-clean / coverage-limited / open / not-searched / note.",
|
|
518
|
-
reparsedBy: "driver/findings-model.mjs:
|
|
518
|
+
reparsedBy: "driver/findings-model.mjs:844 parseFindingsJson; the render owns the coverage panel from these typed states",
|
|
519
519
|
removedByMove: "NOTHING ON THE #850 PLAN REMOVES THIS",
|
|
520
520
|
},
|
|
521
521
|
{
|
|
@@ -533,7 +533,7 @@ export const E3_BACKLOG = [
|
|
|
533
533
|
where: "driver/stages.mjs:3304",
|
|
534
534
|
surface: "stage-message",
|
|
535
535
|
evidence: "MARK ASSESSMENT … STRUCTURED FORM …: either field may instead be an OBJECT {\"read\":\"…\",\"spectrum\":\"…\",\"per_class\":[{\"class\":\"5\",\"note\":\"…\"}],\"per_market\":[{\"market\":\"CN\",\"note\":\"…\"}],\"counter_registrations\":[{\"mark\":\"…\",\"uri\":\"/mark/…\",\"note\":\"…\"}],\"acquired\":\"<optional>\",\"note\":\"<optional residual>",
|
|
536
|
-
reparsedBy: "driver/findings-model.mjs:
|
|
536
|
+
reparsedBy: "driver/findings-model.mjs:844 parseFindingsJson; the report collapses the rows behind toggles and the audit workbook renders them",
|
|
537
537
|
removedByMove: "NOTHING ON THE #850 PLAN REMOVES THIS",
|
|
538
538
|
},
|
|
539
539
|
{
|
|
@@ -542,7 +542,7 @@ export const E3_BACKLOG = [
|
|
|
542
542
|
where: "driver/stages.mjs:3310",
|
|
543
543
|
surface: "stage-message",
|
|
544
544
|
evidence: "FOUR ANSWERS …: \"four_answers\": {\"third_party_rights\":{...},\"objection_likelihood\":{...},\"registrability\":{...},\"client_enforceability\":{...}} … Each answer … is {\"read\":\"…\",\"token\":\"…\",\"basis\":\"…\",\"ordinals\":[…]}. Tokens (closed enums …): third_party_rights = strong|moderate|weak; objection_likelih",
|
|
545
|
-
reparsedBy: "driver/findings-model.mjs:
|
|
545
|
+
reparsedBy: "driver/findings-model.mjs:844 parseFindingsJson",
|
|
546
546
|
removedByMove: "NOTHING ON THE #850 PLAN REMOVES THIS",
|
|
547
547
|
},
|
|
548
548
|
{
|
|
@@ -551,7 +551,7 @@ export const E3_BACKLOG = [
|
|
|
551
551
|
where: "driver/stages.mjs:3221",
|
|
552
552
|
surface: "stage-message",
|
|
553
553
|
evidence: "ACTIONS REGISTER …: emit \"actions\": [...] — ONE object per forward step …, each EXACTLY {\"id\",\"kind\",\"text\",\"ordinals\"} plus an OPTIONAL \"deadline\" and an OPTIONAL \"condition\". … kind: EXACTLY one of — consent / coexistence-agreement / territorial-delimitation / goods-amendment / mark-modification /",
|
|
554
|
-
reparsedBy: "driver/findings-model.mjs:
|
|
554
|
+
reparsedBy: "driver/findings-model.mjs:844 parseFindingsJson; pipeline applyCoverageFloor legalActions arm derives the delivered disposition from the closed kind enum",
|
|
555
555
|
removedByMove: "NOTHING ON THE #850 PLAN REMOVES THIS",
|
|
556
556
|
},
|
|
557
557
|
{
|
|
@@ -560,7 +560,7 @@ export const E3_BACKLOG = [
|
|
|
560
560
|
where: "driver/stages.mjs:3317",
|
|
561
561
|
surface: "stage-message",
|
|
562
562
|
evidence: "COVERAGE JUDGMENT …: emit \"coverage_judgment\": {\"sufficient\":<bool>, \"reason\":\"<one line…>\"} — EXACTLY those two keys. Do NOT emit \"rows\": the driver writes that register itself … anything you type there is replaced wholesale.",
|
|
563
|
-
reparsedBy: "driver/findings-model.mjs:
|
|
563
|
+
reparsedBy: "driver/findings-model.mjs:844 parseFindingsJson. The \"Do NOT emit rows\" clause is the purest E3 case in the tree — the prompt names a field, dictates its shape and states in the same breath that code overwrites it",
|
|
564
564
|
removedByMove: "NOTHING ON THE #850 PLAN REMOVES THIS",
|
|
565
565
|
},
|
|
566
566
|
{
|
|
@@ -575,7 +575,7 @@ export const E3_BACKLOG = [
|
|
|
575
575
|
// in E3_EVIDENCE_UNRESOLVED instead would have grown the not-checked slice for a row that is
|
|
576
576
|
// perfectly checkable, which is the avoidable coverage loss conversion 9's note names one row up.
|
|
577
577
|
evidence: "SEND ONE \"ask_answers\" ENTRY PER ASK, as a TOP-LEVEL field of the findings record you hand to the call (never as a narrative section — the driver renders the labelled line",
|
|
578
|
-
reparsedBy: "driver/findings-model.mjs:
|
|
578
|
+
reparsedBy: "driver/findings-model.mjs:844 parseFindingsJson (finding_ask_answer_answer_missing); assembleReportMd · buildAskAnswersSection joins on the retyped ask string",
|
|
579
579
|
removedByMove: "NOTHING ON THE #850 PLAN REMOVES THIS",
|
|
580
580
|
},
|
|
581
581
|
// DELETED at conversion 10, recorded rather than absorbed — E3's own rule for a
|
|
@@ -611,7 +611,7 @@ export const E3_BACKLOG = [
|
|
|
611
611
|
where: "driver/stages.mjs:3296",
|
|
612
612
|
surface: "stage-message",
|
|
613
613
|
evidence: "add it to the top-level \"context_notes\" array — each object EXACTLY {\"type\":\"famous-neighbour-ungrounded\",\"mark\",\"owner\",\"context\"}",
|
|
614
|
-
reparsedBy: "driver/findings-model.mjs:
|
|
614
|
+
reparsedBy: "driver/findings-model.mjs:844 parseFindingsJson",
|
|
615
615
|
removedByMove: "NOTHING ON THE #850 PLAN REMOVES THIS",
|
|
616
616
|
},
|
|
617
617
|
{
|
|
@@ -620,7 +620,7 @@ export const E3_BACKLOG = [
|
|
|
620
620
|
where: "driver/stages.mjs:3184",
|
|
621
621
|
surface: "stage-message",
|
|
622
622
|
evidence: "- owner: {\"name\",\"country\",\"registrations\":[...]}. … Each registration: {\"uri\", optionally \"classes\":[\"9\",\"41\"],\"status\",\"filed\",\"expiry\",\"jurisdiction\"}. The \"uri\" is the ONLY field that matters: the driver BINDS classes/status/filed/expiry/jurisdiction AND the owner name from the FETCHED record ke",
|
|
623
|
-
reparsedBy: "driver/findings-model.mjs:
|
|
623
|
+
reparsedBy: "driver/findings-model.mjs:844 parseFindingsJson + the record-binding join. Six of the seven keys are stated in the prompt and overwritten by code in the same sentence",
|
|
624
624
|
removedByMove: "M1 removes the opaque `uri` (ordinal / record-handle selection against the band); the object skeleton and the five overwritten keys survive",
|
|
625
625
|
},
|
|
626
626
|
{
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
// D4 verify.mjs parseCoverageLedgerJson, same shape
|
|
22
22
|
// D5 verify.mjs:1504 fail(`${unaccounted[0].token}:…`) — token minted in a DATA ROW
|
|
23
23
|
// D6 verify.mjs:1567 fail(`${violations[0].token}…`) — validatePlanFeasibility in register-plan.mjs
|
|
24
|
-
// D7 verify.mjs:1558 fail(`${v2[0].token}${detail}…`) — register-plan.mjs:
|
|
24
|
+
// D7 verify.mjs:1558 fail(`${v2[0].token}${detail}…`) — register-plan.mjs:2270 disclosureTextByAxis
|
|
25
25
|
// D8 verify.mjs:2470 caseLawLedgerFail fail(caseLawLedgerFail(…)) — token built in case-law-ledger.mjs:195 caseLawLedgerFail
|
|
26
26
|
//
|
|
27
27
|
// A partition built on the 60 tokens a regex CAN see would run green while blind to the rest, which is
|
|
@@ -139,10 +139,10 @@ export const VOCABULARY = [
|
|
|
139
139
|
{ token: "coverage_form_missing", stages: ["register-digest"], site: "driver/verify.mjs" },
|
|
140
140
|
{ token: "coverage_form_empty", stages: ["register-digest"], site: "driver/verify.mjs" },
|
|
141
141
|
{ token: "coverage_status_offenum", stages: ["register-digest"], site: "driver/verify.mjs:2050" },
|
|
142
|
-
{ token: "coverage_deferred_unaccounted", stages: ["register-digest"], site: "driver/verify.mjs coverageFormFail", family: "driver/register-plan.mjs:
|
|
143
|
-
{ token: "coverage_clean_unexecuted", stages: ["register-digest"], site: "driver/verify.mjs, the matterContext validator", family: "driver/register-plan.mjs:
|
|
144
|
-
{ token: "coverage_clean_skipped", stages: ["register-digest"], site: "driver/verify.mjs, the matterContext validator", family: "driver/register-plan.mjs:
|
|
145
|
-
{ token: "coverage_clean_unverified_incomplete", stages: ["register-digest"], site: "driver/verify.mjs, the matterContext validator", family: "driver/register-plan.mjs:
|
|
142
|
+
{ token: "coverage_deferred_unaccounted", stages: ["register-digest"], site: "driver/verify.mjs coverageFormFail", family: "driver/register-plan.mjs:1947 PROVIDER_HARD_ERROR_PREFIX — token on a data row", dynamic: "D5" },
|
|
143
|
+
{ token: "coverage_clean_unexecuted", stages: ["register-digest"], site: "driver/verify.mjs, the matterContext validator", family: "driver/register-plan.mjs:1681 validatePlanFeasibility", dynamic: "D6" },
|
|
144
|
+
{ token: "coverage_clean_skipped", stages: ["register-digest"], site: "driver/verify.mjs, the matterContext validator", family: "driver/register-plan.mjs:2042 searchedJurisdictionsFromPlan", dynamic: "D6" },
|
|
145
|
+
{ token: "coverage_clean_unverified_incomplete", stages: ["register-digest"], site: "driver/verify.mjs, the matterContext validator", family: "driver/register-plan.mjs:2270 disclosureTextByAxis", dynamic: "D7" },
|
|
146
146
|
{ token: "coverage_clean_tainted", stages: ["register-digest"], site: "driver/verify.mjs" },
|
|
147
147
|
{ token: "coverage_ledger_", stages: ["register-digest"], site: "driver/verify.mjs", family: "driver/coverage-ledger.mjs (parseCoverageLedgerJson token-first throws)", dynamic: "D4" },
|
|
148
148
|
{ token: "coverage_key_unknown", stages: ["register-digest"], site: "driver/verify.mjs", family: "driver/coverage-ledger.mjs", dynamic: "D4" },
|
package/driver/coverage-form.mjs
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
// PASS; ~86% of emitted tokens landed in no artifact, and the attempt that passed is the one that
|
|
14
14
|
// PATCHED). A cold ladder never patches.
|
|
15
15
|
//
|
|
16
|
-
// THE CURE IS
|
|
16
|
+
// THE CURE IS THE ONE APPLIED ONE GATE OVER: the driver writes the row and the model fills in the judgment. The
|
|
17
17
|
// axis, the coverage unit, the open crowd blocks with their qids and hit counts, and the deferred slices
|
|
18
18
|
// with their per-qid receipt reasons are all facts the driver holds BEFORE the stage dispatches. It
|
|
19
19
|
// writes them. The seat sets `status` and `reason`, and nothing else in the file is the seat's to write.
|
|
@@ -856,7 +856,7 @@ export function findCoverageFormViolations(rows, formError = null) {
|
|
|
856
856
|
// kind and nothing in it is a string the model had to copy. parseCoverageLedgerFull survives, but only as
|
|
857
857
|
// the ARCHIVED-RUN reader (loadCoverageLedger's prose fallback): no gate parses this table any more.
|
|
858
858
|
|
|
859
|
-
const cell = (s) => String(s ?? "").replace(/\|/g, "\\|").replace(/\s+/g, " ").trim();
|
|
859
|
+
const cell = (s) => String(s ?? "").replace(/\\/g, "\\\\").replace(/\|/g, "\\|").replace(/\s+/g, " ").trim();
|
|
860
860
|
|
|
861
861
|
/** The `## Coverage ledger` section, rendered from the form's rows. "" when nothing is settled. PURE. */
|
|
862
862
|
export function renderCoverageLedgerSection(rows) {
|
|
@@ -97,6 +97,30 @@ export function prepareSample(dir, { repoRoot, tmp } = {}) {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
|
|
100
|
+
/**
|
|
101
|
+
* THE COPIES GO WHEN THEIR PUBLISH IS DONE, AND AT EXIT WHATEVER HAPPENED.
|
|
102
|
+
*
|
|
103
|
+
* Every copy below is made in the system temp directory and nothing removed it: four per `demo --once`,
|
|
104
|
+
* one per demo start, some a full replayed run of about 1,850 files, and 36 GB of them on one machine
|
|
105
|
+
* (measured 2026-09-19). Each root is recorded as it is made. A caller releases them the moment its
|
|
106
|
+
* publish is done, and an exit hook removes whatever is left, on success and on failure. A caller that
|
|
107
|
+
* can be stopped by a signal turns the signal into an exit, so the hook runs then too.
|
|
108
|
+
*/
|
|
109
|
+
const copies = new Set();
|
|
110
|
+
let exitHooked = false;
|
|
111
|
+
function tracked(root) {
|
|
112
|
+
copies.add(root);
|
|
113
|
+
if (!exitHooked) { exitHooked = true; process.once("exit", releaseDemoCopies); }
|
|
114
|
+
return root;
|
|
115
|
+
}
|
|
116
|
+
/** Remove every copy made so far. Safe to call more than once. */
|
|
117
|
+
export function releaseDemoCopies() {
|
|
118
|
+
for (const d of [...copies]) {
|
|
119
|
+
try { rmSync(d, { recursive: true, force: true }); } catch { /* going anyway; the exit hook tries again */ }
|
|
120
|
+
copies.delete(d);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
100
124
|
/**
|
|
101
125
|
* The directory a frozen demo should be PUBLISHED from — itself, or a copy when it is part of this tree.
|
|
102
126
|
*
|
|
@@ -117,7 +141,7 @@ export function publishSource(dir, { repoRoot, tmp = tmpdir() } = {}) {
|
|
|
117
141
|
const root = resolve(repoRoot ?? "");
|
|
118
142
|
const here = resolve(dir);
|
|
119
143
|
if (!root || !(here === root || here.startsWith(root + sep))) return dir;
|
|
120
|
-
const copy = join(mkdtempSync(join(tmp, "clearotron-demo-")), "sample");
|
|
144
|
+
const copy = join(tracked(mkdtempSync(join(tmp, "clearotron-demo-"))), "sample");
|
|
121
145
|
cpSync(here, copy, { recursive: true });
|
|
122
146
|
return copy;
|
|
123
147
|
}
|
|
@@ -135,7 +159,7 @@ export function publishContainer(root, { repoRoot, tmp = tmpdir() } = {}) {
|
|
|
135
159
|
const repo = resolve(repoRoot ?? "");
|
|
136
160
|
const here = resolve(root);
|
|
137
161
|
if (!repo || !(here === repo || here.startsWith(repo + sep))) return { dir: root, unusable: demoInventory(root).unusable };
|
|
138
|
-
const copy = join(mkdtempSync(join(tmp, "clearotron-demo-")), "sample");
|
|
162
|
+
const copy = join(tracked(mkdtempSync(join(tmp, "clearotron-demo-"))), "sample");
|
|
139
163
|
mkdirSync(copy, { recursive: true });
|
|
140
164
|
const { children, unusable } = demoInventory(here);
|
|
141
165
|
const left = [...unusable];
|
|
@@ -288,8 +288,8 @@ export function callsSoFar(dispositionsPath) {
|
|
|
288
288
|
export { PARK_AFTER_REFUSALS };
|
|
289
289
|
|
|
290
290
|
/**
|
|
291
|
-
* Which rows have been refused past the bound. PURE, and counted PER ROW ACROSS CALLS — the unit
|
|
292
|
-
* own banner records an earlier investigation dying on, when it joined per-row-final-state instead.
|
|
291
|
+
* Which rows have been refused past the bound. PURE, and counted PER ROW ACROSS CALLS — the unit this
|
|
292
|
+
* module's own banner records an earlier investigation dying on, when it joined per-row-final-state instead.
|
|
293
293
|
*
|
|
294
294
|
* A row that is ruled later is never re-parked, because the union only parks rows that are not ruled.
|
|
295
295
|
* @returns {string[]} row_ids, sorted, so the same ledger always yields the same answer.
|
|
@@ -145,7 +145,7 @@ Stages must name **abstract tiers**, not provider aliases. Per-engine maps:
|
|
|
145
145
|
| `sweep` | register-unit, case-law, skeptic, report-overview, report-card | `sonnet` | `$CLEAROTRON_OPENAI_MODEL_SWEEP` |
|
|
146
146
|
| `cheap` | saturation-probe | `haiku` | `$CLEAROTRON_OPENAI_MODEL_CHEAP` |
|
|
147
147
|
|
|
148
|
-
**AN UNHONOURED OVERRIDE IS AN ERROR, NOT A SUBSTITUTION** (
|
|
148
|
+
**AN UNHONOURED OVERRIDE IS AN ERROR, NOT A SUBSTITUTION** (2026-08-03). This
|
|
149
149
|
section used to declare two further tiers — `skeptic` → `google/gemini-3-flash-preview` and
|
|
150
150
|
`refutation` → `together/deepseek-ai/DeepSeek-V4-Pro` — each substituting an anthropic model on the
|
|
151
151
|
anthropic engine, "grade-moving, validated only in the paid A/B". The substitution never was validated
|
|
@@ -191,7 +191,7 @@ disarms the refusal and never the record.
|
|
|
191
191
|
| `max` | `max` | `xhigh` |
|
|
192
192
|
|
|
193
193
|
`off` used to map to `minimal` on codex and `low` on claude — a whole rung apart at the bottom, so a
|
|
194
|
-
cross-engine effort comparison at `off` was off by one
|
|
194
|
+
cross-engine effort comparison at `off` was off by one. `low` is the anthropic
|
|
195
195
|
floor, so codex came up to it and codex's `minimal` is deliberately unreachable from the driver's tier
|
|
196
196
|
vocabulary. `max` is the one sanctioned divergence: it means "this engine's top rung", and codex has no
|
|
197
197
|
`max`. `engine.anthropic.test.mjs` pins the two tables together and asserts that single exception.
|
|
@@ -200,7 +200,7 @@ vocabulary. `max` is the one sanctioned divergence: it means "this engine's top
|
|
|
200
200
|
(`assertEffectiveTier`), on the EFFECTIVE tier rather than the declared one: Haiku 4.5 rejects adaptive
|
|
201
201
|
thinking and the request bounces to sonnet, so the pairing measures sonnet and records haiku. Both ways
|
|
202
202
|
it can arise are runtime overrides that never touch the stage table (`CLEAROTRON_STAGE_THINKING`, an
|
|
203
|
-
`--experiment --model`), which is why the start-of-run scan alone could not see it
|
|
203
|
+
`--experiment --model`), which is why the start-of-run scan alone could not see it.
|
|
204
204
|
|
|
205
205
|
## 4. `claude -p` invocation (anthropic-agent)
|
|
206
206
|
|
|
@@ -212,7 +212,7 @@ const RECORDING = Object.freeze({
|
|
|
212
212
|
// SECOND — skeptic, same shape ( is the template). Its OWN key, so blind-frame's seat is never
|
|
213
213
|
// handed record_skeptic and skeptic is never handed record_blind_frame.
|
|
214
214
|
//
|
|
215
|
-
// skeptic's key carries a SECOND tool: search_run_artifacts, the sanctioned read surface (
|
|
215
|
+
// skeptic's key carries a SECOND tool: search_run_artifacts, the sanctioned read surface (the
|
|
216
216
|
// ratification hold, unlock path 1). A READ over the run's own tree, not retrieval — it dials nothing,
|
|
217
217
|
// writes nothing, and is bounded to CLEAROTRON_BAND_RUN_DIR by construction (skeptic-search.mjs). It
|
|
218
218
|
// replaces the artifact half of the Bash reads O3c measured; the skill-doc half was already the seeded
|
|
@@ -1132,7 +1132,7 @@ serve({
|
|
|
1132
1132
|
factors: { type: "array", minItems: 2, maxItems: 4, items: { type: "string" }, description: "2–4 one-line load-bearing observations behind the band." },
|
|
1133
1133
|
counterFactors: { type: "array", minItems: 1, maxItems: 3, items: { type: "string" }, description: "1–3 one-line statements of what holds this name at this band rather than the next, either way." },
|
|
1134
1134
|
mitigation: { type: "string", description: "May be \"\" when nothing would move the band — but SEND THE KEY, so a considered \"none\" is not confusable with an omission." },
|
|
1135
|
-
assessment: { type: "string", description: "The opening paragraph a reader of THIS MARK'S own report sees first: what the name is, what the landscape looks like, what drives the rating
|
|
1135
|
+
assessment: { type: "string", description: "The opening paragraph a reader of THIS MARK'S own report sees first: what the name is, what the landscape looks like, what drives the rating." },
|
|
1136
1136
|
contextFraming: { type: "string" },
|
|
1137
1137
|
registerEstimate: { type: "string" },
|
|
1138
1138
|
parodyNote: { type: ["string", "null"] },
|