clearotron 0.4.1-beta.0 → 0.4.1-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/THIRD-PARTY-NOTICES.md +1 -1
- package/bin/README.md +1 -1
- package/bin/clearotron.mjs +2 -0
- package/bin/mcp.mjs +80 -0
- package/bin/start.mjs +14 -1
- package/build-info.json +2 -2
- package/demo/README.md +1 -1
- package/docs/architecture/04-configuration-reference.md +0 -1
- package/docs/architecture/06-operations-runbook.md +4 -3
- package/docs/architecture/08-development-guide.md +3 -1
- package/driver/CHANGELOG.md +17 -0
- package/driver/citation-census.json +3 -3
- package/driver/compare.mjs +1 -1
- package/driver/contract-audit.mjs +6 -6
- package/driver/contract-dictation-registry.mjs +1 -1
- package/driver/contract-e3-backlog.mjs +17 -16
- package/driver/contract-vocabulary.mjs +138 -125
- package/driver/declination-call.mjs +5 -1
- package/driver/dev-portal.mjs +2 -1
- package/driver/engine/mcp/codex-config.mjs +7 -2
- package/driver/engine/mcp/gather-config.mjs +4 -0
- package/driver/engine/mcp/recording-server.mjs +1 -1
- package/driver/engine/mcp/supplemental.mjs +26 -1
- package/driver/engine/openai-agent.mjs +13 -3
- package/driver/findings-model.mjs +80 -13
- package/driver/flag-snapshot.mjs +2 -1
- package/driver/foreign-record-links.mjs +50 -0
- package/driver/frame-diff-model.mjs +1 -1
- package/driver/gateway.mjs +4 -4
- package/driver/jx.mjs +1 -1
- package/driver/knockout-review-record.mjs +55 -1
- package/driver/named-band.mjs +2 -0
- package/driver/owner-screen.mjs +7 -4
- package/driver/package.json +1 -1
- package/driver/pipeline-knockout.mjs +14 -12
- package/driver/pipeline.mjs +118 -20
- package/driver/portal-service.mjs +5 -4
- package/driver/products.mjs +1 -1
- package/driver/profiles.mjs +4 -3
- package/driver/publish/publish-inputs.mjs +2 -2
- package/driver/publish/xlsx.mjs +1 -1
- package/driver/register-count.mjs +2 -2
- package/driver/register-coverage.mjs +1 -1
- package/driver/register-plan.mjs +13 -2
- package/driver/result-noun-fields.mjs +3 -3
- package/driver/scope-rules.mjs +2 -2
- package/driver/stage-context.mjs +9 -0
- package/driver/stages-knockout.mjs +6 -5
- package/driver/stages.mjs +23 -23
- package/driver/suite-census.json +97 -31
- package/driver/synthesis-record.mjs +14 -5
- package/driver/verify.mjs +1 -1
- package/mcp-server/CHANGELOG.md +8 -0
- package/mcp-server/CONNECT.md +9 -3
- package/mcp-server/demo-mode.mjs +10 -0
- package/mcp-server/lib/runs.mjs +7 -1
- package/mcp-server/lib/scrub.mjs +1 -1
- package/mcp-server/package.json +1 -1
- package/mcp-server/packs/README.md +1 -1
- package/mcp-server/server.mjs +16 -2
- package/package.json +3 -2
- package/portal-ui/package.json +3 -3
- package/providers/_shared/count.mjs +5 -1
- package/providers/_shared/enumerate.mjs +66 -21
- package/providers/_shared/execute-plan.mjs +13 -4
- package/providers/oauth-mcp-bridge/CHANGELOG.md +8 -0
- package/providers/oauth-mcp-bridge/package.json +1 -1
- package/providers/signa/src/capabilities.js +15 -0
- package/providers/signa/src/core.js +55 -26
- package/scripts/e2e-first-time.mjs +3 -3
- package/scripts/env-audit.mjs +3 -2
- package/scripts/freeze-example-run.mjs +8 -8
- package/scripts/mcp-registry-listing.mjs +199 -0
- package/scripts/mint-plugin-folder.mjs +65 -0
- package/scripts/release-version.mjs +44 -0
- package/scripts/score.mjs +1 -1
- package/shared/register-floor.mjs +19 -0
- package/shared/trigger-lane.mjs +1 -1
- package/skills/clearotron-ops/SKILL.md +81 -24
package/driver/stages.mjs
CHANGED
|
@@ -1206,7 +1206,7 @@ export const VARIANT_CATEGORY_BRIEF =
|
|
|
1206
1206
|
// on an element a move was supposed to discharge is indistinguishable from a relabel.
|
|
1207
1207
|
//
|
|
1208
1208
|
// `tokens` lists the validator failure tokens that SPEAK ABOUT that element. PER STAGE, never global:
|
|
1209
|
-
// `too_short` and `missing` come from the shared nonEmpty()
|
|
1209
|
+
// `too_short` and `missing` come from the shared helpers nonEmpty() and needs() in verify.mjs, and are
|
|
1210
1210
|
// legitimately owned by DIFFERENT elements in matter-frame, clearance-variants and frame-diff. A global
|
|
1211
1211
|
// token→element map sees several owners for one token and "fixes" a partition that was never violated.
|
|
1212
1212
|
//
|
|
@@ -1287,7 +1287,7 @@ export const STAGES = {
|
|
|
1287
1287
|
},
|
|
1288
1288
|
"Applicant's own & affiliated marks — the self-exclusion set (mandatory)": {
|
|
1289
1289
|
class: "judgment", tokens: [],
|
|
1290
|
-
why: "naming affiliates beyond the seed is judgment; the profile half is already pre-bound —
|
|
1290
|
+
why: "naming affiliates beyond the seed is judgment; the profile half is already pre-bound — this stage's `message` hands the model exclusionSeed verbatim and _driver/instructed-scope.json carries job.customer",
|
|
1291
1291
|
},
|
|
1292
1292
|
"Campaign shape (stated) — the intake's campaign facts retyped from the `Stated campaign shape` line the dispatch already carries": {
|
|
1293
1293
|
class: "mechanical:code-rendered", tokens: [],
|
|
@@ -1436,7 +1436,7 @@ export const STAGES = {
|
|
|
1436
1436
|
},
|
|
1437
1437
|
"mark — \"<the mark verbatim>\"": {
|
|
1438
1438
|
class: "mechanical:pre-bound", tokens: ["variantmodel_mark_missing"],
|
|
1439
|
-
why: "_driver/instructed-scope.json.marks holds it and stage-context.mjs
|
|
1439
|
+
why: "_driver/instructed-scope.json.marks holds it and VALIDATOR_SIDECARS declared in stage-context.mjs binds that file to this stage. variantTermShapeGaps() in variant-manifest-model.mjs already concedes the field is not the model's: it is excluded from the term-shape gate because \"the stage is told to emit it VERBATIM, and it arrives from the job… a value this stage CANNOT restate\"",
|
|
1440
1440
|
},
|
|
1441
1441
|
"dominant_element — the distinctive anchor the sweep enumerates": {
|
|
1442
1442
|
class: "judgment", tokens: ["variantmodel_dominant_element_missing"],
|
|
@@ -1456,7 +1456,7 @@ export const STAGES = {
|
|
|
1456
1456
|
},
|
|
1457
1457
|
"variants[].value — the search terms themselves": {
|
|
1458
1458
|
class: "judgment", tokens: ["variantmodel_term_markup"],
|
|
1459
|
-
why: "the repo forbids code from minting a search term twice over — stages.mjs
|
|
1459
|
+
why: "the repo forbids code from minting a search term twice over — scriptFloorDirective() in stages.mjs and variantCompletenessGaps() in variant-manifest-model.mjs (\"VALIDATES, NEVER GENERATES… the moment code mints a search term, judgment has moved into the funnel\"). variantmodel_term_markup is therefore a shape rule that stays model-facing BY DESIGN; do not reclassify it mechanical to satisfy E6. It also walks dominant_element and elements[].value (variantTermShapeGaps), which is why they carry no token of their own",
|
|
1460
1460
|
},
|
|
1461
1461
|
"variants[].category — one of core|phonetic|visual|transliteration|numeric|composite|other": {
|
|
1462
1462
|
class: "judgment", tokens: [],
|
|
@@ -1472,7 +1472,7 @@ export const STAGES = {
|
|
|
1472
1472
|
},
|
|
1473
1473
|
"Family completeness — at minimum one core, one phonetic and one visual variant, plus a transliteration variant when the mark, the dominant element or any elements[] value is non-Latin": {
|
|
1474
1474
|
class: "judgment", tokens: ["variantmodel_family_incomplete", "variantmodel_variants_empty"],
|
|
1475
|
-
why: "structural completeness of the family the plan compiles from; code refuses but must never mint the missing member (variant-manifest-model.mjs
|
|
1475
|
+
why: "structural completeness of the family the plan compiles from; code refuses but must never mint the missing member (variantCompletenessGaps() in variant-manifest-model.mjs). variantmodel_family_incomplete carries THREE arms — category:<cat>, script:<term> and script-coverage:<script>:<territories> — and owns all three here, including the per-script arm declared below",
|
|
1476
1476
|
},
|
|
1477
1477
|
"Per-script coverage — at least one rendering of the mark in each script the in-scope territories register marks in, as a transliteration variant carrying its romanization": {
|
|
1478
1478
|
class: "judgment", tokens: [],
|
|
@@ -1516,7 +1516,7 @@ export const STAGES = {
|
|
|
1516
1516
|
},
|
|
1517
1517
|
"### Scope ledger rows — {Layer, Item, Status: applied|dropped, Reason, Reopen trigger} across variant / field / source / jurisdiction": {
|
|
1518
1518
|
class: "judgment", tokens: [],
|
|
1519
|
-
why: "defending an omission with the concrete observation that should reopen it is the whole judgment, and frame-diff diffs it against the blind re-derivation. The ROW SHAPE is mechanical — scope-ledger.mjs
|
|
1519
|
+
why: "defending an omission with the concrete observation that should reopen it is the whole judgment, and frame-diff diffs it against the blind re-derivation. The ROW SHAPE is mechanical — renderScopeLedgerJson() in scope-ledger.mjs parses the table into scope-ledger.json — and the jurisdiction rows are largely a re-carry of the matter frame's own Scope-jurisdictions line",
|
|
1520
1520
|
},
|
|
1521
1521
|
"Prose variant-table category token — translit-<script>, and for Chinese translit-zh-meaning vs translit-zh-phonetic": {
|
|
1522
1522
|
class: "judgment", tokens: [],
|
|
@@ -1531,7 +1531,7 @@ export const STAGES = {
|
|
|
1531
1531
|
},
|
|
1532
1532
|
"Per-jurisdiction sub-queries": {
|
|
1533
1533
|
class: "judgment", tokens: [],
|
|
1534
|
-
why: "a per-territory search decision no artifact holds — the dispatch names the deliverable and no file the model reads says what one looks like. coverage-ledger.mjs
|
|
1534
|
+
why: "a per-territory search decision no artifact holds — the dispatch names the deliverable and no file the model reads says what one looks like. normalizeAxis() in coverage-ledger.mjs shows a downstream consumer that expects them (\"the per-jurisdiction sub-query belongs to primary-sweep\")",
|
|
1535
1535
|
},
|
|
1536
1536
|
"Verify? ✅ column on every transliteration row of the prose Variants table": {
|
|
1537
1537
|
class: "mechanical:code-rendered", tokens: [],
|
|
@@ -1807,7 +1807,7 @@ export const STAGES = {
|
|
|
1807
1807
|
},
|
|
1808
1808
|
"PR / reputational section — the readings the meaning sweep surfaced, per form, each labelled benign or loaded": {
|
|
1809
1809
|
class: "judgment", tokens: ["connotation_search_missing"],
|
|
1810
|
-
why: "The semantic read of a surfaced passage is the model's. `connotation_search_missing` (verify.mjs
|
|
1810
|
+
why: "The semantic read of a surfaced passage is the model's. `connotation_search_missing` (commonLawEvidence() in verify.mjs) fires when the ledger recorded no meaning query at all.",
|
|
1811
1811
|
},
|
|
1812
1812
|
"`Connotation-search source: <URL | \"perplexity_research — no result\">` line on a clean PR row": {
|
|
1813
1813
|
class: "mechanical:code-extracted", tokens: ["connotation_search_missing"],
|
|
@@ -1970,7 +1970,7 @@ export const STAGES = {
|
|
|
1970
1970
|
},
|
|
1971
1971
|
"disposition form `note` — one line saying what the receipt says and why it reads that way": {
|
|
1972
1972
|
class: "judgment", tokens: ["connotation_no_ruling"],
|
|
1973
|
-
why: "#850 keeps it. The empty-note state lands in the `no_ruling` residual (connotation-search.mjs
|
|
1973
|
+
why: "#850 keeps it. The empty-note state lands in the `no_ruling` residual (findConnotationViolations() in connotation-search.mjs).",
|
|
1974
1974
|
},
|
|
1975
1975
|
"disposition form `receipt_index` — the 1-based POSITION of the candidate you ruled on, in that row's own list": {
|
|
1976
1976
|
class: "mechanical:pre-bound", tokens: ["connotation_form_damaged", "connotation_cite_absent"],
|
|
@@ -2102,7 +2102,7 @@ export const STAGES = {
|
|
|
2102
2102
|
contractElements: {
|
|
2103
2103
|
"execute the frozen plan — ONE register_execute_plan call with {plan_path, axis, output_path}": {
|
|
2104
2104
|
class: "mechanical:tool-written", tokens: ["named_band_missing", "tool_timeout"],
|
|
2105
|
-
why: "All three args are driver values interpolated into the message; the tool writes every band block. #850 calls this already right. Note #793: `named_band_missing` and `tool_timeout` are one evidence state with two causes, and registerPlanCallKilled
|
|
2105
|
+
why: "All three args are driver values interpolated into the message; the tool writes every band block. #850 calls this already right. Note #793: `named_band_missing` and `tool_timeout` are one evidence state with two causes, and registerPlanCallKilled() in tool-calls.mjs separates them from the call log, not from the model.",
|
|
2106
2106
|
},
|
|
2107
2107
|
"the dictated entry list — qid, predicate, terms, owner, nice_classes, regions, when-guard, expected_kind, covered_by": {
|
|
2108
2108
|
class: "mechanical:pre-bound", tokens: [],
|
|
@@ -2126,11 +2126,11 @@ export const STAGES = {
|
|
|
2126
2126
|
},
|
|
2127
2127
|
"named-band block envelope — {state: enumerated|incomplete, query, total_hits, records|fetched+sample+reason}": {
|
|
2128
2128
|
class: "mechanical:tool-written", tokens: ["named_band_unparseable", "named_band_block_invalid", "named_band_state_invalid", "band_block_unplanned", "named_band_invalid"],
|
|
2129
|
-
why: "#850: M (envelope), tool-written blocks. `band_block_unplanned` (verify.mjs
|
|
2129
|
+
why: "#850: M (envelope), tool-written blocks. `band_block_unplanned` (validators.registerUnit in verify.mjs) is the backstop that kills a hand-authored qid-less block — a token that exists only because the legacy lane still offers the duty in the same message.",
|
|
2130
2130
|
},
|
|
2131
2131
|
"enumerated block records carried verbatim — record_id, mark_text, classes, status, owner_name, owner_country, application_date, registration_date, expiry_date, jurisdictions, screen_verdict": {
|
|
2132
2132
|
class: "mechanical:tool-written", tokens: ["named_band_collapsed"],
|
|
2133
|
-
why: "register_enumerate already returns each record batch-screened; carrying it is transcription. `named_band_collapsed` (verify.mjs
|
|
2133
|
+
why: "register_enumerate already returns each record batch-screened; carrying it is transcription. `named_band_collapsed` (validators.registerUnit in verify.mjs, findCollapsedBands) is exactly the recall loss that transcription produces — a slice claiming total_hits with zero records reaching the band.",
|
|
2134
2134
|
},
|
|
2135
2135
|
"per-axis prose digest — the SHORT AUDIT NOTE at register-units/<axis>.md": {
|
|
2136
2136
|
class: "judgment", tokens: ["too_short"],
|
|
@@ -2142,7 +2142,7 @@ export const STAGES = {
|
|
|
2142
2142
|
},
|
|
2143
2143
|
"axis applicability — decide the axis has no work in this manifest and write a one-line \"not applicable\" band block": {
|
|
2144
2144
|
class: "judgment", tokens: ["band_block_unplanned"],
|
|
2145
|
-
why: "The applicability call is the model's; the block is not. Under the supplemental lane a seat obeying unit.md
|
|
2145
|
+
why: "The applicability call is the model's; the block is not. Under the supplemental lane a seat obeying unit.md's \"not applicable\" rule ('write a single block … so the file always lands') writes exactly the qid-less block validators.registerUnit in verify.mjs kills. The skill file and the stage message contradict each other on the one path the skill offers for an empty axis.",
|
|
2146
2146
|
},
|
|
2147
2147
|
"reading the band back and judging it — keep proposing until the axis's dangerous named band is covered": {
|
|
2148
2148
|
class: "judgment", tokens: [],
|
|
@@ -2150,7 +2150,7 @@ export const STAGES = {
|
|
|
2150
2150
|
},
|
|
2151
2151
|
"layer-execution declaration — whether the prose says the register layer / provider tools were not executed or not bound": {
|
|
2152
2152
|
class: "mechanical:code-extracted", tokens: ["declared_not_executed"],
|
|
2153
|
-
why: "_driver/plan-execution.json and the tool-call log already hold whether the call ran — registerPlanCallKilled
|
|
2153
|
+
why: "_driver/plan-execution.json and the tool-call log already hold whether the call ran — registerPlanCallKilled() in tool-calls.mjs reads exactly that to settle the same question one arm below. This arm still decides it from the model's sentence.",
|
|
2154
2154
|
},
|
|
2155
2155
|
"`CROSS-CHECK REQUIRED: <what> — <why>` — the check that is needed and why": {
|
|
2156
2156
|
class: "judgment", tokens: [],
|
|
@@ -2364,7 +2364,7 @@ export const STAGES = {
|
|
|
2364
2364
|
},
|
|
2365
2365
|
"reason — the short paragraph carrying the stated ground for the tier (owner characterisation, customer/channel read, decisive ground, Stage-2 mitigant)": {
|
|
2366
2366
|
class: "judgment", tokens: ["placement_reason_missing", "placement_reason_bare"],
|
|
2367
|
-
why: "Four downstream stages adopt or counter-reason BY ARGUING WITH THIS TEXT (
|
|
2367
|
+
why: "Four downstream stages adopt or counter-reason BY ARGUING WITH THIS TEXT (the B2 comment in this stage's `message` says so). It is authored reasoning, not a value any artifact holds.",
|
|
2368
2368
|
},
|
|
2369
2369
|
"borderline: true — the declaration that the promotion question could be argued either way on this record": {
|
|
2370
2370
|
class: "judgment", tokens: ["placement_borderline_invalid"],
|
|
@@ -2372,7 +2372,7 @@ export const STAGES = {
|
|
|
2372
2372
|
},
|
|
2373
2373
|
"select — one record URI of the register candidate being placed": {
|
|
2374
2374
|
class: "mechanical:code-extracted", tokens: [],
|
|
2375
|
-
why: "buildSelectionIndex() in placement-form.mjs already holds every selectable record, built from _driver/register-positions.json plus the band shape's floors, and resolves any URI of a family to the canonical row. #850 M1: the model should return the 1-based index into that driver-written list; code resolves index→id. WHICH candidate to place stays judgment — the row existing at all is the judgment; only the pointing token is mechanical. NO VALIDATOR TOKEN speaks about it: an unresolved select is recorded on the form as `unresolved[]` (placement-union.mjs
|
|
2375
|
+
why: "buildSelectionIndex() in placement-form.mjs already holds every selectable record, built from _driver/register-positions.json plus the band shape's floors, and resolves any URI of a family to the canonical row. #850 M1: the model should return the 1-based index into that driver-written list; code resolves index→id. WHICH candidate to place stays judgment — the row existing at all is the judgment; only the pointing token is mechanical. NO VALIDATOR TOKEN speaks about it: an unresolved select is recorded on the form as `unresolved[]` (pushSelection() in placement-union.mjs) and handed back in the next dispatch, never a fail.",
|
|
2376
2376
|
},
|
|
2377
2377
|
"seat rows for candidates the register does not hold — mark / owner / jurisdiction / records: [] written in full": {
|
|
2378
2378
|
class: "judgment", tokens: ["placement_mark_missing", "placement_owner_missing", "placement_jurisdiction_invalid", "placement_records_invalid"],
|
|
@@ -2404,7 +2404,7 @@ export const STAGES = {
|
|
|
2404
2404
|
},
|
|
2405
2405
|
"retract: <row_id> — withdrawing a seat row already on the form": {
|
|
2406
2406
|
class: "judgment", tokens: [],
|
|
2407
|
-
why: "Whether a placed candidate should come off is a call only the model makes. The row_id it names is driver-assigned (shortId 'PS'/'PR', placement-form.mjs
|
|
2407
|
+
why: "Whether a placed candidate should come off is a call only the model makes. The row_id it names is driver-assigned (shortId 'PS'/'PR', in seatRows() and buildSelectionIndex() in placement-form.mjs), so the HANDLE is code-assigned even though the act is judgment.",
|
|
2408
2408
|
},
|
|
2409
2409
|
"return payload — the absolute output path plus a 2-3 line summary": {
|
|
2410
2410
|
class: "mechanical:pre-bound", tokens: [],
|
|
@@ -2490,7 +2490,7 @@ export const STAGES = {
|
|
|
2490
2490
|
},
|
|
2491
2491
|
"seat-added coverage rows — the decision to add one, and the axis it is filed under (expressed in the `unit` label)": {
|
|
2492
2492
|
class: "judgment", tokens: ["coverage_form_axis_invalid"],
|
|
2493
|
-
why: "The shipped code rules it judgment in its own words: 'THE AXIS IS PART OF THE JUDGMENT, and on a SEAT row it is the one identifier the seat still supplies' and normalizeAxis 'repair[s] formatting, never invent[s] an axis' (coverage-form.mjs
|
|
2493
|
+
why: "The shipped code rules it judgment in its own words: 'THE AXIS IS PART OF THE JUDGMENT, and on a SEAT row it is the one identifier the seat still supplies' and normalizeAxis 'repair[s] formatting, never invent[s] an axis' (rowIsSettled() in coverage-form.mjs). The driver cannot know which axis a coverage unit it never planned belongs under.",
|
|
2494
2494
|
},
|
|
2495
2495
|
"the seat row's duplicate `axis` cell (the same token already typed as the leading segment of `unit`)": {
|
|
2496
2496
|
class: "mechanical:code-extracted", tokens: ["coverage_form_axis_invalid"],
|
|
@@ -2703,11 +2703,11 @@ export const STAGES = {
|
|
|
2703
2703
|
},
|
|
2704
2704
|
"the escalation decision — which register axes carry a material, unresolved, genuinely closeable gap, and the one-line reason for each": {
|
|
2705
2705
|
class: "judgment", tokens: [],
|
|
2706
|
-
why: "Whether a documented coverage-limited row, a capability-gap deferral or a fresh concern on a confirmed-clean row warrants spending a re-run. The driver hands the coverage/execution truth in as a computed table (
|
|
2706
|
+
why: "Whether a documented coverage-limited row, a capability-gap deferral or a fresh concern on a confirmed-clean row warrants spending a re-run. The driver hands the coverage/execution truth in as a computed table (skepticDeferralExtra() in pipeline.mjs) precisely so this is a call over data rather than a re-derivation — but the call itself is nobody else's.",
|
|
2707
2707
|
},
|
|
2708
2708
|
"escalation decisions — one {axis, reason} per axis that must be re-run, sent through record_skeptic": {
|
|
2709
2709
|
class: "mechanical:code-rendered", tokens: [],
|
|
2710
|
-
why: "#850 rules the line shape M: typed rows, code renders. The axis is one of the closed list the driver wrote into the same message (`Valid axes: ${axes}
|
|
2710
|
+
why: "#850 rules the line shape M: typed rows, code renders. The axis is one of the closed list the driver wrote into the same message (`Valid axes: ${axes}`), and the parse in escalatedAxes() in skeptic-record.mjs recognises only /ESCALATE:\\s*<axis>\\b/i per known axis — the em-dash, the reason, the section title and the literal 'none' are parsed by nothing. NO TOKEN: skepticFlags never inspects these lines, so a malformed ESCALATE line is a silent no-escalation, not a failure.",
|
|
2711
2711
|
},
|
|
2712
2712
|
"the verbatim ESCALATE string dictated for a `translit-too-generic` unit digest": {
|
|
2713
2713
|
class: "mechanical:code-rendered", tokens: [],
|
|
@@ -2715,7 +2715,7 @@ export const STAGES = {
|
|
|
2715
2715
|
},
|
|
2716
2716
|
"the `risk: <category>` field inside that dictated ESCALATE line": {
|
|
2717
2717
|
class: "mechanical:code-rendered", tokens: [],
|
|
2718
|
-
why: "IT HAS NO CONSUMER AT ALL. stages.mjs
|
|
2718
|
+
why: "IT HAS NO CONSUMER AT ALL. The D3 note in stages.mjs (\"the escalation-risk SHADOW apparatus … is DELETED\") records that the risk-category filter was deleted, and pipeline.mjs states 'spec-48 D3 — the escalation-risk SHADOW loop (risk-tag parse + would-skip telemetry for the never-enabled CLEAROTRON_ESCALATION_FILTER) is DELETED' at the parse site (envelopeDecision() in pipeline.mjs). The doc block at envelopeDecision() in pipeline.mjs that describes reading the field is a stale header left standing over envelopeDecision — the function it documented is gone. Classed code-rendered because it is not judgment; the correct move is deletion from the skill file.",
|
|
2719
2719
|
},
|
|
2720
2720
|
"return payload — a 2-3 line summary; the audit itself rides record_skeptic": {
|
|
2721
2721
|
class: "mechanical:tool-written", tokens: ["skeptic_"],
|
|
@@ -3707,7 +3707,7 @@ export const STAGES = {
|
|
|
3707
3707
|
},
|
|
3708
3708
|
"actions.checks_we_ran[].source_link (the `([source](<url>))` URL in each bullet)": {
|
|
3709
3709
|
class: "mechanical:code-rendered", tokens: [],
|
|
3710
|
-
why: "A URL the run already fetched, retyped by hand: the same 127-URI transcription class #850 rules M for synthesis. findings.json carries the typed source.resolved_link (findings-model.mjs
|
|
3710
|
+
why: "A URL the run already fetched, retyped by hand: the same 127-URI transcription class #850 rules M for synthesis. findings.json carries the typed source.resolved_link (validateSource() in findings-model.mjs, fullDetail() in render.mjs) and the coverage rows carry theirs; code can render the link once the model names the check.",
|
|
3711
3711
|
},
|
|
3712
3712
|
// RETIRED BY CONVERSION 4 — `actions.only_you_can_close_these[]`. buildOnlyYouSection already
|
|
3713
3713
|
// replaced any authored section wholesale, so this row described an ask the driver overwrote. The
|
|
@@ -3724,7 +3724,7 @@ export const STAGES = {
|
|
|
3724
3724
|
},
|
|
3725
3725
|
"lint_contracts.withdrawn_findings_excluded (a withdrawn finding 'DOES NOT EXIST for this report')": {
|
|
3726
3726
|
class: "mechanical:pre-bound", tokens: [],
|
|
3727
|
-
why: "`withdrawn` is a typed disposition (findings-model.mjs
|
|
3727
|
+
why: "`withdrawn` is a typed disposition (DISPOSITIONS declared in findings-model.mjs) and fullProseOrdinals already filters it (fullProseOrdinals in pipeline.mjs). The driver can hand a filtered findings view instead of handing the whole file plus a prohibition.",
|
|
3728
3728
|
},
|
|
3729
3729
|
// RETIRED BY CONVERSION 4 — the `::p::` MARKER. Which note is internal is still the model's call
|
|
3730
3730
|
// and rides `internal: true` on the entry; the marker itself is a rendering instruction the driver
|
package/driver/suite-census.json
CHANGED
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
"todos": 0
|
|
53
53
|
},
|
|
54
54
|
"a-batch-of-names-is-one-question-per-name-without-or.test.mjs": {
|
|
55
|
-
"tests":
|
|
56
|
-
"asserts":
|
|
55
|
+
"tests": 6,
|
|
56
|
+
"asserts": 28,
|
|
57
57
|
"skips": 0,
|
|
58
58
|
"todos": 0
|
|
59
59
|
},
|
|
@@ -195,9 +195,15 @@
|
|
|
195
195
|
"skips": 0,
|
|
196
196
|
"todos": 0
|
|
197
197
|
},
|
|
198
|
+
"a-clean-knockout-hands-the-reviewer-its-first-read-lines.test.mjs": {
|
|
199
|
+
"tests": 6,
|
|
200
|
+
"asserts": 25,
|
|
201
|
+
"skips": 0,
|
|
202
|
+
"todos": 0
|
|
203
|
+
},
|
|
198
204
|
"a-client-cell-carries-no-raw-engine-words.test.mjs": {
|
|
199
|
-
"tests":
|
|
200
|
-
"asserts":
|
|
205
|
+
"tests": 5,
|
|
206
|
+
"asserts": 18,
|
|
201
207
|
"skips": 0,
|
|
202
208
|
"todos": 0
|
|
203
209
|
},
|
|
@@ -532,8 +538,8 @@
|
|
|
532
538
|
"todos": 0
|
|
533
539
|
},
|
|
534
540
|
"a-failed-run-resumes-from-the-command-line.test.mjs": {
|
|
535
|
-
"tests":
|
|
536
|
-
"asserts":
|
|
541
|
+
"tests": 4,
|
|
542
|
+
"asserts": 14,
|
|
537
543
|
"skips": 0,
|
|
538
544
|
"todos": 0
|
|
539
545
|
},
|
|
@@ -579,6 +585,12 @@
|
|
|
579
585
|
"skips": 0,
|
|
580
586
|
"todos": 0
|
|
581
587
|
},
|
|
588
|
+
"a-foreign-record-link-is-named-once-and-blanked-at-salvage.test.mjs": {
|
|
589
|
+
"tests": 8,
|
|
590
|
+
"asserts": 31,
|
|
591
|
+
"skips": 0,
|
|
592
|
+
"todos": 0
|
|
593
|
+
},
|
|
582
594
|
"a-frame-call-with-places-per-name-passes-the-gate.test.mjs": {
|
|
583
595
|
"tests": 2,
|
|
584
596
|
"asserts": 7,
|
|
@@ -664,8 +676,8 @@
|
|
|
664
676
|
"todos": 0
|
|
665
677
|
},
|
|
666
678
|
"a-job-on-the-older-goods-spelling-scopes-the-same.test.mjs": {
|
|
667
|
-
"tests":
|
|
668
|
-
"asserts":
|
|
679
|
+
"tests": 11,
|
|
680
|
+
"asserts": 28,
|
|
669
681
|
"skips": 0,
|
|
670
682
|
"todos": 0
|
|
671
683
|
},
|
|
@@ -765,6 +777,12 @@
|
|
|
765
777
|
"skips": 0,
|
|
766
778
|
"todos": 0
|
|
767
779
|
},
|
|
780
|
+
"a-late-synthesis-save-keeps-the-seams-writes.test.mjs": {
|
|
781
|
+
"tests": 2,
|
|
782
|
+
"asserts": 16,
|
|
783
|
+
"skips": 0,
|
|
784
|
+
"todos": 0
|
|
785
|
+
},
|
|
768
786
|
"a-link-in-the-workbook-is-not-banned-vocabulary.test.mjs": {
|
|
769
787
|
"tests": 2,
|
|
770
788
|
"asserts": 5,
|
|
@@ -1173,6 +1191,12 @@
|
|
|
1173
1191
|
"skips": 0,
|
|
1174
1192
|
"todos": 0
|
|
1175
1193
|
},
|
|
1194
|
+
"a-register-floor-is-carried-and-never-a-zero.test.mjs": {
|
|
1195
|
+
"tests": 7,
|
|
1196
|
+
"asserts": 19,
|
|
1197
|
+
"skips": 0,
|
|
1198
|
+
"todos": 0
|
|
1199
|
+
},
|
|
1176
1200
|
"a-register-manual-states-what-its-provider-declares.test.mjs": {
|
|
1177
1201
|
"tests": 6,
|
|
1178
1202
|
"asserts": 13,
|
|
@@ -1314,7 +1338,7 @@
|
|
|
1314
1338
|
"a-screenshot-of-an-error-page-is-not-a-report.test.mjs": {
|
|
1315
1339
|
"tests": 21,
|
|
1316
1340
|
"asserts": 55,
|
|
1317
|
-
"skips":
|
|
1341
|
+
"skips": 5,
|
|
1318
1342
|
"todos": 0
|
|
1319
1343
|
},
|
|
1320
1344
|
"a-script-is-asked-once-per-market-that-files-in-it.test.mjs": {
|
|
@@ -1360,8 +1384,8 @@
|
|
|
1360
1384
|
"todos": 0
|
|
1361
1385
|
},
|
|
1362
1386
|
"a-session-the-classifier-cut-is-not-recorded-as-clean.test.mjs": {
|
|
1363
|
-
"tests":
|
|
1364
|
-
"asserts":
|
|
1387
|
+
"tests": 13,
|
|
1388
|
+
"asserts": 80,
|
|
1365
1389
|
"skips": 0,
|
|
1366
1390
|
"todos": 0
|
|
1367
1391
|
},
|
|
@@ -1419,6 +1443,12 @@
|
|
|
1419
1443
|
"skips": 0,
|
|
1420
1444
|
"todos": 0
|
|
1421
1445
|
},
|
|
1446
|
+
"a-stable-cut-moves-the-plugin-pin.test.mjs": {
|
|
1447
|
+
"tests": 4,
|
|
1448
|
+
"asserts": 13,
|
|
1449
|
+
"skips": 0,
|
|
1450
|
+
"todos": 0
|
|
1451
|
+
},
|
|
1422
1452
|
"a-stable-is-published-only-over-a-clean-code-scan.test.mjs": {
|
|
1423
1453
|
"tests": 9,
|
|
1424
1454
|
"asserts": 19,
|
|
@@ -1829,7 +1859,7 @@
|
|
|
1829
1859
|
},
|
|
1830
1860
|
"an-exact-spelling-band-stacks-at-the-register-s-exact-width.test.mjs": {
|
|
1831
1861
|
"tests": 3,
|
|
1832
|
-
"asserts":
|
|
1862
|
+
"asserts": 11,
|
|
1833
1863
|
"skips": 0,
|
|
1834
1864
|
"todos": 0
|
|
1835
1865
|
},
|
|
@@ -2068,8 +2098,8 @@
|
|
|
2068
2098
|
"todos": 0
|
|
2069
2099
|
},
|
|
2070
2100
|
"both-doors-start-on-both-paths.test.mjs": {
|
|
2071
|
-
"tests":
|
|
2072
|
-
"asserts":
|
|
2101
|
+
"tests": 27,
|
|
2102
|
+
"asserts": 64,
|
|
2073
2103
|
"skips": 0,
|
|
2074
2104
|
"todos": 0
|
|
2075
2105
|
},
|
|
@@ -2130,7 +2160,7 @@
|
|
|
2130
2160
|
"case-law-credential-state.test.mjs": {
|
|
2131
2161
|
"tests": 8,
|
|
2132
2162
|
"asserts": 26,
|
|
2133
|
-
"skips":
|
|
2163
|
+
"skips": 1,
|
|
2134
2164
|
"todos": 0
|
|
2135
2165
|
},
|
|
2136
2166
|
"case-law-join.test.mjs": {
|
|
@@ -2519,7 +2549,7 @@
|
|
|
2519
2549
|
},
|
|
2520
2550
|
"coverage-judgment-rows.test.mjs": {
|
|
2521
2551
|
"tests": 9,
|
|
2522
|
-
"asserts":
|
|
2552
|
+
"asserts": 45,
|
|
2523
2553
|
"skips": 0,
|
|
2524
2554
|
"todos": 0
|
|
2525
2555
|
},
|
|
@@ -2578,8 +2608,8 @@
|
|
|
2578
2608
|
"todos": 0
|
|
2579
2609
|
},
|
|
2580
2610
|
"declination-is-stated-not-inferred.test.mjs": {
|
|
2581
|
-
"tests":
|
|
2582
|
-
"asserts":
|
|
2611
|
+
"tests": 25,
|
|
2612
|
+
"asserts": 73,
|
|
2583
2613
|
"skips": 0,
|
|
2584
2614
|
"todos": 0
|
|
2585
2615
|
},
|
|
@@ -2991,6 +3021,12 @@
|
|
|
2991
3021
|
"skips": 0,
|
|
2992
3022
|
"todos": 0
|
|
2993
3023
|
},
|
|
3024
|
+
"each-stable-npm-serves-is-listed-in-the-mcp-registry.test.mjs": {
|
|
3025
|
+
"tests": 11,
|
|
3026
|
+
"asserts": 61,
|
|
3027
|
+
"skips": 0,
|
|
3028
|
+
"todos": 0
|
|
3029
|
+
},
|
|
2994
3030
|
"effective-scope.test.mjs": {
|
|
2995
3031
|
"tests": 15,
|
|
2996
3032
|
"asserts": 44,
|
|
@@ -3250,8 +3286,8 @@
|
|
|
3250
3286
|
"todos": 0
|
|
3251
3287
|
},
|
|
3252
3288
|
"experiment-context.test.mjs": {
|
|
3253
|
-
"tests":
|
|
3254
|
-
"asserts":
|
|
3289
|
+
"tests": 26,
|
|
3290
|
+
"asserts": 86,
|
|
3255
3291
|
"skips": 0,
|
|
3256
3292
|
"todos": 0
|
|
3257
3293
|
},
|
|
@@ -3808,8 +3844,8 @@
|
|
|
3808
3844
|
"todos": 0
|
|
3809
3845
|
},
|
|
3810
3846
|
"no-stage-is-offered-a-command-tool.test.mjs": {
|
|
3811
|
-
"tests":
|
|
3812
|
-
"asserts":
|
|
3847
|
+
"tests": 7,
|
|
3848
|
+
"asserts": 19,
|
|
3813
3849
|
"skips": 0,
|
|
3814
3850
|
"todos": 0
|
|
3815
3851
|
},
|
|
@@ -4162,8 +4198,8 @@
|
|
|
4162
4198
|
"todos": 0
|
|
4163
4199
|
},
|
|
4164
4200
|
"portal-service.test.mjs": {
|
|
4165
|
-
"tests":
|
|
4166
|
-
"asserts":
|
|
4201
|
+
"tests": 133,
|
|
4202
|
+
"asserts": 718,
|
|
4167
4203
|
"skips": 1,
|
|
4168
4204
|
"todos": 0
|
|
4169
4205
|
},
|
|
@@ -4614,7 +4650,7 @@
|
|
|
4614
4650
|
"register-record-log-run-scoped.test.mjs": {
|
|
4615
4651
|
"tests": 9,
|
|
4616
4652
|
"asserts": 21,
|
|
4617
|
-
"skips":
|
|
4653
|
+
"skips": 1,
|
|
4618
4654
|
"todos": 0
|
|
4619
4655
|
},
|
|
4620
4656
|
"register-review-fixes.test.mjs": {
|
|
@@ -4661,7 +4697,7 @@
|
|
|
4661
4697
|
},
|
|
4662
4698
|
"release-pipeline.test.mjs": {
|
|
4663
4699
|
"tests": 124,
|
|
4664
|
-
"asserts":
|
|
4700
|
+
"asserts": 480,
|
|
4665
4701
|
"skips": 2,
|
|
4666
4702
|
"todos": 0
|
|
4667
4703
|
},
|
|
@@ -5410,8 +5446,8 @@
|
|
|
5410
5446
|
"todos": 0
|
|
5411
5447
|
},
|
|
5412
5448
|
"synthesis-structural-input.test.mjs": {
|
|
5413
|
-
"tests":
|
|
5414
|
-
"asserts":
|
|
5449
|
+
"tests": 11,
|
|
5450
|
+
"asserts": 69,
|
|
5415
5451
|
"skips": 0,
|
|
5416
5452
|
"todos": 0
|
|
5417
5453
|
},
|
|
@@ -7166,6 +7202,30 @@
|
|
|
7166
7202
|
"skips": 0,
|
|
7167
7203
|
"todos": 0
|
|
7168
7204
|
},
|
|
7205
|
+
"the-handshake-reports-the-package-version.test.mjs": {
|
|
7206
|
+
"tests": 1,
|
|
7207
|
+
"asserts": 3,
|
|
7208
|
+
"skips": 0,
|
|
7209
|
+
"todos": 0
|
|
7210
|
+
},
|
|
7211
|
+
"the-package-starts-the-mcp-server.test.mjs": {
|
|
7212
|
+
"tests": 6,
|
|
7213
|
+
"asserts": 22,
|
|
7214
|
+
"skips": 0,
|
|
7215
|
+
"todos": 0
|
|
7216
|
+
},
|
|
7217
|
+
"the-plugin-folder-is-what-the-directory-installs.test.mjs": {
|
|
7218
|
+
"tests": 3,
|
|
7219
|
+
"asserts": 18,
|
|
7220
|
+
"skips": 0,
|
|
7221
|
+
"todos": 0
|
|
7222
|
+
},
|
|
7223
|
+
"the-plugin-starts-npx-through-the-shell-on-windows.test.mjs": {
|
|
7224
|
+
"tests": 8,
|
|
7225
|
+
"asserts": 24,
|
|
7226
|
+
"skips": 1,
|
|
7227
|
+
"todos": 0
|
|
7228
|
+
},
|
|
7169
7229
|
"the-portal-can-tell-who-has-connected-an-assistant.test.mjs": {
|
|
7170
7230
|
"tests": 12,
|
|
7171
7231
|
"asserts": 35,
|
|
@@ -7661,6 +7721,12 @@
|
|
|
7661
7721
|
"skips": 0,
|
|
7662
7722
|
"todos": 0
|
|
7663
7723
|
},
|
|
7724
|
+
"providers/_shared/test/a-register-floor-is-too-many-to-read.test.mjs": {
|
|
7725
|
+
"tests": 8,
|
|
7726
|
+
"asserts": 47,
|
|
7727
|
+
"skips": 0,
|
|
7728
|
+
"todos": 0
|
|
7729
|
+
},
|
|
7664
7730
|
"providers/_shared/test/a-slow-question-is-asked-again-in-region-halves.test.mjs": {
|
|
7665
7731
|
"tests": 9,
|
|
7666
7732
|
"asserts": 38,
|
|
@@ -7723,7 +7789,7 @@
|
|
|
7723
7789
|
},
|
|
7724
7790
|
"providers/_shared/test/owner-count-verification.test.mjs": {
|
|
7725
7791
|
"tests": 13,
|
|
7726
|
-
"asserts":
|
|
7792
|
+
"asserts": 52,
|
|
7727
7793
|
"skips": 0,
|
|
7728
7794
|
"todos": 0
|
|
7729
7795
|
},
|
|
@@ -7884,8 +7950,8 @@
|
|
|
7884
7950
|
"todos": 0
|
|
7885
7951
|
},
|
|
7886
7952
|
"providers/signa/test/exact-spellings-go-as-one-ranked-list.test.mjs": {
|
|
7887
|
-
"tests":
|
|
7888
|
-
"asserts":
|
|
7953
|
+
"tests": 11,
|
|
7954
|
+
"asserts": 39,
|
|
7889
7955
|
"skips": 0,
|
|
7890
7956
|
"todos": 0
|
|
7891
7957
|
},
|
|
@@ -53,7 +53,7 @@ import { declinationCallPaths, readDeclinations } from "./declination-tool.mjs";
|
|
|
53
53
|
import { reconcileDeclinationDuty, declinationDutyRefusal } from "./declination-duty.mjs";
|
|
54
54
|
import { findingUris } from "./record-carry.mjs"; // one derivation of "which records did the findings name", called not copied
|
|
55
55
|
import { foldAfterSave } from "./record-fold.mjs"; // once the delivery seam is passed, the saved record is folded again
|
|
56
|
-
|
|
56
|
+
import { recordOriginsOr, blankOnRepeat, recordBlanking, FOREIGN_HOST_TOKEN } from "./foreign-record-links.mjs"; // a foreign record link: refused once, then blanked
|
|
57
57
|
export const NARRATIVE_FILE = "narrative.md";
|
|
58
58
|
export const FINDINGS_FILE = "findings.json";
|
|
59
59
|
|
|
@@ -269,7 +269,7 @@ export function withoutWithheldRows(rows, ledger) {
|
|
|
269
269
|
return (Array.isArray(rows) ? rows : []).filter((r) => !namesIn(r?.area).some((n) => withheld.has(n)));
|
|
270
270
|
}
|
|
271
271
|
|
|
272
|
-
export function acceptSynthesis(params, { asks = [], ledger = null, manifest = null, method = undefined, methodInvalid = null, owed = null, declined = null } = {}) {
|
|
272
|
+
export function acceptSynthesis(params, { asks = [], ledger = null, manifest = null, method = undefined, methodInvalid = null, owed = null, declined = null, recordOrigins = null } = {}) {
|
|
273
273
|
const doc = params?.findings;
|
|
274
274
|
if (!doc || typeof doc !== "object" || Array.isArray(doc)) {
|
|
275
275
|
return { ok: false, reason: "synthesis_findings_missing: `findings` must be the findings document object { schema_version, rated_under_framework, findings, coverage, … } — this is the record the report and the workbook are built from, and there is no path that renders without it" };
|
|
@@ -383,7 +383,7 @@ export function acceptSynthesis(params, { asks = [], ledger = null, manifest = n
|
|
|
383
383
|
// own file gone wrong, and the seat cannot fix it — so it is refused by name, never read as "no method".
|
|
384
384
|
if (methodInvalid) return { ok: false, reason: `framework_method_unreadable: _driver/${FROZEN_METHOD_FILE} does not read back (${String(methodInvalid).slice(0, 160)}) — a driver fault, not the writer's` };
|
|
385
385
|
let parsedDoc;
|
|
386
|
-
try { parsedDoc = parseFindingsJson(findings, manifest ? { manifest, ...(method !== undefined ? { method } : {}) } : {}); }
|
|
386
|
+
try { parsedDoc = parseFindingsJson(findings, { ...(manifest ? { manifest, ...(method !== undefined ? { method } : {}) } : {}), ...(Array.isArray(recordOrigins) ? { recordOrigins } : {}) }); }
|
|
387
387
|
catch (e) {
|
|
388
388
|
return { ok: false, reason: `synthesis_findings_invalid: ${String(e?.message ?? e).slice(0, 300)}` };
|
|
389
389
|
}
|
|
@@ -608,7 +608,7 @@ export function recordSynthesis(runDir, received, opts = {}) {
|
|
|
608
608
|
const auto = driverReadsFor(dir0);
|
|
609
609
|
const { asks = auto.asks, ledger = auto.ledger, manifest = auto.manifest,
|
|
610
610
|
method = auto.method, methodInvalid = auto.methodInvalid ?? null,
|
|
611
|
-
owed = auto.owed, declined = auto.declined,
|
|
611
|
+
owed = auto.owed, declined = auto.declined, recordOrigins = undefined,
|
|
612
612
|
now = () => new Date().toISOString() } = opts;
|
|
613
613
|
const { dir, payload, accepted, refusals } = synthesisCallPaths(dir0);
|
|
614
614
|
// Its sibling rule — ONE FILE PER CALL, refusals included. This used to
|
|
@@ -644,7 +644,16 @@ export function recordSynthesis(runDir, received, opts = {}) {
|
|
|
644
644
|
call = merged.merged;
|
|
645
645
|
}
|
|
646
646
|
|
|
647
|
-
|
|
647
|
+
// A RECORD LINK ON A HOST THIS REGISTER DOES NOT PUBLISH is gated here as verify.mjs gates the saved
|
|
648
|
+
// file. The run's first such call is refused, naming every finding, so the seat can fix them in this
|
|
649
|
+
// turn; a repeat is accepted with those links blanked and the originals kept (foreign-record-links.mjs).
|
|
650
|
+
const origins = recordOriginsOr(recordOrigins);
|
|
651
|
+
const repeat = blankOnRepeat(call, origins, refusalsFor(dir0).some((r) => String(r?.reason ?? "").includes(FOREIGN_HOST_TOKEN)));
|
|
652
|
+
if (repeat.blanked.length) {
|
|
653
|
+
call = repeat.call;
|
|
654
|
+
recordBlanking(dir0, { stage: "synthesis", layer: "call", blanked: repeat.blanked, kept: repeat.kept });
|
|
655
|
+
}
|
|
656
|
+
const v = acceptSynthesis(call, { asks, ledger, manifest, method, methodInvalid, owed, declined, recordOrigins: origins });
|
|
648
657
|
if (!v.ok) {
|
|
649
658
|
noteRefusal(v.reason);
|
|
650
659
|
return { written: null, refused: v.reason,
|
package/driver/verify.mjs
CHANGED
|
@@ -158,7 +158,7 @@ function nonEmpty(content, min = MIN) {
|
|
|
158
158
|
* true for only one lane, and put back. Appending keeps every existing matcher matching — they all test
|
|
159
159
|
* substrings — and gives the seat the one word it was missing.
|
|
160
160
|
*
|
|
161
|
-
* It also sharpens `noChange` (
|
|
161
|
+
* It also sharpens `noChange` (in runStageLadder() in gateway.mjs, "this attempt's token equals the previous attempt's"):
|
|
162
162
|
* a file that starts failing a DIFFERENT member now reads as changed instead of as a stalled retry.
|
|
163
163
|
*
|
|
164
164
|
* `names` is positional against `markers` and optional; a call site that omits it emits exactly the token
|
package/mcp-server/CHANGELOG.md
CHANGED
package/mcp-server/CONNECT.md
CHANGED
|
@@ -21,9 +21,9 @@ It reads run directories off your disk. So:
|
|
|
21
21
|
|
|
22
22
|
- **It shows you runs you have already produced.** `CLEAROTRON_WORK_DIR` is where the engine writes
|
|
23
23
|
them, and that is the one variable the server needs.
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
- **With no install, it shows you the demo.** `npx clearotron mcp` starts this server from the npm package.
|
|
25
|
+
On a machine with no install it answers from the four sample runs `npx clearotron demo` replays, and every
|
|
26
|
+
row says it is the demo. On a machine with an install it reads that install's runs.
|
|
27
27
|
- **Nothing here spends money on its own,** with two exceptions that are gated and named: `start_run`
|
|
28
28
|
enqueues a real clearance, and `what_if_run` re-runs one pipeline stage. Both are refused by default on
|
|
29
29
|
a sensible allowlist — see "Hold two tools back" below.
|
|
@@ -51,6 +51,12 @@ claude mcp add trademark-artifacts --scope user \
|
|
|
51
51
|
|
|
52
52
|
Check it: `claude mcp list` prints `trademark-artifacts: … - √ Connected`.
|
|
53
53
|
|
|
54
|
+
With no clone, start it from the npm package instead, naming the version:
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
claude mcp add trademark-artifacts --scope user -- npx -y clearotron@<version> mcp
|
|
58
|
+
```
|
|
59
|
+
|
|
54
60
|
`--scope user` makes it available in every project, not only the directory you ran it in. In Windows
|
|
55
61
|
PowerShell 5.1, write the separator as `"--"`: that shell drops a bare `--`. Remove it with
|
|
56
62
|
`claude mcp remove trademark-artifacts`.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
|
+
// Copyright 2026 Cordillera Sàrl. Additional terms under section 7 of the AGPL-3.0 apply — see ADDITIONAL-TERMS.md
|
|
3
|
+
//
|
|
4
|
+
// demo-mode.mjs — whether this server is serving the demo's sample runs.
|
|
5
|
+
//
|
|
6
|
+
// `clearotron mcp` decides it and the server reads it, in one process: bin/mcp.mjs sets it before it
|
|
7
|
+
// loads the server, and the server reads it as it answers. It is a module and not an environment
|
|
8
|
+
// variable because nothing outside this process sets it or reads it, and every environment variable the
|
|
9
|
+
// product reads is a setting an operator is told about.
|
|
10
|
+
export const demoMode = { on: false };
|