clearotron 0.3.2-beta.7 → 0.3.2-beta.9
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 +58 -26
- package/CONTRIBUTING.md +8 -8
- package/INSTALL.md +148 -81
- package/README.md +3 -3
- package/SECURITY.md +3 -3
- package/bin/brandowner.mjs +3 -3
- package/bin/framework-preflight.mjs +1 -1
- package/bin/onboard.mjs +637 -216
- package/bin/start.mjs +151 -27
- package/bin/update.mjs +58 -11
- package/build-info.json +2 -2
- package/docs/DELIVERY.md +2 -1
- package/docs/INTAKE.md +1 -1
- package/docs/ONBOARDING.md +1 -1
- package/docs/architecture/03-run-lifecycle.md +6 -6
- package/docs/architecture/04-configuration-reference.md +32 -14
- package/docs/architecture/05-config-governance.md +23 -8
- package/docs/architecture/05-customer-profiles.md +2 -2
- package/docs/architecture/06-operations-runbook.md +3 -3
- package/docs/architecture/08-development-guide.md +6 -6
- package/docs/configuration.md +5 -5
- package/docs/decisions/0003-credential-model.md +1 -1
- package/docs/writing-standard.md +4 -0
- package/driver/CHANGELOG.md +124 -0
- package/driver/README.md +3 -3
- package/driver/band-size.mjs +59 -0
- package/driver/binding-layers.mjs +1 -1
- package/driver/citation-census.json +3 -3
- package/driver/{prelim-variants-record.mjs → clearance-variants-record.mjs} +24 -24
- package/driver/common-law-receipts.mjs +2 -2
- package/driver/company-bundle.mjs +3 -3
- package/driver/compose-read.mjs +8 -14
- package/driver/config-inventory.mjs +112 -9
- package/driver/consumption-ledger.mjs +2 -2
- package/driver/contract-arm2-baseline.json +2 -5
- package/driver/contract-dictation-registry.mjs +19 -19
- package/driver/contract-e3-backlog.mjs +43 -43
- package/driver/contract-e3-baseline.json +14 -14
- package/driver/contract-vocabulary.mjs +68 -27
- package/driver/deliver-trigger.sh +16 -16
- package/driver/demo-container.mjs +3 -3
- package/driver/dev-portal.mjs +3 -3
- package/driver/disposition-call.mjs +1 -1
- package/driver/door-gates.mjs +41 -7
- package/driver/doubt-ledger.mjs +2 -2
- package/driver/drainer-identity.mjs +34 -8
- package/driver/driver.config.mjs +367 -104
- package/driver/engine/CONTRACT.md +10 -3
- package/driver/engine/README.md +2 -2
- package/driver/engine/anthropic-agent.mjs +77 -21
- package/driver/engine/auth.mjs +129 -10
- package/driver/engine/jx-turn.mjs +7 -6
- package/driver/engine/mcp/README.md +1 -1
- package/driver/engine/mcp/dispositions-server.mjs +3 -3
- package/driver/engine/mcp/gather-config.mjs +9 -9
- package/driver/engine/mcp/perplexity-server.mjs +2 -2
- package/driver/engine/mcp/recording-server.mjs +18 -5
- package/driver/engine/openai-agent.mjs +4 -2
- package/driver/engine/probe.mjs +110 -23
- package/driver/enqueue-schema.mjs +6 -2
- package/driver/findings-model.mjs +6 -3
- package/driver/flag-snapshot.mjs +34 -8
- package/driver/form-neighbourhood.mjs +54 -7
- package/driver/framework.mjs +4 -4
- package/driver/gateway.mjs +36 -24
- package/driver/jx-lanes.mjs +23 -4
- package/driver/jx-units.mjs +7 -4
- package/driver/jx.mjs +34 -4
- package/driver/knockout-review-record.mjs +56 -4
- package/driver/known-conflicts.mjs +1 -1
- package/driver/matter-frame-record.mjs +90 -1
- package/driver/named-band.mjs +1 -1
- package/driver/ordinary-words.mjs +51 -0
- package/driver/outbox-backoff.mjs +31 -16
- package/driver/package.json +1 -1
- package/driver/partial-payload-baseline.json +2 -2
- package/driver/phase0.mjs +3 -3
- package/driver/pipeline-knockout.mjs +5 -5
- package/driver/pipeline.mjs +396 -81
- package/driver/placement-form.mjs +77 -1
- package/driver/placement-model.mjs +1 -1
- package/driver/portal-config-view.mjs +30 -1
- package/driver/portal-report.mjs +107 -6
- package/driver/portal-service.mjs +80 -14
- package/driver/portal-upstream.mjs +1 -1
- package/driver/predelivery-lint.mjs +12 -2
- package/driver/preserve-merge.mjs +3 -3
- package/driver/product-rows.mjs +2 -2
- package/driver/products.mjs +1 -1
- package/driver/profiles/README.md +3 -3
- package/driver/profiles/demo-brand-owner.json +2 -2
- package/driver/profiles.mjs +55 -17
- package/driver/progress.mjs +18 -8
- package/driver/provider-usage.mjs +8 -8
- package/driver/publish/index.mjs +154 -8
- package/driver/publish/knockout.mjs +39 -5
- package/driver/publish/pool-admin.mjs +1 -1
- package/driver/publish/publish-inputs.mjs +18 -2
- package/driver/publish/render-knockout.mjs +184 -31
- package/driver/publish/render.mjs +323 -93
- package/driver/publish/report-data.mjs +4 -1
- package/driver/publish/report-topbar.mjs +58 -0
- package/driver/publish/search-depth.mjs +133 -4
- package/driver/publish/templates/report.css +78 -4
- package/driver/publish/xlsx.mjs +20 -1
- package/driver/queue-order.mjs +2 -2
- package/driver/recording-agreement.mjs +1 -1
- package/driver/reference-score.mjs +1 -1
- package/driver/register-availability.mjs +2 -2
- package/driver/register-count.mjs +50 -5
- package/driver/register-coverage.mjs +161 -1
- package/driver/register-digest-record.mjs +236 -11
- package/driver/register-grant-vocabulary.mjs +1 -1
- package/driver/register-plan.mjs +189 -2
- package/driver/registry-fidelity.mjs +3 -3
- package/driver/repair-composers.mjs +1 -1
- package/driver/repair-contract.mjs +1 -1
- package/driver/replay-archive.mjs +6 -6
- package/driver/report-overview-record.mjs +2 -2
- package/driver/result-noun-fields.mjs +2 -2
- package/driver/run-economics.mjs +41 -10
- package/driver/run-requirements.mjs +173 -9
- package/driver/runner.mjs +5 -5
- package/driver/scope-facts.mjs +20 -5
- package/driver/scope-ledger.mjs +5 -5
- package/driver/search-policy.mjs +22 -12
- package/driver/skills/README.md +15 -15
- package/driver/skills/blind-frame/SKILL.md +2 -2
- package/driver/skills/case-law-citation/SKILL.md +4 -4
- package/driver/skills/case-law-citation/sources/eurlex.md +1 -1
- package/driver/skills/{prelim-common-law → clearance-common-law}/SKILL.md +22 -22
- package/driver/skills/{prelim-common-law → clearance-common-law}/perplexity-prompts.md +1 -1
- package/driver/skills/{prelim-register → clearance-register}/SKILL.md +10 -10
- package/driver/skills/{prelim-register → clearance-register}/digest.md +2 -2
- package/driver/skills/{prelim-register → clearance-register}/providers/README.md +1 -1
- package/driver/skills/{prelim-register → clearance-register}/providers/clarivate.md +37 -35
- package/driver/skills/{prelim-register → clearance-register}/providers/corsearch.md +20 -11
- package/driver/skills/{prelim-register → clearance-register}/providers/signa.md +5 -5
- package/driver/skills/{prelim-register → clearance-register}/register-recipes.md +3 -3
- package/driver/skills/{prelim-register → clearance-register}/status-rules.md +2 -2
- package/driver/skills/{prelim-register → clearance-register}/stealth-filer-indicators.md +1 -1
- package/driver/skills/{prelim-register → clearance-register}/unit.md +2 -2
- package/driver/skills/{prelim-search → clearance-search}/SKILL.md +31 -31
- package/driver/skills/{prelim-search → clearance-search}/delivery-contract.md +1 -1
- package/driver/skills/{prelim-search → clearance-search}/phase2-execution.md +18 -18
- package/driver/skills/{prelim-search → clearance-search}/synthesis-rules.md +7 -7
- package/driver/skills/{prelim-variants → clearance-variants}/SKILL.md +18 -18
- package/driver/skills/{prelim-variants → clearance-variants}/transliteration-scripts.md +5 -5
- package/driver/skills/frame-diff/SKILL.md +1 -1
- package/driver/skills/knockout-assess/SKILL.md +10 -7
- package/driver/skills/matter-frame/SKILL.md +3 -3
- package/driver/skills/narrative-refutation/SKILL.md +9 -9
- package/driver/skills/placement-inquiry/SKILL.md +5 -5
- package/driver/stage-context.mjs +1 -1
- package/driver/stages-knockout.mjs +4 -4
- package/driver/stages.mjs +65 -61
- package/driver/status-snapshot.mjs +2 -2
- package/driver/suite-census.json +340 -136
- package/driver/surface-exit-verdict.mjs +58 -0
- package/driver/systemd/README.md +9 -6
- package/driver/systemd/clearotron-worker.service +1 -1
- package/driver/terminal-clamp.mjs +109 -1
- package/driver/tokens.mjs +169 -3
- package/driver/unit-environment.mjs +42 -15
- package/driver/unit-inventory.mjs +19 -2
- package/driver/usage-ledger.mjs +1 -1
- package/driver/variant-manifest-model.mjs +4 -4
- package/driver/verify-knockout.mjs +27 -0
- package/driver/verify.mjs +94 -6
- package/driver/whatif-queue.mjs +1 -1
- package/driver/wordlists/en.txt +63906 -0
- package/mcp-server/CHANGELOG.md +8 -0
- package/mcp-server/README.md +1 -1
- package/mcp-server/lib/README.md +1 -1
- package/mcp-server/lib/options.mjs +8 -7
- package/mcp-server/lib/plan.mjs +18 -2
- package/mcp-server/lib/runs.mjs +1 -1
- package/mcp-server/lib/usage.mjs +3 -3
- package/mcp-server/lib/whatif.mjs +1 -1
- package/mcp-server/package.json +1 -1
- package/mcp-server/server.mjs +18 -1
- package/package.json +12 -11
- package/portal-ui/dist/assets/{index-CVOIvdhc.css → index-CtvwLCti.css} +207 -3
- package/portal-ui/dist/assets/{index-5UyqAyNM.js → index-EVaSo5-g.js} +1580 -527
- package/portal-ui/dist/index.html +2 -2
- package/portal-ui/package.json +1 -1
- package/providers/README.md +1 -1
- package/providers/_shared/enumerate.mjs +6 -6
- package/providers/_shared/execute-plan.mjs +3 -3
- package/providers/_shared/ledger.mjs +119 -5
- package/providers/_shared/provider-text.mjs +2 -2
- package/providers/_shared/screen.mjs +2 -2
- package/providers/_shared/script-form.mjs +3 -3
- package/providers/_shared/territory-codes.mjs +23 -3
- package/providers/clarivate/README.md +1 -1
- package/providers/clarivate/src/capabilities.js +12 -12
- package/providers/clarivate/src/core.js +37 -43
- package/providers/corsearch/README.md +1 -1
- package/providers/corsearch/src/capabilities.js +5 -5
- package/providers/corsearch/src/core.js +3 -3
- package/providers/jx/README.md +2 -1
- package/providers/jx/src/turn-envelope.mjs +8 -3
- package/providers/oauth-mcp-bridge/CHANGELOG.md +8 -0
- package/providers/oauth-mcp-bridge/package.json +1 -1
- package/providers/perplexity/src/core.js +1 -1
- package/providers/signa/README.md +1 -1
- package/providers/signa/src/capabilities.js +42 -49
- package/providers/signa/src/core.js +106 -29
- package/providers/uspto-local/README.md +1 -1
- package/providers/uspto-local/src/sync.js +1 -1
- package/scripts/README.md +1 -0
- package/scripts/ask-ai-render-check.mjs +127 -1
- package/scripts/authority-boundary-probe.mjs +8 -6
- package/scripts/backfill-started-at.mjs +2 -2
- package/scripts/census-merge-driver.mjs +33 -2
- package/scripts/citation-anchor-report.mjs +181 -0
- package/scripts/dead-names.mjs +1 -1
- package/scripts/deprecate-below.mjs +66 -8
- package/scripts/drain-preflight.mjs +1 -1
- package/scripts/e2e.mjs +174 -0
- package/scripts/env-audit.mjs +39 -6
- package/scripts/env-classify.mjs +20 -2
- package/scripts/freeze-example-run.mjs +61 -18
- package/scripts/generated-files-are-current.mjs +69 -4
- package/scripts/live-surface-check.mjs +124 -41
- package/scripts/markdown-link-check.mjs +1 -1
- package/scripts/merge-shape-check.mjs +242 -0
- package/scripts/mint-names-in-force.mjs +5 -5
- package/scripts/mint-offered-territories.mjs +72 -0
- package/scripts/mint-public-residue.mjs +2 -2
- package/scripts/mint-reference-strip-backlog.mjs +2 -2
- package/scripts/mint-suite-census.mjs +75 -2
- package/scripts/mint-writing-standard-backlog.mjs +2 -2
- package/scripts/purge-runs.mjs +7 -7
- package/scripts/reconcile-runs.mjs +2 -2
- package/scripts/release-approve-parked.mjs +20 -2
- package/scripts/release-await-cut.mjs +120 -1
- package/scripts/release-note-required.mjs +76 -8
- package/scripts/report-header-render-check.mjs +164 -0
- package/scripts/settings-render-check.mjs +75 -2
- package/scripts/test-full.mjs +96 -3
- package/scripts/test-run.mjs +10 -0
- package/shared/brand.mjs +27 -0
- package/shared/connect-clients.mjs +39 -11
- package/shared/deployment-box.mjs +7 -2
- package/shared/driver-dir.mjs +1 -1
- package/shared/env-aliases.mjs +1 -1
- package/shared/identifier-scan.mjs +65 -9
- package/shared/identifier-sentinels.mjs +22 -0
- package/shared/names-in-force.mjs +4 -2
- package/shared/offered-territories.json +738 -0
- package/shared/pre-rename-spellings.mjs +53 -0
- package/shared/reference-guard-classes.mjs +40 -2
- package/shared/stdio-connect.mjs +39 -4
- package/shared/tree-commit.mjs +48 -0
- /package/driver/skills/{prelim-register → clearance-register}/providers/euipo.md +0 -0
- /package/driver/skills/{prelim-register → clearance-register}/providers/free-tier.md +0 -0
- /package/driver/skills/{prelim-register → clearance-register}/providers/uspto-local.md +0 -0
- /package/driver/skills/{prelim-search → clearance-search}/field-doctrine-pharma.md +0 -0
- /package/driver/skills/{prelim-search → clearance-search}/firm-wide-reasoning.md +0 -0
- /package/driver/skills/{prelim-search → clearance-search}/report-prose.md +0 -0
- /package/driver/skills/{prelim-search → clearance-search}/risk-framework-demo.manifest.json +0 -0
- /package/driver/skills/{prelim-search → clearance-search}/risk-framework-demo.md +0 -0
- /package/driver/skills/{prelim-search → clearance-search}/risk-framework-triage.manifest.json +0 -0
- /package/driver/skills/{prelim-search → clearance-search}/risk-framework-triage.md +0 -0
- /package/driver/skills/{prelim-search → clearance-search}/risk-framework.manifest.json +0 -0
- /package/driver/skills/{prelim-search → clearance-search}/risk-framework.md +0 -0
- /package/driver/skills/{prelim-search → clearance-search}/template-formatting.md +0 -0
- /package/driver/skills/{prelim-search → clearance-search}/templates/email/generic.md +0 -0
- /package/driver/skills/{prelim-search → clearance-search}/templates/search-request-form.html +0 -0
- /package/driver/skills/{prelim-search → clearance-search}/worked-examples-demo.md +0 -0
- /package/driver/skills/{prelim-search → clearance-search}/worked-examples.md +0 -0
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
//
|
|
15
15
|
// AND IT PRESENTED AS SEARCHED, which is the part that made it a compliance defect rather than a
|
|
16
16
|
// coverage one. The disclosure machinery only describes territories the compiler recorded as
|
|
17
|
-
// UNREACHABLE. These were recorded as reached, so there was no row to render, and `
|
|
17
|
+
// UNREACHABLE. These were recorded as reached, so there was no row to render, and `clearance-search`'s
|
|
18
18
|
// rule against rendering a deferred jurisdiction as a clean negative had nothing to fire on.
|
|
19
19
|
//
|
|
20
20
|
// ── TWO FACTS, KEPT APART ON PURPOSE ────────────────────────────────────────────────────────────────
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
2
|
// Copyright 2026 Cordillera Sàrl. Additional terms under section 7 of the AGPL-3.0 apply — see ADDITIONAL-TERMS.md
|
|
3
|
-
//
|
|
3
|
+
// clearance-variants-record.mjs — the recording transport for the variant manifest.
|
|
4
4
|
//
|
|
5
5
|
// Conversion 3, after blind-frame, skeptic, frame-diff and matter-frame. It is
|
|
6
6
|
// the first conversion whose ruling includes CLASS 3, and the first that can DELETE a derivation rather
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
// O3c measured the cost of that hand-formatting directly: 9 Bash calls with 4 WRITES across 15 attempts,
|
|
18
18
|
// and the shape is `python3 -c` over `variant-manifest.json` — the seat pre-checking its own JSON before
|
|
19
19
|
// saving it. That is CLASS 3, and the design's ruling is that such a check does not get a compute tool:
|
|
20
|
-
// it moves to the ACCEPTANCE BOUNDARY. `
|
|
20
|
+
// it moves to the ACCEPTANCE BOUNDARY. `acceptClearanceVariants` measures on accept and refuses with the
|
|
21
21
|
// measured value, so the check runs on every call instead of when a seat remembers to run it.
|
|
22
22
|
//
|
|
23
23
|
// ── AND IT DELETES A DERIVATION, WHICH IS THE REAL PRIZE ────────────────────────────────────────────
|
|
@@ -45,8 +45,8 @@ export const PROSE_FILE = "variant-manifest.md";
|
|
|
45
45
|
const SCHEMA_VERSION = 1;
|
|
46
46
|
|
|
47
47
|
/** Where the call's evidence lives — the driver's own record of what the seat handed it. */
|
|
48
|
-
export function
|
|
49
|
-
const dir = driverDir(runDir, "
|
|
48
|
+
export function clearanceVariantsCallPaths(runDir) {
|
|
49
|
+
const dir = driverDir(runDir, "clearance-variants-calls");
|
|
50
50
|
return { dir, payload: join(dir, "call-001.json"), accepted: join(dir, "accepted.json") };
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -107,7 +107,7 @@ export function renderScopeLedgerTable(rows) {
|
|
|
107
107
|
* Rendering from the parsed model is what makes the two artifacts one statement: they cannot disagree
|
|
108
108
|
* about a variant, because both are projections of one validated object. PURE.
|
|
109
109
|
*/
|
|
110
|
-
export function
|
|
110
|
+
export function renderClearanceVariants(model, scopeRows) {
|
|
111
111
|
// ── HEADING DEPTH IS LOAD-BEARING, AND THIS IS THE ONE THING IN THIS FILE NOT TO "TIDY" ────────────
|
|
112
112
|
//
|
|
113
113
|
// `variantsManifestAudit` (common-law-receipts.mjs) arms a term collector on any heading matching
|
|
@@ -151,7 +151,7 @@ export function renderPrelimVariants(model, scopeRows) {
|
|
|
151
151
|
...model.search_floor.map((a) => `- ${a}`), "");
|
|
152
152
|
|
|
153
153
|
out.push(...renderScopeLedgerTable(scopeRows));
|
|
154
|
-
out.push("---", "", "Rendered by the driver from the stage's `
|
|
154
|
+
out.push("---", "", "Rendered by the driver from the stage's `record_clearance_variants` call. "
|
|
155
155
|
+ `The structured model in ${MODEL_FILE} is the authority for the terms, and scope-ledger.json for the `
|
|
156
156
|
+ "ledger; this file is their human-readable projection.", "");
|
|
157
157
|
return out.join("\n");
|
|
@@ -178,8 +178,8 @@ const DECLARED = Object.freeze({
|
|
|
178
178
|
export const refuseUndeclared = (params) => refuseUndeclaredShared(params, DECLARED, "variantmodel");
|
|
179
179
|
|
|
180
180
|
/** The last ACCEPTED call for this run, or null. */
|
|
181
|
-
export function
|
|
182
|
-
return lastAccepted(
|
|
181
|
+
export function lastAcceptedClearanceVariants(runDir) {
|
|
182
|
+
return lastAccepted(clearanceVariantsCallPaths(String(runDir ?? "")).accepted, readFileSync);
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
/**
|
|
@@ -190,7 +190,7 @@ export function lastAcceptedPrelimVariants(runDir) {
|
|
|
190
190
|
* Preserving rather than requiring, because nothing here can tell a first call from a repair and a
|
|
191
191
|
* product refusal is never a pass. See preserve-merge.mjs for the class.
|
|
192
192
|
*/
|
|
193
|
-
export function
|
|
193
|
+
export function mergeClearanceVariantsCall(stored, received) {
|
|
194
194
|
const base = stored ?? {};
|
|
195
195
|
return {
|
|
196
196
|
mark: received?.mark,
|
|
@@ -207,7 +207,7 @@ export function mergePrelimVariantsCall(stored, received) {
|
|
|
207
207
|
};
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
-
export function
|
|
210
|
+
export function acceptClearanceVariants(params) {
|
|
211
211
|
const model = {
|
|
212
212
|
schema_version: SCHEMA_VERSION,
|
|
213
213
|
mark: params?.mark,
|
|
@@ -250,7 +250,7 @@ export function acceptPrelimVariants(params) {
|
|
|
250
250
|
scopeRows.push({ layer, item, status, reason, reopen_trigger });
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
-
return { ok: true, model: parsed, scopeRows, content:
|
|
253
|
+
return { ok: true, model: parsed, scopeRows, content: renderClearanceVariants(parsed, scopeRows) };
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
/**
|
|
@@ -263,8 +263,8 @@ export function acceptPrelimVariants(params) {
|
|
|
263
263
|
* the first two, so a crash between writes leaves the run with its load-bearing files and a missing
|
|
264
264
|
* restatement rather than a restatement of something never stored.
|
|
265
265
|
*/
|
|
266
|
-
export function
|
|
267
|
-
const { dir, payload } =
|
|
266
|
+
export function recordClearanceVariants(runDir, received, { now = () => new Date().toISOString() } = {}) {
|
|
267
|
+
const { dir, payload } = clearanceVariantsCallPaths(String(runDir ?? ""));
|
|
268
268
|
// — ONE FILE PER CALL, refusals included. This wrote a single fixed `call-001.json`,
|
|
269
269
|
// so a turn refused and then re-sent kept only the survivor: the file whose header promises "including
|
|
270
270
|
// calls that were refused" held the one call that was not. Sequence 1 still resolves to `call-001.json`,
|
|
@@ -288,8 +288,8 @@ export function recordPrelimVariants(runDir, received, { now = () => new Date().
|
|
|
288
288
|
if (undeclared) {
|
|
289
289
|
return { written: null, refused: undeclared, captured: closeCapture({ ok: false, refused: undeclared }), capture_failed: captureFailed };
|
|
290
290
|
}
|
|
291
|
-
const call =
|
|
292
|
-
const verdict =
|
|
291
|
+
const call = mergeClearanceVariantsCall(lastAcceptedClearanceVariants(runDir), received);
|
|
292
|
+
const verdict = acceptClearanceVariants(call);
|
|
293
293
|
if (!verdict.ok) {
|
|
294
294
|
return { written: null, refused: verdict.reason, captured: closeCapture({ ok: false, refused: verdict.reason }), capture_failed: captureFailed };
|
|
295
295
|
}
|
|
@@ -299,7 +299,7 @@ export function recordPrelimVariants(runDir, received, { now = () => new Date().
|
|
|
299
299
|
try {
|
|
300
300
|
writeFileSync(at, JSON.stringify(verdict.model, null, 2) + "\n");
|
|
301
301
|
// Step 5. BEST-EFFORT, in its own try — see report-overview-record.mjs for why.
|
|
302
|
-
try { writeFileSync(
|
|
302
|
+
try { writeFileSync(clearanceVariantsCallPaths(String(runDir ?? "")).accepted, acceptedEnvelope(call, now())); }
|
|
303
303
|
catch { /* a lost base is never a lost artifact */ }
|
|
304
304
|
writeFileSync(proseAt, verdict.content);
|
|
305
305
|
} catch (e) {
|
|
@@ -320,7 +320,7 @@ export function recordPrelimVariants(runDir, received, { now = () => new Date().
|
|
|
320
320
|
|
|
321
321
|
/** The typed scope-ledger rows, for the driver's own serialisation. PURE — no re-parse of the table. */
|
|
322
322
|
export function recordedScopeRows(received) {
|
|
323
|
-
const v =
|
|
323
|
+
const v = acceptClearanceVariants(received);
|
|
324
324
|
return v.ok ? v.scopeRows : [];
|
|
325
325
|
}
|
|
326
326
|
|
|
@@ -332,7 +332,7 @@ export function recordedScopeRows(received) {
|
|
|
332
332
|
* and it carried no ledger rows" — which is a manifest with an empty ledger, not a manifest to re-parse.
|
|
333
333
|
* Collapsing the two would send the driver back to the table on a run that had already answered.
|
|
334
334
|
*
|
|
335
|
-
* The rows are re-validated through `
|
|
335
|
+
* The rows are re-validated through `acceptClearanceVariants` rather than trusted raw out of the capture:
|
|
336
336
|
* the capture records what ARRIVED, untidied, including a refused call's params. IMPURE (reads the run).
|
|
337
337
|
*/
|
|
338
338
|
export function recordedScopeLedgerRows(runDir) {
|
|
@@ -344,22 +344,22 @@ export function recordedScopeLedgerRows(runDir) {
|
|
|
344
344
|
// partial does not validate on its own, so this would have returned null — "no typed call, go and
|
|
345
345
|
// parse the prose" — on a run whose merged call had validated and written a manifest. The accepted
|
|
346
346
|
// base IS the merged, validated call, which is exactly what this wants.
|
|
347
|
-
const merged =
|
|
347
|
+
const merged = lastAcceptedClearanceVariants(dir0);
|
|
348
348
|
if (merged) {
|
|
349
|
-
const v =
|
|
349
|
+
const v = acceptClearanceVariants(merged);
|
|
350
350
|
if (v.ok) return v.scopeRows;
|
|
351
351
|
}
|
|
352
352
|
// FALLBACK: runs that predate the base, which have a capture and no accepted.json. Unchanged
|
|
353
353
|
// behaviour for them, and it is why this is a fallback rather than a replacement.
|
|
354
354
|
let captured;
|
|
355
|
-
try { captured = JSON.parse(readFileSync(
|
|
355
|
+
try { captured = JSON.parse(readFileSync(clearanceVariantsCallPaths(dir0).payload, "utf8")); }
|
|
356
356
|
catch { return null; } // no call — the prose path is the answer
|
|
357
|
-
const v =
|
|
357
|
+
const v = acceptClearanceVariants(captured?.params);
|
|
358
358
|
return v.ok ? v.scopeRows : null; // a refused call never wrote a manifest either
|
|
359
359
|
}
|
|
360
360
|
|
|
361
361
|
/** Was this run's manifest written through the typed transport? The ruled discriminator. */
|
|
362
|
-
export function
|
|
363
|
-
try { readFileSync(
|
|
362
|
+
export function clearanceVariantsWasRecorded(runDir) {
|
|
363
|
+
try { readFileSync(clearanceVariantsCallPaths(String(runDir ?? "")).payload, "utf8"); return true; }
|
|
364
364
|
catch { return false; }
|
|
365
365
|
}
|
|
@@ -46,7 +46,7 @@ function rowCells(ln) {
|
|
|
46
46
|
* The variant terms the manifest commits the grid to search: data rows of sections whose heading
|
|
47
47
|
* contains "variants" (the Variants tables). "Variant applicability" sections (category
|
|
48
48
|
* dispositions, not search terms) are excluded. The term column is resolved from each table's
|
|
49
|
-
* HEADER row — the live
|
|
49
|
+
* HEADER row — the live clearance-variants format is `| Category | Value | Rationale | Verify? |`
|
|
50
50
|
* (term in "Value"), while older/test manifests use `| Variant | ... |` (term first); default 0
|
|
51
51
|
* when no recognizable header exists.
|
|
52
52
|
*/
|
|
@@ -842,7 +842,7 @@ export function mergeCommonLawFindings(parts) {
|
|
|
842
842
|
// FALSE against the real ledger, and the arm failed the very run it was derived from:
|
|
843
843
|
//
|
|
844
844
|
// • `candidates[]` is RAW, UNJUDGED web-search output — the grid program records up to 8 candidates
|
|
845
|
-
// per cell "without judging similarity" (skills/
|
|
845
|
+
// per cell "without judging similarity" (skills/clearance-common-law/perplexity-prompts.md), and the
|
|
846
846
|
// filtering is explicitly the model's. The real cell `CORAL FREEZE × vitaminshoppe.com` holds three:
|
|
847
847
|
// a BCAA how-to video, a Hawaiian shaved-ice supplement and a Dallas store-locator page. The
|
|
848
848
|
// model's "No results" means "no relevant listing", and no deterministic test can tell that page
|
|
@@ -44,7 +44,7 @@ import { Refusal } from "../shared/onboarding-store.mjs";
|
|
|
44
44
|
* Broken means someone TRIED to select one and it does not resolve, and falling back there would rate a
|
|
45
45
|
* client's matters under a framework nobody chose while the output said everything was fine.
|
|
46
46
|
*
|
|
47
|
-
* The profile validator checks the SHAPE of this string only (`skills/
|
|
47
|
+
* The profile validator checks the SHAPE of this string only (`skills/clearance-search/<file>.md`, no
|
|
48
48
|
* escape) and never whether the file is there — so a shape-valid path to a document that does not exist
|
|
49
49
|
* validates cleanly and fails at rating time, which is the wrong place to find out.
|
|
50
50
|
*/
|
|
@@ -58,9 +58,9 @@ export function resolveFramework(requested, {
|
|
|
58
58
|
const path = String(requested).trim();
|
|
59
59
|
// Shape first, and by the profile validator's own rule rather than a second copy of it: a path that
|
|
60
60
|
// would be refused at load must be refused here, in the same words, before anything is written.
|
|
61
|
-
if (!/^skills\/prelim-search\/[^/]+\.md$/.test(path) || path.includes(".."))
|
|
61
|
+
if (!/^skills\/(?:clearance|prelim)-search\/[^/]+\.md$/.test(path) || path.includes("..")) // either spelling of the folder, as the profile loader
|
|
62
62
|
throw new Refusal(
|
|
63
|
-
`--framework must name a document of the form "skills/
|
|
63
|
+
`--framework must name a document of the form "skills/clearance-search/<file>.md" (got ${JSON.stringify(path)}). `
|
|
64
64
|
+ `A profile selects a SHIPPED framework, never an arbitrary path.`);
|
|
65
65
|
|
|
66
66
|
// RESOLVED THE WAY THE RATING STAGE RESOLVES IT, never by joining the repo root. `skills/...` paths
|
package/driver/compose-read.mjs
CHANGED
|
@@ -55,6 +55,7 @@ const MAX_CLASSES = 15;
|
|
|
55
55
|
const MAX_TERRITORIES = 20;
|
|
56
56
|
const MAX_NOTES = 8;
|
|
57
57
|
import { PRODUCTS, PRODUCT_IDS } from "./products.mjs";
|
|
58
|
+
import OFFERED from "../shared/offered-territories.json" with { type: "json" }; // the form's own list, minted by rule
|
|
58
59
|
|
|
59
60
|
const MAX_STR = 600;
|
|
60
61
|
const MAX_NOTE = 240;
|
|
@@ -62,22 +63,15 @@ const MAX_NOTE = 240;
|
|
|
62
63
|
/**
|
|
63
64
|
* The territory vocabulary, as offered by the composer's Where field.
|
|
64
65
|
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
66
|
+
* READ FROM THE SAME FILE THE FORM READS: shared/offered-territories.json, minted by rule from what the
|
|
67
|
+
* registers can search (scripts/mint-offered-territories.mjs). It used to be a hand-kept copy of the form's
|
|
68
|
+
* own list, "mirrored" by a comment, and a comment keeps nothing equal. One file read twice cannot differ.
|
|
67
69
|
*
|
|
68
|
-
* "Worldwide"
|
|
69
|
-
* and the read
|
|
70
|
-
*
|
|
71
|
-
* bytes on the wire in the first place.
|
|
70
|
+
* "Worldwide" is not in it. It is not a territory the composer offers and never was — it is a MODE,
|
|
71
|
+
* and the read carries it as its own boolean. Listing it taught the model to write a token the form had to
|
|
72
|
+
* strip back out, which is how "everywhere" and "nowhere in particular" became the same bytes on the wire.
|
|
72
73
|
*/
|
|
73
|
-
export const PROMPT_TERRITORIES = Object.freeze([
|
|
74
|
-
"European Union", "Benelux", "African Regional (ARIPO)",
|
|
75
|
-
"United States", "United Kingdom", "Ireland", "France", "Germany", "Spain", "Italy", "Netherlands",
|
|
76
|
-
"Switzerland", "Austria", "Sweden", "Norway", "Poland", "Bulgaria", "Greece", "Turkey", "Canada",
|
|
77
|
-
"Mexico", "Brazil", "Argentina", "China", "Hong Kong", "Taiwan", "Macau", "Japan", "South Korea",
|
|
78
|
-
"Singapore", "India", "Thailand", "Australia", "New Zealand", "United Arab Emirates", "Saudi Arabia",
|
|
79
|
-
"South Africa",
|
|
80
|
-
]);
|
|
74
|
+
export const PROMPT_TERRITORIES = Object.freeze([...OFFERED.regions, ...OFFERED.countries].map((t) => t.name));
|
|
81
75
|
|
|
82
76
|
/**
|
|
83
77
|
* The shape the model must answer in.
|
|
@@ -42,7 +42,10 @@ import {
|
|
|
42
42
|
DEFAULT_ENGINE_ID, ENGINE_BINARIES, PROVIDERS, RESEARCH_PROVIDERS, SERP_PROVIDERS,
|
|
43
43
|
missingCredentials, preflightEngineBinary, providerIdFrom,
|
|
44
44
|
} from "./driver.config.mjs";
|
|
45
|
-
import {
|
|
45
|
+
import {
|
|
46
|
+
resolveAuthMode, billingMode, cloudsSwitchedOn, BILLING_MODES, CLOUD_SWITCH, CLOUD_CREDENTIAL_CHECK,
|
|
47
|
+
} from "./engine/auth.mjs";
|
|
48
|
+
import { billingRefusalWords } from "./run-requirements.mjs"; // — a refusal that quotes the billing word says it by name
|
|
46
49
|
import { CASELAW_BRIDGES } from "./engine/mcp/gather-config.mjs"; // — the list that decides what is spawned
|
|
47
50
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
48
51
|
import { join } from "node:path";
|
|
@@ -60,7 +63,9 @@ const shown = (names) => names.map((n) => n);
|
|
|
60
63
|
* absent, because the alternative is silently billing a subscription the operator thought they had
|
|
61
64
|
* stopped using (engine/auth.mjs's opening argument). A writer that caught that and recorded "unknown"
|
|
62
65
|
* would erase precisely the misconfiguration a staff config page exists to surface, so it is caught and
|
|
63
|
-
* recorded AS ITSELF: mode `api-key`, `apiBilled: false`, and a fault naming the variable to set.
|
|
66
|
+
* recorded AS ITSELF: mode `api-key`, `apiBilled: false`, and a fault naming the variable to set. The
|
|
67
|
+
* cloud mode's refusals, and a word that is not a mode at all, are recorded as themselves too, by the
|
|
68
|
+
* refusal's own sentence.
|
|
64
69
|
*
|
|
65
70
|
* `apiBilled` is what the page should believe over `mode` — the two come apart in exactly this case,
|
|
66
71
|
* and only one of them describes who gets the invoice.
|
|
@@ -77,14 +82,38 @@ export function engineInventory(env = process.env) {
|
|
|
77
82
|
const billing = (() => {
|
|
78
83
|
try {
|
|
79
84
|
const a = resolveAuthMode({ engineName: id, env });
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
// `cloud` is the resolver's own answer, never re-derived here: the account a run bills is whatever
|
|
86
|
+
// the run door resolves, and a page that worked it out a second way could name another.
|
|
87
|
+
const cloud = a.cloud ?? null;
|
|
88
|
+
return { mode: a.mode, apiBilled: a.apiBilled === true, missing: [], cloud, cloudName: cloudName(cloud) };
|
|
89
|
+
} catch (e) {
|
|
90
|
+
// Recorded AS ITSELF, whichever refusal it was. An API-key mode with no key names the variable to
|
|
91
|
+
// set, reconstructed from the table so it cannot drift from it. Every other refusal (a cloud mode with
|
|
92
|
+
// no cloud switched on or with two, a cloud switch beside a mode it contradicts, a word that is not a
|
|
93
|
+
// mode) leaves `missing` empty, because the page reads `missing` as "set this key" and a key that is
|
|
94
|
+
// set is not missing, and carries a `reason` the page words itself (billingRefusalReason, below).
|
|
95
|
+
const mode = billingMode(env);
|
|
96
|
+
const keyAbsent = Boolean(spec?.apiKeyEnv) && String(env[spec.apiKeyEnv] ?? "") === "";
|
|
97
|
+
if (mode === "api-key" && keyAbsent) {
|
|
98
|
+
return { mode, apiBilled: false, missing: shown([spec.apiKeyEnv]), cloud: null, cloudName: null };
|
|
99
|
+
}
|
|
100
|
+
const reason = billingRefusalReason(id, env);
|
|
101
|
+
const notAMode = reason.kind === "not-a-mode";
|
|
84
102
|
return {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
103
|
+
// A WORD THAT IS NOT A MODE IS NOT RECORDED. It is whatever was typed into the setting that decides
|
|
104
|
+
// who pays, and a key pasted there by mistake is that word; this inventory is written to a file and
|
|
105
|
+
// served to a browser. So the mode reads `unknown`, and the refusal says the setting by name.
|
|
106
|
+
mode: notAMode ? "unknown" : mode,
|
|
107
|
+
apiBilled: false, missing: [], cloud: null, cloudName: null,
|
|
108
|
+
// THAT REFUSAL IS WRITTEN HERE, NOT CLEANED FROM THE RESOLVER'S. The resolver's sentence quotes the
|
|
109
|
+
// typed word, and removing it by pattern depends on how the word is spelled: a word that itself
|
|
110
|
+
// contains " is not a billing mode" left its tail behind. Built from names alone, nothing typed can
|
|
111
|
+
// reach it. Every other refusal quotes only setting names and the three mode words.
|
|
112
|
+
refusal: notAMode
|
|
113
|
+
? `${reason.setting} is set to a word that is not a billing mode — refusing to guess, because the guess `
|
|
114
|
+
+ `would bill the subscription. One of: ${reason.modes.join(", ")}.`
|
|
115
|
+
: billingRefusalWords(String(e?.message ?? e)),
|
|
116
|
+
reason,
|
|
88
117
|
};
|
|
89
118
|
}
|
|
90
119
|
})();
|
|
@@ -104,6 +133,80 @@ export function engineInventory(env = process.env) {
|
|
|
104
133
|
return { id, vendor: spec?.vendor ?? null, known: Boolean(spec), billing, binaryPresent };
|
|
105
134
|
}
|
|
106
135
|
|
|
136
|
+
/**
|
|
137
|
+
* What a reader calls the account a cloud mode bills: "Google Cloud", "Microsoft Azure", "Amazon Bedrock"
|
|
138
|
+
* or "Gateway". Null for no cloud.
|
|
139
|
+
*
|
|
140
|
+
* ONE TABLE OF CLOUD NAMES, NOT TWO. `CLOUD_CREDENTIAL_CHECK` in engine/auth.mjs already names each cloud
|
|
141
|
+
* the way a reader knows it, for the advice a refused sign-in prints, and this reads it rather than keeping
|
|
142
|
+
* a second list that could name a cloud differently on the page. It writes the gateway "the gateway", for
|
|
143
|
+
* use inside a sentence; a label on a page drops the article and starts with a capital, and that one
|
|
144
|
+
* adjustment is the whole of what this adds.
|
|
145
|
+
*/
|
|
146
|
+
export function cloudName(cloud) {
|
|
147
|
+
const who = CLOUD_CREDENTIAL_CHECK[cloud]?.who;
|
|
148
|
+
if (!who) return null;
|
|
149
|
+
const bare = who.replace(/^the /, "");
|
|
150
|
+
return bare.charAt(0).toUpperCase() + bare.slice(1);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* WHY A BILLING SETTING REFUSES EVERY SEARCH, as data: which refusal it is and the names involved, so the
|
|
155
|
+
* config page words it once, in plain English, without reading the resolver's sentence apart.
|
|
156
|
+
*
|
|
157
|
+
* `kind` is one of:
|
|
158
|
+
* switch-beside-mode subscription or api-key, and a cloud's switch on beside it (`clouds`)
|
|
159
|
+
* two-clouds cloud, and more than one cloud switched on (`clouds`)
|
|
160
|
+
* no-cloud cloud, and no cloud switched on and no gateway address (`clouds` lists every
|
|
161
|
+
* switch, and `gateway` the gateway's setting, as the choices to make)
|
|
162
|
+
* not-a-mode a word that is not a billing mode (`modes` are the ones this engine takes)
|
|
163
|
+
* cloud-on-codex cloud, on the Codex engine, which a cloud account cannot pay for (`engineSetting`
|
|
164
|
+
* and `engineChoice` name the Claude engine only where it would pay: one cloud
|
|
165
|
+
* switched on, or none and a gateway address; otherwise that move is one more refusal)
|
|
166
|
+
* unclassified a refusal this list does not name; the page says only that searches are refused.
|
|
167
|
+
* Not "other": that is an assistant's id in connect-clients.mjs, and a surface may
|
|
168
|
+
* not name one in code
|
|
169
|
+
*
|
|
170
|
+
* `defaulted` says the billing setting is blank, so `subscription` is the default and not a word anybody
|
|
171
|
+
* wrote: a page that said "payment is set to subscription" would send a reader looking for a line their
|
|
172
|
+
* settings file does not have. It is the state measured on Foundry, a switch on and the word unset.
|
|
173
|
+
*
|
|
174
|
+
* THE SAME PREDICATES AS THE RESOLVER, IN ITS ORDER. `resolveAuthMode` refuses by throwing a sentence and
|
|
175
|
+
* nothing else, so the kind is read back from the same environment through the same functions it uses
|
|
176
|
+
* (`billingMode`, `cloudsSwitchedOn`), in the order it checks them. Called only once it has thrown.
|
|
177
|
+
*
|
|
178
|
+
* NAMES, NEVER A VALUE. `mode` is sent only when it is one of the three modes; the word in a `not-a-mode`
|
|
179
|
+
* refusal is whatever was typed, and it is not sent at all.
|
|
180
|
+
*/
|
|
181
|
+
export function billingRefusalReason(id, env = process.env) {
|
|
182
|
+
const mode = billingMode(env);
|
|
183
|
+
const setting = "CLEAROTRON_AI_BILLING";
|
|
184
|
+
const clouds = (ids) => ids.map((c) => ({ name: cloudName(c), setting: CLOUD_SWITCH[c] }));
|
|
185
|
+
const defaulted = String(env[setting] ?? "").trim() === "";
|
|
186
|
+
const base = { setting, mode: null, defaulted, clouds: [], modes: [], gateway: null, engineSetting: null, engineChoice: null };
|
|
187
|
+
if (id === "openai-agent") {
|
|
188
|
+
if (mode === "cloud") {
|
|
189
|
+
// The resolver's own test for a cloud the Claude engine would pay through, in its words: one switch,
|
|
190
|
+
// or no switch and a gateway address.
|
|
191
|
+
const on = cloudsSwitchedOn(env);
|
|
192
|
+
const claudeWouldPay = on.length === 1 || (!on.length && Boolean(env.ANTHROPIC_BASE_URL));
|
|
193
|
+
return { ...base, kind: "cloud-on-codex", mode, modes: ["subscription", "api-key"],
|
|
194
|
+
...(claudeWouldPay ? { engineSetting: "CLEAROTRON_AI", engineChoice: "anthropic-agent" } : {}) };
|
|
195
|
+
}
|
|
196
|
+
if (mode !== "subscription" && mode !== "api-key") return { ...base, kind: "not-a-mode", modes: ["subscription", "api-key"] };
|
|
197
|
+
}
|
|
198
|
+
if (id === "anthropic-agent") {
|
|
199
|
+
const on = cloudsSwitchedOn(env);
|
|
200
|
+
if ((mode === "subscription" || mode === "api-key") && on.length) return { ...base, kind: "switch-beside-mode", mode, clouds: clouds(on) };
|
|
201
|
+
if (mode === "cloud" && on.length > 1) return { ...base, kind: "two-clouds", mode, clouds: clouds(on) };
|
|
202
|
+
if (mode === "cloud" && !on.length) {
|
|
203
|
+
return { ...base, kind: "no-cloud", mode, clouds: clouds(Object.keys(CLOUD_SWITCH)), gateway: "ANTHROPIC_BASE_URL" };
|
|
204
|
+
}
|
|
205
|
+
if (!BILLING_MODES.includes(mode)) return { ...base, kind: "not-a-mode", modes: [...BILLING_MODES] };
|
|
206
|
+
}
|
|
207
|
+
return { ...base, kind: "unclassified", mode: BILLING_MODES.includes(mode) ? mode : null };
|
|
208
|
+
}
|
|
209
|
+
|
|
107
210
|
/**
|
|
108
211
|
* The three states an install can be in, as far as running a search goes..
|
|
109
212
|
*
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
// follows, so an MCP tool call can read consumption without dragging the pipeline in.
|
|
26
26
|
|
|
27
27
|
import { appendFileSync, readFileSync, readdirSync } from "node:fs";
|
|
28
|
-
import { join } from "node:path";
|
|
28
|
+
import { join } from "node:path"; import { studioDirFor } from "../shared/pre-rename-spellings.mjs";
|
|
29
29
|
|
|
30
30
|
/** Where the consumption ledger sits: beside the matter ledger, in the studio dir. */
|
|
31
31
|
export function consumptionLedgerPath(studioRoot) {
|
|
@@ -158,7 +158,7 @@ export function accountConsumption({ workspaceRoot, account, now = Date.now() })
|
|
|
158
158
|
|
|
159
159
|
const rows = [];
|
|
160
160
|
for (const ws of workspaces) {
|
|
161
|
-
const studio = join(workspaceRoot, ws
|
|
161
|
+
const studio = studioDirFor(join(workspaceRoot, ws));
|
|
162
162
|
try {
|
|
163
163
|
for (const line of readFileSync(consumptionLedgerPath(studio), "utf8").split("\n")) {
|
|
164
164
|
if (!line.trim()) continue;
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"the baseline tracks named elements, and a rename is a new name. Regenerate rather than work around it.",
|
|
12
12
|
"Measured 139 of 287 declared elements."
|
|
13
13
|
],
|
|
14
|
-
"total":
|
|
14
|
+
"total": 104,
|
|
15
15
|
"byStage": {
|
|
16
16
|
"matter-frame": [
|
|
17
17
|
"### Intake asks line shape — rendered by the driver from intake_asks[]",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"Scope reasoning — search-wide/cite-narrow, the in-scope-by-reach routes, and the reopen trigger behind each exclusion",
|
|
25
25
|
"search_channels — the domains where real use of THIS matter's goods would show"
|
|
26
26
|
],
|
|
27
|
-
"
|
|
27
|
+
"clearance-variants": [
|
|
28
28
|
"### Scope ledger rows — {Layer, Item, Status: applied|dropped, Reason, Reopen trigger} across variant / field / source / jurisdiction",
|
|
29
29
|
"Archetype — primary (one of six) + modifiers + one-line reasoning",
|
|
30
30
|
"Cross-mark themes — shared elements, shared conceptual themes, shared industry-incumbent alerts (multi-mark requests)",
|
|
@@ -84,7 +84,6 @@
|
|
|
84
84
|
"the dictated entry list — qid, predicate, terms, owner, nice_classes, regions, when-guard, expected_kind, covered_by"
|
|
85
85
|
],
|
|
86
86
|
"placement-inquiry": [
|
|
87
|
-
"mark / owner / records / territories / classes on a SELECTED row",
|
|
88
87
|
"retract: <row_id> — withdrawing a seat row already on the form",
|
|
89
88
|
"return payload — the absolute output path plus a 2-3 line summary",
|
|
90
89
|
"select — one record URI of the register candidate being placed",
|
|
@@ -94,8 +93,6 @@
|
|
|
94
93
|
"register-digest": [
|
|
95
94
|
"## Summary counts — total queries executed (search + detail-fetch), enumerated records across N axes, crowd-descriptor count, candidates past the gate, surfaced count, open-verification-flag count",
|
|
96
95
|
"Audit trail — per-unit search/detail-fetch counts, per-jurisdiction `_query` attribution",
|
|
97
|
-
"INSTRUCTED CHECKS — the answer to each requester ask the register owns",
|
|
98
|
-
"adopt-or-override each placement by engaging its reason, and the `### Disagreement resolutions` rows (one per surfaced disagreement and per borderline:true, each ADOPTED/OVERRODE in writing)",
|
|
99
96
|
"return payload — the absolute output path plus a 2-3 line summary (counts + the path of the file written)",
|
|
100
97
|
"rolled-up coverage judgment — `sufficient: <true|false>`",
|
|
101
98
|
"source attribution — the register name tagged on each record, plus the EUIPO `environment` word",
|
|
@@ -111,10 +111,10 @@ export function grantedToolsFor(stage) {
|
|
|
111
111
|
//
|
|
112
112
|
// SIX OF THE TEN ARE ONE SUB-CLASS NOBODY HAD NAMED: SHARED DOCTRINE, DIVERGENT GRANTS. A skill file is
|
|
113
113
|
// served whole to several stages whose grants differ, so the same sentence is a correct instruction to
|
|
114
|
-
// one seat and an order for a tool the next seat does not hold. `
|
|
115
|
-
// register-unit and register-digest; `
|
|
116
|
-
// `
|
|
117
|
-
//
|
|
114
|
+
// one seat and an order for a tool the next seat does not hold. `clearance-register/SKILL.md` goes to
|
|
115
|
+
// register-unit and register-digest; `clearance-search/phase2-execution.md` goes to skeptic;
|
|
116
|
+
// `clearance-search/synthesis-rules.md` goes to synthesis AND report-overview. report-overview and
|
|
117
|
+
// clearance-variants are tool-free BY DESIGN, each with its reason written out in TOOL_FREE_STAGES;
|
|
118
118
|
// skeptic has since CONVERTED to the RECORDING category (its reason moved to RECORDING_STAGES) and
|
|
119
119
|
// holds exactly its own record tool — still no retrieval tool, so its entries below reproduce
|
|
120
120
|
// unchanged. Each of the three is currently served a document telling it to run a lookup.
|
|
@@ -124,31 +124,31 @@ export function grantedToolsFor(stage) {
|
|
|
124
124
|
// only shrink. The test asserts every entry still reproduces, so a pair fixed in fails CI here
|
|
125
125
|
// until its line is deleted.
|
|
126
126
|
export const TOOL_ORDER_BACKLOG = [
|
|
127
|
-
{ stage: "register-digest", tool: "register_enumerate", site: "driver/skills/
|
|
127
|
+
{ stage: "register-digest", tool: "register_enumerate", site: "driver/skills/clearance-register/SKILL.md",
|
|
128
128
|
closes: "#865 — shared doctrine: SKILL.md is served to register-unit (holds register) and register-digest "
|
|
129
129
|
+ "(holds band only, since the plan freeze retired live search from the judgment seat)." },
|
|
130
|
-
{ stage: "register-digest", tool: "register_execute_plan", site: "driver/skills/
|
|
130
|
+
{ stage: "register-digest", tool: "register_execute_plan", site: "driver/skills/clearance-register/SKILL.md",
|
|
131
131
|
closes: "#865 — same shared file, same split grant." },
|
|
132
|
-
{ stage: "register-digest", tool: "register_batch_screen", site: "driver/skills/
|
|
132
|
+
{ stage: "register-digest", tool: "register_batch_screen", site: "driver/skills/clearance-register/digest.md",
|
|
133
133
|
closes: "#865 — the digest's OWN doctrine, not a shared file: this one is the stage being told to "
|
|
134
134
|
+ "batch-screen with a tool its grant does not carry. gather-config.mjs:196 already records that "
|
|
135
135
|
+ "this stage's prompt once ordered live register checks; the order outlived the note." },
|
|
136
|
-
{ stage: "register-unit", tool: "band_record", site: "driver/skills/
|
|
136
|
+
{ stage: "register-unit", tool: "band_record", site: "driver/skills/clearance-register/SKILL.md",
|
|
137
137
|
closes: "#865 — same shared file, same split grant." },
|
|
138
|
-
{ stage: "register-unit", tool: "band_shape", site: "driver/skills/
|
|
138
|
+
{ stage: "register-unit", tool: "band_shape", site: "driver/skills/clearance-register/SKILL.md",
|
|
139
139
|
closes: "#865 — same shared file, same split grant." },
|
|
140
|
-
{ stage: "report-overview", tool: "band_record", site: "driver/skills/
|
|
140
|
+
{ stage: "report-overview", tool: "band_record", site: "driver/skills/clearance-search/synthesis-rules.md",
|
|
141
141
|
closes: "#865 — same shared file, same split grant." },
|
|
142
|
-
{ stage: "register-unit", tool: "band_lookup", site: "driver/skills/
|
|
142
|
+
{ stage: "register-unit", tool: "band_lookup", site: "driver/skills/clearance-register/SKILL.md",
|
|
143
143
|
closes: "#865 — the mirror image: the band tools are the judgment stages', and the unit lane holds "
|
|
144
144
|
+ "register instead." },
|
|
145
|
-
{ stage: "register-unit", tool: "record_coverage", site: "driver/skills/
|
|
145
|
+
{ stage: "register-unit", tool: "record_coverage", site: "driver/skills/clearance-register/SKILL.md",
|
|
146
146
|
closes: "#865 — same shared-spine split as the band tools above, minted by the typed coverage "
|
|
147
147
|
+ "transport: the spine's Coverage-ledger section (mode-scoped to DIGEST in its own words) orders "
|
|
148
148
|
+ "`record_coverage`, which only register-digest's grant carries — the unit lane must never hold a "
|
|
149
149
|
+ "writer into judgment's coverage record. Resolved the day the spine's coverage doctrine moves "
|
|
150
150
|
+ "wholly into digest.md, or #865 scopes shared-spine text per seat." },
|
|
151
|
-
{ stage: "register-unit", tool: "record_register_digest", site: "driver/skills/
|
|
151
|
+
{ stage: "register-unit", tool: "record_register_digest", site: "driver/skills/clearance-register/SKILL.md",
|
|
152
152
|
closes: "#865 — the SAME shared-spine split as record_coverage above, minted by conversion 11's typed "
|
|
153
153
|
+ "findings transport. The spine's mode list names the tool inside its **Digest mode (judgment — "
|
|
154
154
|
+ "Layer B)** bullet, which is the sentence that already names record_coverage and the band tools; "
|
|
@@ -157,20 +157,20 @@ export const TOOL_ORDER_BACKLOG = [
|
|
|
157
157
|
+ "spine's digest doctrine moves wholly into digest.md, or #865 scopes shared-spine text per seat — "
|
|
158
158
|
+ "and NOT by granting it: the funnel must never hold a writer into judgment's findings document, "
|
|
159
159
|
+ "which is the same rule that keeps record_coverage off its grant." },
|
|
160
|
-
{ stage: "skeptic", tool: "perplexity_research", site: "driver/skills/
|
|
160
|
+
{ stage: "skeptic", tool: "perplexity_research", site: "driver/skills/clearance-search/phase2-execution.md",
|
|
161
161
|
closes: "#865 — skeptic holds NO retrieval tool ('new search work enters via the escalation lane, never "
|
|
162
162
|
+ "from this seat' — it converted to the RECORDING category, gaining record_skeptic plus the "
|
|
163
163
|
+ "read-only, run-dir-scoped search_run_artifacts, and no retrieval tool) "
|
|
164
164
|
+ "and is served a document ordering a live query." },
|
|
165
|
-
{ stage: "skeptic", tool: "register_propose_supplemental", site: "driver/skills/
|
|
165
|
+
{ stage: "skeptic", tool: "register_propose_supplemental", site: "driver/skills/clearance-search/phase2-execution.md",
|
|
166
166
|
closes: "#865 — same seat, same file, the supplemental mint it cannot call." },
|
|
167
|
-
{ stage: "report-overview", tool: "perplexity_research", site: "driver/skills/
|
|
167
|
+
{ stage: "report-overview", tool: "perplexity_research", site: "driver/skills/clearance-search/synthesis-rules.md",
|
|
168
168
|
closes: "#865 — synthesis-rules.md is served to synthesis (holds perplexity + band) and to "
|
|
169
169
|
+ "report-overview (TOOL-FREE: 'renders the shell from the settled narrative + findings')." },
|
|
170
|
-
{ stage: "report-overview", tool: "band_lookup", site: "driver/skills/
|
|
170
|
+
{ stage: "report-overview", tool: "band_lookup", site: "driver/skills/clearance-search/synthesis-rules.md",
|
|
171
171
|
closes: "#865 — same shared file, same split grant." },
|
|
172
|
-
{ stage: "
|
|
173
|
-
closes: "#865 —
|
|
172
|
+
{ stage: "clearance-variants", tool: "perplexity_research", site: "driver/skills/clearance-variants/SKILL.md",
|
|
173
|
+
closes: "#865 — clearance-variants is TOOL-FREE by design ('pure reasoning over material already on "
|
|
174
174
|
+ "disk') and its own doctrine names a research call." },
|
|
175
175
|
];
|
|
176
176
|
|