clearotron 0.5.0-beta.2 → 0.5.0-beta.4
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 +7 -0
- package/build-info.json +2 -2
- package/docs/architecture/03-run-lifecycle.md +6 -0
- package/docs/architecture/04-configuration-reference.md +1 -0
- package/docs/architecture/05-config-governance.md +1 -1
- package/driver/CHANGELOG.md +21 -0
- package/driver/band-shape.mjs +19 -11
- package/driver/contract-vocabulary.mjs +3 -3
- package/driver/coverage-form-io.mjs +3 -1
- package/driver/coverage-form.mjs +21 -2
- package/driver/coverage-ledger.mjs +7 -1
- package/driver/declination-call.mjs +33 -16
- package/driver/degraded-parts.mjs +6 -0
- package/driver/engine/mcp/band-server.mjs +12 -12
- package/driver/engine/mcp/clarivate-server.mjs +2 -0
- package/driver/engine/mcp/codex-config.mjs +12 -7
- package/driver/engine/mcp/corsearch-server.mjs +2 -0
- package/driver/engine/mcp/declination-server.mjs +4 -5
- package/driver/engine/mcp/dispositions-server.mjs +7 -0
- package/driver/engine/mcp/euipo-server.mjs +2 -0
- package/driver/engine/mcp/free-tier-server.mjs +2 -0
- package/driver/engine/mcp/gather-config.mjs +15 -0
- package/driver/engine/mcp/held-answers.mjs +11 -3
- package/driver/engine/mcp/perplexity-server.mjs +29 -1
- package/driver/engine/mcp/recording-server.mjs +16 -1
- package/driver/engine/mcp/signa-server.mjs +2 -0
- package/driver/engine/mcp/supplemental.mjs +11 -3
- package/driver/engine/mcp/uspto-local-server.mjs +2 -0
- package/driver/engine/openai-agent.mjs +48 -9
- package/driver/envelope-settle.mjs +13 -3
- package/driver/findings-model.mjs +17 -0
- package/driver/gateway.mjs +31 -10
- package/driver/package.json +1 -1
- package/driver/parts-not-completed.mjs +52 -11
- package/driver/pipeline-knockout.mjs +5 -4
- package/driver/pipeline.mjs +474 -81
- package/driver/placement-decisions.mjs +24 -9
- package/driver/placement-form-io.mjs +21 -1
- package/driver/placement-form.mjs +25 -15
- package/driver/placement-union.mjs +53 -8
- package/driver/predelivery-lint.mjs +8 -1
- package/driver/publish/index.mjs +7 -3
- package/driver/register-digest-record.mjs +6 -3
- package/driver/research-answers.mjs +54 -7
- package/driver/runner.mjs +4 -4
- package/driver/saved-findings-block.mjs +36 -0
- package/driver/skills/clearance-register/digest.md +1 -1
- package/driver/skills/clearance-search/phase2-execution.md +7 -5
- package/driver/skills/clearance-search/synthesis-rules.md +3 -3
- package/driver/skills/placement-inquiry/SKILL.md +3 -3
- package/driver/stage-context.mjs +18 -0
- package/driver/stages.mjs +41 -13
- package/driver/suite-census.json +140 -14
- package/driver/synthesis-record.mjs +167 -1
- package/driver/verify.mjs +6 -6
- package/mcp-server/CHANGELOG.md +8 -0
- package/mcp-server/package.json +1 -1
- package/package.json +1 -1
- package/portal-ui/package.json +1 -1
- package/providers/_shared/README.md +1 -0
- package/providers/_shared/enumerate.mjs +4 -3
- package/providers/_shared/execute-plan.mjs +33 -7
- package/providers/_shared/send-until.mjs +25 -0
- package/providers/oauth-mcp-bridge/CHANGELOG.md +8 -0
- package/providers/oauth-mcp-bridge/package.json +1 -1
- package/scripts/band-shape-probe.mjs +1 -1
- package/scripts/e2e-first-time.mjs +2 -1
- package/scripts/release-notes-lint.mjs +1 -1
- package/shared/inside-run.mjs +54 -0
- package/shared/names-in-force.mjs +1 -0
- package/shared/slices-taken-out.mjs +65 -0
- package/skills/clearotron-account/SKILL.md +1 -1
- package/skills/clearotron-ops/SKILL.md +1 -1
|
@@ -17,35 +17,40 @@
|
|
|
17
17
|
//
|
|
18
18
|
// ONCE PER PART. The catch never writes a part whose record already exists: a failure on the pass that delivers
|
|
19
19
|
// without it ends the run as it always did, with the stop notice, and the record is removed then, so a later resume
|
|
20
|
-
// tries the part again.
|
|
20
|
+
// tries the part again. The searches are the one part whose record grows: each failure names the slices it could not
|
|
21
|
+
// prove ran, and a failure that names a slice the record does not hold yet adds it; one that names none new ends the
|
|
22
|
+
// run, so the run still ends.
|
|
21
23
|
//
|
|
22
|
-
// A pure leaf: node:fs, node:path
|
|
24
|
+
// A pure leaf: node:fs, node:path, shared/driver-dir.mjs and shared/slices-taken-out.mjs (node:fs and the same) only.
|
|
23
25
|
import { readFileSync, writeFileSync, renameSync, rmSync, readdirSync } from "node:fs";
|
|
24
26
|
import { join } from "node:path";
|
|
25
27
|
import { driverDir, ensureDriverDir } from "../shared/driver-dir.mjs";
|
|
28
|
+
// Where the record sits is stated with the band readers outside the driver, which read the searches' record too.
|
|
29
|
+
import { NOT_COMPLETED_DIR, notCompletedPath } from "../shared/slices-taken-out.mjs";
|
|
26
30
|
|
|
27
|
-
export
|
|
31
|
+
export { NOT_COMPLETED_DIR, notCompletedPath };
|
|
28
32
|
|
|
29
33
|
// The covered parts. `assessment` is the run's overall assessment: placement, the register write-up and synthesis, and
|
|
30
34
|
// everything built from them. `review` is the first review of the assessment, whose verdict the sign-off is. `overview`
|
|
31
35
|
// is the report overview, the conclusion under the rating. `delivery` is the
|
|
32
36
|
// changed-material check before publishing: it never delivers past staleness, and its record buys the report one more
|
|
33
|
-
// assembly from the current material instead of the stop notice.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
37
|
+
// assembly from the current material instead of the stop notice. `searches` is the register's searches: the slices a
|
|
38
|
+
// check could not prove ran, each with its axis, its qid and the reason it is open, taken out of the band and
|
|
39
|
+
// delivered as open rows; the axes whose pass was killed at its time limit, read as the last pass left them and
|
|
40
|
+
// disclosed, their clean claims open (`disclosed_axes`); and the units that wrote no result once their attempts were
|
|
41
|
+
// spent, delivered as their bands stand and not sent again (`unfinished_units`).
|
|
42
|
+
export const NOT_COMPLETED_PARTS = Object.freeze(["assessment", "review", "overview", "delivery", "searches"]);
|
|
40
43
|
|
|
41
44
|
/**
|
|
42
45
|
* Record that `part` could not be completed. `stage` is the stage that failed, `reason` its cause for the run's record
|
|
43
46
|
* (never a reader's cell), `sig` and `terminalKind` what the recovery decision said. Written through a temporary file
|
|
44
47
|
* and a rename, so a reader never sees half a record. Returns the record.
|
|
45
48
|
*/
|
|
46
|
-
export function writePartNotCompleted(runDir, part, { stage = null, reason = null, sig = null, terminalKind = null } = {}) {
|
|
49
|
+
export function writePartNotCompleted(runDir, part, { stage = null, reason = null, sig = null, terminalKind = null, slices = null, disclosedAxes = null, unfinishedUnits = null } = {}) {
|
|
47
50
|
if (!NOT_COMPLETED_PARTS.includes(part)) throw new Error(`parts-not-completed: "${part}" is not a covered part`);
|
|
48
51
|
const record = { part, stage, reason: reason == null ? null : String(reason).slice(0, 600), sig, terminalKind,
|
|
52
|
+
...(Array.isArray(slices) ? { slices } : {}), ...(Array.isArray(disclosedAxes) && disclosedAxes.length ? { disclosed_axes: disclosedAxes } : {}),
|
|
53
|
+
...(Array.isArray(unfinishedUnits) && unfinishedUnits.length ? { unfinished_units: unfinishedUnits } : {}),
|
|
49
54
|
ts: new Date().toISOString() };
|
|
50
55
|
const path = notCompletedPath(runDir, part);
|
|
51
56
|
ensureDriverDir(runDir, NOT_COMPLETED_DIR);
|
|
@@ -76,6 +81,42 @@ export function partsNotCompleted(runDir) {
|
|
|
76
81
|
return NOT_COMPLETED_PARTS.filter((p) => names.includes(`${p}.json`)).map((p) => readPartNotCompleted(runDir, p));
|
|
77
82
|
}
|
|
78
83
|
|
|
84
|
+
/**
|
|
85
|
+
* The slices of `failed` that `record` does not hold yet, each `{axis, qid, reason}`, or `{axis, query, reason}` for a
|
|
86
|
+
* slice with no qid, which its query names: what a failure of the searches adds to their record. [] when it adds
|
|
87
|
+
* none. PURE.
|
|
88
|
+
*/
|
|
89
|
+
export function slicesNotYetRecorded(record, failed) {
|
|
90
|
+
const keyOf = (s) => `${s?.axis}\u0000${s?.qid ? `qid:${s.qid}` : `query:${s?.query}`}`;
|
|
91
|
+
const held = new Set((Array.isArray(record?.slices) ? record.slices : []).map(keyOf));
|
|
92
|
+
const out = [];
|
|
93
|
+
for (const s of Array.isArray(failed) ? failed : []) {
|
|
94
|
+
if (!s?.axis || (!s?.qid && !s?.query) || held.has(keyOf(s))) continue;
|
|
95
|
+
held.add(keyOf(s));
|
|
96
|
+
out.push(s.qid ? { axis: String(s.axis), qid: String(s.qid), reason: String(s.reason ?? "") }
|
|
97
|
+
: { axis: String(s.axis), query: String(s.query), reason: String(s.reason ?? "") });
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* The axes of `failed` that `record` does not list as disclosed yet: a pass on each was killed at its time limit and its
|
|
104
|
+
* recovery is spent, so the delivering pass reads its band as it stands and discloses it. [] when it adds none. PURE.
|
|
105
|
+
*/
|
|
106
|
+
export function axesNotYetDisclosed(record, failed) {
|
|
107
|
+
const held = new Set(Array.isArray(record?.disclosed_axes) ? record.disclosed_axes : []);
|
|
108
|
+
return [...new Set((Array.isArray(failed) ? failed : []).map((a) => String(a ?? "").trim()).filter((a) => a && !held.has(a)))];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* The units of `failed` that `record` does not list as unfinished yet: each wrote no result once its attempts were spent,
|
|
113
|
+
* so the delivering pass takes it as its band stands instead of sending it again. [] when it adds none. PURE.
|
|
114
|
+
*/
|
|
115
|
+
export function unitsNotYetRecorded(record, failed) {
|
|
116
|
+
const held = new Set(Array.isArray(record?.unfinished_units) ? record.unfinished_units : []);
|
|
117
|
+
return [...new Set((Array.isArray(failed) ? failed : []).map((a) => String(a ?? "").trim()).filter((a) => a && !held.has(a)))];
|
|
118
|
+
}
|
|
119
|
+
|
|
79
120
|
/** Remove one part's record, once that part has completed after all. */
|
|
80
121
|
export function clearPartNotCompleted(runDir, part) {
|
|
81
122
|
try { rmSync(notCompletedPath(runDir, part), { force: true }); } catch { /* none */ }
|
|
@@ -64,7 +64,7 @@ import { writeRunStatus, readRunStatus, rollupStatus, atomicWrite, identitySeed
|
|
|
64
64
|
import { batchMarkName } from "./mark-name.mjs";
|
|
65
65
|
import { runLog, note, outputMeta } from "./log.mjs";
|
|
66
66
|
import { defaultTerritoryState } from "./effective-scope.mjs"; // the stored-defaults reading — one producer, shared with the clearance lane
|
|
67
|
-
import {
|
|
67
|
+
import { whatsappRouting } from "./stages.mjs";
|
|
68
68
|
import { writeOutboxPacket } from "./outbox.mjs";
|
|
69
69
|
import { rollupTokens, stampTokenRollup } from "./tokens.mjs";
|
|
70
70
|
import { recordRunConsumption } from "./consumption-ledger.mjs";
|
|
@@ -1205,8 +1205,9 @@ export async function knockoutInner(ctx, job, opts = {}) {
|
|
|
1205
1205
|
// two existing. Where no number is held the packet now SAYS so in `whatsappToReason` rather than
|
|
1206
1206
|
// substituting the operator silently.
|
|
1207
1207
|
//
|
|
1208
|
-
// The failure notice below
|
|
1209
|
-
//
|
|
1208
|
+
// The failure notice below routes the same way (buildFailurePacket). It used to keep `AGENT_WHATSAPP[agent]` as an
|
|
1209
|
+
// operational page, but the courier relays it to the requester, who is owed it as they are owed a report, and the
|
|
1210
|
+
// operator keeps the page as the copy beside it.
|
|
1210
1211
|
...whatsappRouting(job, agent),
|
|
1211
1212
|
// ONE LINE, N LINKS. This said "Report: <one url>" and on a batch that url is now null, which would
|
|
1212
1213
|
// have read "Report: null" — the fail-visible shape doing its job, and still not a line to send. A
|
|
@@ -1350,7 +1351,7 @@ export async function knockoutInner(ctx, job, opts = {}) {
|
|
|
1350
1351
|
try {
|
|
1351
1352
|
const rich = buildFailurePacket({
|
|
1352
1353
|
runId, agent, job, failedStage, shortReason, terminalKind,
|
|
1353
|
-
reasonVerbatim: String(reason).slice(0, 1000),
|
|
1354
|
+
reasonVerbatim: String(reason).slice(0, 1000),
|
|
1354
1355
|
});
|
|
1355
1356
|
const packet = {
|
|
1356
1357
|
kind: "run-failed", ...rich,
|