@ceccec/millennium-solutions 9.8.2 → 9.8.3

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.
Files changed (52) hide show
  1. package/README.md +104 -69
  2. package/dist/data/baked/answer_gate.json +1 -0
  3. package/dist/data/baked/answer_verify_arith.json +1 -0
  4. package/dist/data/baked/answer_verify_arxiv.json +1 -0
  5. package/dist/data/baked/anti_fake.json +1 -0
  6. package/dist/data/baked/api_gates.json +1 -0
  7. package/dist/data/baked/apis_guru_cross.json +1 -0
  8. package/dist/data/baked/apis_guru_gaps.json +1 -0
  9. package/dist/data/baked/apis_theorems.json +1 -0
  10. package/dist/data/baked/coils.json +1 -0
  11. package/dist/data/baked/constants_check.json +1 -0
  12. package/dist/data/baked/contradictions.json +1 -0
  13. package/dist/data/baked/discover.json +1 -0
  14. package/dist/data/baked/discoveries.json +1 -0
  15. package/dist/data/baked/entanglements.json +1 -0
  16. package/dist/data/baked/evidence.json +1 -0
  17. package/dist/data/baked/hexbit_route.json +1 -0
  18. package/dist/data/baked/index.json +41 -0
  19. package/dist/data/baked/leads.json +1 -0
  20. package/dist/data/baked/leaks.json +1 -0
  21. package/dist/data/baked/memory_check.json +1 -0
  22. package/dist/data/baked/memory_derive.json +1 -0
  23. package/dist/data/baked/metrics_face.json +1 -0
  24. package/dist/data/baked/package_gates.json +1 -0
  25. package/dist/data/baked/prefix_check.json +1 -0
  26. package/dist/data/baked/prose_check.json +1 -0
  27. package/dist/data/baked/qpu_court_local.json +1 -0
  28. package/dist/data/baked/qpu_families.json +1 -0
  29. package/dist/data/baked/recompute.json +1 -0
  30. package/dist/data/baked/session_report.json +1 -0
  31. package/dist/data/baked/theorem_only.json +1 -0
  32. package/dist/data/baked/trinity.json +1 -0
  33. package/dist/data/discovered.json +480 -0
  34. package/dist/data/formulas.jsonld +27809 -25985
  35. package/dist/mcp.bin.js +18 -1
  36. package/dist/src/0/index.d.ts +1 -0
  37. package/dist/src/0/index.js +7 -8
  38. package/dist/src/factor/index.d.ts +58 -0
  39. package/dist/src/factor/index.js +209 -0
  40. package/dist/src/factor/verify.d.ts +18 -0
  41. package/dist/src/factor/verify.js +28 -0
  42. package/dist/src/mcp/index.d.ts +3602 -110
  43. package/dist/src/mcp/index.js +141 -4
  44. package/dist/src/mcp/serve.d.ts +12 -2
  45. package/dist/src/mcp/serve.js +71 -6
  46. package/dist/src/mcp/suites.d.ts +1 -0
  47. package/dist/src/mcp/suites.js +14 -0
  48. package/dist/src/mirror/index.d.ts +18 -0
  49. package/dist/src/mirror/index.js +37 -0
  50. package/dist/src/policy/index.d.ts +8 -0
  51. package/dist/src/policy/index.js +23 -0
  52. package/package.json +19 -4
@@ -1,3 +1,4 @@
1
+ import { SUITES } from './suites.js';
1
2
  export const WRITES = new Set(['lean_seal', 'lean_generate', 'pages', 'ledger_trial']);
2
3
  export const TOOLS = [
3
4
  { name: 'novelty', description: 'Run this deposit\'s own prior-art search against any statement: zbMATH, OpenAlex, Crossref, arXiv, and the OEIS for any integer sequence in it. Returns the verdict vocabulary the record uses — CANDIDATES | NONE_FOUND | NONE_FOUND_PARTIAL | NOT_MEASURED | TOO_FEW_TERMS — with the queries sent, the hits, and THE FLOORS APPLIED (relevance ≥ 0.6 over the first 5 results per source), because a verdict cannot be read apart from the domain that made it. NONE_FOUND means "these searches, on this date, returned nothing" and never "nothing earlier exists": a keyword search misses what it does not name. Writes nothing.',
@@ -5,9 +6,9 @@ export const TOOLS = [
5
6
  { name: 'coils', description: 'The cross formulas, clustered: every expression in the deposit\'s vocabulary evaluated at every point of a grid and grouped by the resulting vector. Two expressions in one coil prove each other — compute either and the other is computed. Returns the coils, the pair count, and the expressions that coil with NOTHING, which are the ones prose must never interchange.',
6
7
  inputSchema: { type: 'object', properties: {}, required: [] } },
7
8
  { name: 'discoveries', description: 'Where the next prior-art search should go, consolidating the generators: which theorems sit in files declaring their own work, which have no search recorded, which families are at octave scale. A RANK IS NOT A NOVELTY CLAIM — this orders a queue, and only a performed search can say whether a statement has an earlier author. Reports the coverage, which is the finding: novelty in this tree is measured for a few per cent of it.',
8
- inputSchema: { type: 'object', properties: { limit: { type: 'number' } }, required: [] } },
9
+ inputSchema: { type: 'object', properties: { cursor: { type: 'number', description: 'the next cursor from the previous page; omit for the first page' }, limit: { type: 'number' } }, required: [] } },
9
10
  { name: 'formulas', description: 'Every formula this deposit decides, as data: the proposition the Lean kernel accepted, character for character, with its file, namespace, wing, tactic and ledger key. Filter by any of them. Nothing summarised and nothing authored.',
10
- inputSchema: { type: 'object', properties: { wing: { type: 'string' }, file: { type: 'string' }, contains: { type: 'string' }, limit: { type: 'number' } }, required: [] } },
11
+ inputSchema: { type: 'object', properties: { cursor: { type: 'number', description: 'the next cursor from the previous page; omit for the first page' }, wing: { type: 'string' }, file: { type: 'string' }, contains: { type: 'string' }, limit: { type: 'number' } }, required: [] } },
11
12
  { name: 'handle', description: 'The SHORT FORM: the first four hex of an address, plus the message, determine the whole address — so nothing but the message ever travels. Pass text to mint a handle; pass handle AND text to resolve one. ROUTES and REJECTS, never identifies: 16 bits over 2912 sealed receipts collide 71 times (birthday expectation 64.7), and the collision-free minimum today is 7 hex. The window is the FRONT four hex because hex 12..16 and 16..20 overlap the forced version/variant bits and carry less — and hex 12..16 is the third dash-group of the display form, the one an eye would reach for.',
12
13
  inputSchema: { type: 'object', properties: { text: { type: 'string' }, handle: { type: 'string' } }, required: ['text'] } },
13
14
  { name: 'content_address', description: 'Content-address (uuid) any text — INTEGRITY/provenance, NOT encryption or proof.',
@@ -34,6 +35,30 @@ export const TOOLS = [
34
35
  inputSchema: { type: 'object', properties: {}, required: [] } },
35
36
  { name: 'lean_verify', description: 'Compile every Lean file and audit it per theorem: #print axioms on each, hygiene (no sorry / native_decide outside comments), theorem counts. Fails if any file carries an axiom or does not compile. This is the gate every seal depends on.',
36
37
  inputSchema: { type: 'object', properties: { file: { type: 'string', description: 'optional single file to verify' } }, required: [] } },
38
+ { name: 'lean_audit_library', description: 'Audit every theorem a Lean library declares, not only the ones a tool serves: build the library, then for each module check that it compiles, carries no sorry, and that each theorem is axiom-free or uses only the standard axioms (propext, Quot.sound). Reports any custom axiom or failure by name.',
39
+ inputSchema: { type: 'object', properties: { project: { type: 'string', description: 'the Lake project directory' }, src: { type: 'string', description: 'the library source root, relative to the project' }, prefix: { type: 'string', description: 'the module prefix, e.g. Qpu' } }, required: ['project', 'src', 'prefix'] } },
40
+ { name: 'web_search', description: 'Search a free public index — wikipedia, openalex or arxiv — and return its hits: title, address, and the snippet it returned. A NONE result means the index returned nothing for that query on this date, never that nothing exists. Use it for online answers through the MCP.',
41
+ inputSchema: { type: 'object', properties: { source: { type: 'string', enum: ['wikipedia', 'openalex', 'arxiv'] }, query: { type: 'string' }, limit: { type: 'number', description: '1 to 10, default 5' } }, required: ['source', 'query'] } },
42
+ { name: 'clay_conditions', description: 'Test the three conditions CMI sets before it considers a proposed solution (publication in a Qualifying Outlet under §6, two years since publication, general acceptance), one verdict each, MET or NOT MET with the reason. The §6(e) and §6(f) text is read from the live rules PDF through web_fetch first. With no evidence record every condition is NOT MET.',
43
+ inputSchema: { type: 'object', properties: {}, required: [] } },
44
+ { name: 'web_fetch', description: 'Read one public http(s) page and return only the passages that match a case-insensitive pattern, each with context, and the content address of the fetched body. Use it for online answers through the MCP. The passages are the page as fetched now; nothing is checked against another source.',
45
+ inputSchema: { type: 'object', properties: { url: { type: 'string' }, pattern: { type: 'string', description: 'regular expression, case-insensitive' }, window: { type: 'number', description: 'characters of context on each side, 20 to 600, default 160' }, raw: { type: 'boolean', description: 'match the HTML itself, so href links can be found' } }, required: ['url', 'pattern'] } },
46
+ { name: 'lean_split', description: 'Break one large Lean statement into smaller questions and answer each yes or no. The statement must be a conjunction A ∧ B ∧ ...; it is split at its top level, each conjunct becomes its own theorem, and lean_ask answers each one. The whole holds only when every part does. The answer names which part failed and why.',
47
+ inputSchema: { type: 'object', properties: { source: { type: 'string', description: 'Lean source whose last theorem has a conjunction as its statement' } }, required: ['source'] } },
48
+ { name: 'task_route', description: 'Paste anything. An integer is classified and checked: trial division, then a Miller–Rabin test. Composite answers come with a proof (a witness or an exact product check); probable primes are labelled probable, not proved. Factors are returned only when the product check passes; large factorisation is not attempted. Text is returned unrouted, with the tools that can take it.',
49
+ inputSchema: { type: 'object', properties: { input: { type: 'string', description: 'the pasted number or text' } }, required: ['input'] } },
50
+ { name: 'run_suite', description: 'Run one named test suite through the server and return its verdict: PASS, FAIL, or SKIPPED (skipped by the environment, never a pass). Suites are an allowlist: mcp-gate, hardcode-gate, mcp-check, net-tools-test, clay-conditions, clay-conditions-self-test, environment.',
51
+ inputSchema: { type: 'object', properties: { suite: { type: 'string', enum: Object.keys(SUITES) } }, required: ['suite'] } },
52
+ { name: 'stall_check', description: 'Flag submitted text that says the next step is unknown, by phrase match on each line. It reads only the text it is given. It cannot see reasoning that was not written down, and no match does not mean the author is not stalled.',
53
+ inputSchema: { type: 'object', properties: { text: { type: 'string', description: 'the text to check' } }, required: ['text'] } },
54
+ { name: 'session_report', description: 'Report the calls this server served in its log: how many, by tool and by status, first and last, and total time. It counts only this server\'s calls. A client reports its own token spend; the server cannot see it.',
55
+ inputSchema: { type: 'object', properties: {}, required: [] } },
56
+ { name: 'git_commit_paths', description: 'Commit only the named files of an allowlisted repository (millennium or qpu) through its own hooks. The hooks run and are never bypassed: a hook that refuses refuses the commit, and the named paths are unstaged again. Pathspec only: nothing else staged enters the commit. Never pushes, amends, or rewrites history.',
57
+ inputSchema: { type: 'object', properties: { repo: { type: 'string', enum: ['millennium', 'qpu'] }, message: { type: 'string', description: 'the commit message; its first line is the subject' }, paths: { type: 'array', items: { type: 'string' }, description: 'the files to commit, relative to the repository' } }, required: ['repo', 'message', 'paths'] } },
58
+ { name: 'answer', description: 'Answer one question with TRUE, FALSE, SOURCED, or UNKNOWN. The question is routed by kind: an integer goes to the arithmetic verifier (TRUE or FALSE from an exact witness), a Lean theorem to the kernel (TRUE only when it compiles with no sorry and no axiom), a DOI to the record resolver (SOURCED only for the canonical record), a Clay problem or other text to UNKNOWN with its reason. Every TRUE or FALSE carries its certificate.',
59
+ inputSchema: { type: 'object', properties: { question: { type: 'string', description: 'an integer, a Lean theorem, a DOI, or a question' } }, required: ['question'] } },
60
+ { name: 'lean_ask', description: 'Answer one Lean question from its source: does it compile, does it use sorry, and which axioms each theorem in it depends on. Compiles in a temporary directory, never in the tree, with the toolchain pinned in lean-toolchain. Answers ABSENT when the Lean toolchain is not on PATH.',
61
+ inputSchema: { type: 'object', properties: { source: { type: 'string', description: 'the Lean source to answer about' } }, required: ['source'] } },
37
62
  { name: 'lean_seal', description: 'Seal every compiled, axiom-free Lean theorem into the ledger with a chained receipt. ONLY by-decide theorems are sealed — rfl on a declared constant proves the declaration, not a fact. Gated on lean_verify; seals nothing if the layer does not verify. Pass dry=true to report without writing.',
38
63
  inputSchema: { type: 'object', properties: { dry: { type: 'boolean' } }, required: [] } },
39
64
  { name: 'lean_generate', description: 'Generate quantified Lean for ledger families — one theorem subsuming a whole family of per-parameter rows. Five gates: compiles, axiom-free, agrees with the ledger test at every parameter, carries a boundary case, and flags a zero divisor in range. Pass emit=true to write.',
@@ -48,8 +73,59 @@ export const TOOLS = [
48
73
  inputSchema: { type: 'object', properties: { domain: { type: 'string' }, spanningOnly: { type: 'boolean' } } } },
49
74
  { name: 'api_joins', description: 'Ask several independent public services for the SAME entity and report which values two or more of them return — the join DISCOVERED from the data rather than declared. PubChem, ChEMBL and ChEBI all return the InChIKey BSYNRYMUTXBXSQ-UHFFFAOYSA-N for aspirin, at three different paths, from two institutions on two continents. Negative results are reported and are the interesting ones: two plant-naming authorities share no joinable value, which is the problem Kew\'s credential-gated MPNS exists to solve. A JOIN IS NOT A TRUTH — it establishes that two databases mean the same entity, never that either is correct; two services can agree and both be wrong. Reaches the network; writes nothing.',
50
75
  inputSchema: { type: 'object', properties: { probe: { type: 'string', enum: ['drug', 'protein', 'plant', 'paper'] } } } },
76
+ { name: 'leaks', description: 'Measure where runtime temperature (random draws) and time (clock reads, timers) enter the deposit: every site in src/ and scripts/, classified by kind and role, with the cracks that are to be replaced by theorems. Read from the source on each call; nothing is typed.',
77
+ inputSchema: { type: 'object', properties: { json: { type: 'boolean', description: 'true for the inventory as JSON, false or absent for markdown' } }, required: [] } },
78
+ { name: 'cern', description: 'Enumerate the public CERN Open Data corpus through the sitemap that its robots.txt advertises (never the disallowed /api/), address every record, and run the involution check with its control: a non-involution must go red. Writes .cern/ and checks docs/CERN-ENUMERATION.md against the figures measured. Needs the network; takes minutes.',
79
+ inputSchema: { type: 'object', properties: {}, required: [] } },
80
+ { name: 'apis_guru_cross', description: 'Cross-check the APIs.guru catalogue, offline: for each catalogued API, its spec verdict (is the OpenAPI document served and a spec?) read against its live verdict (does its own server answer?). Reports agreements and disagreements. Reads the committed runs; makes no request.', inputSchema: { type: 'object', properties: {}, required: [] } },
81
+ { name: 'api_adapters', description: 'Ask every API adapter in the registry live, one verdict each: PROVEN when the reply contains the fact the adapter states, WRONG when it does not, REFUSED when robots.txt disallows the path, GATED when a key or licence is needed, NOT MEASURED when the host did not answer. Makes network requests, paced one per second per host.', inputSchema: { type: 'object', properties: {}, required: [] } },
82
+ { name: 'apis_guru_gaps', description: 'The APIs.guru catalogue set against the hosts this tree names: gaps are catalogued APIs whose server the code names but no adapter covers; unused are the rest. Offline; reads the committed live run.', inputSchema: { type: 'object', properties: {}, required: [] } },
83
+ { name: 'understand', description: 'Say which route a request belongs to, and say when none does. Returns UNDERSTOOD with the tool and its arguments, or UNDERSTOOD false with the options the server has. Never answers a request with a route it does not match.', inputSchema: { type: 'object', properties: { request: { type: 'string', description: 'the request as written' } }, required: ['request'] } },
84
+ { name: 'contradictions', description: 'The prose of this deposit set against its own Lean proofs: every place a document says what src/proof does not establish. Reads the tree; makes no request. Each finding names the file and line.', inputSchema: { type: 'object', properties: {}, required: [] } },
85
+ { name: 'answer_gate', description: "Refuse stored or emitted answers that break the certificate rules. The rules are kernel-checked Lean; this reads a JSON array of answers and asks the kernel whether each holds.", inputSchema: { "type": "object", "properties": { "answers": { "type": "array" } }, "required": [] } },
86
+ { name: 'answer_verify_arith', description: "The C2 verifier: proposes a factor or a primality proof and asks the Lean kernel whether it holds. TRUE or FALSE only when the kernel accepts it; otherwise UNKNOWN.", inputSchema: { "type": "object", "properties": { "input": { "type": "string", "description": "the integer to decide" } }, "required": [] } },
87
+ { name: 'answer_verify_arxiv', description: "The C3 verifier for arXiv: SOURCED only when the abstract page of the preprint resolves to the stated title. Fetched robots-respecting and keyless.", inputSchema: { "type": "object", "properties": { "id": { "type": "string" }, "title": { "type": "string" } }, "required": [] } },
88
+ { name: 'answer_verify_doi', description: "The C3 verifier for a DOI: resolves it through the MCP and returns SOURCED or UNKNOWN.", inputSchema: { "type": "object", "properties": { "doi": { "type": "string" } }, "required": [] } },
89
+ { name: 'answer_verify_lean', description: "The C1 verifier: runs the Lean kernel on a source and returns TRUE or UNKNOWN for one theorem.", inputSchema: { "type": "object", "properties": { "theorem": { "type": "string" }, "source": { "type": "string", "description": "the Lean source" } }, "required": [] } },
90
+ { name: 'anti_fake', description: "Flag Lean code that claims a proof it does not have. By default checks the Lean files staged for a commit.", inputSchema: { "type": "object", "properties": { "staged": { "type": "boolean" } }, "required": [] } },
91
+ { name: 'apis_guru', description: "The APIs.guru catalogue. mode catalogue snapshots the directory (fast). mode probe starts the full probe of every catalogued specification in the background; its result is written to the evidence folder.", inputSchema: { "type": "object", "properties": { "mode": { "type": "string", "enum": ["catalogue", "probe"] } }, "required": [] } },
92
+ { name: 'apis_guru_live', description: "Starts, in the background, the live reachability pass over every catalogued API server that its specification allows without a key. The result is written to the evidence folder.", inputSchema: { "type": "object", "properties": {}, "required": [] } },
93
+ { name: 'apis_theorems', description: "Writes src/proof/apis.lean from the committed APIs.guru run, so the kernel decides statements about the verdict counts. The counts are read from the run, not typed.", inputSchema: { "type": "object", "properties": {}, "required": [] } },
94
+ { name: 'pre_commit_court', description: "The pre-commit court: manual work is sent to the court before it is committed. Runs the court over the staged work.", inputSchema: { "type": "object", "properties": {}, "required": [] } },
95
+ { name: 'prefix_check', description: "A name that repeats the repository it lives in carries no information. Flags served names that carry a repository prefix.", inputSchema: { "type": "object", "properties": { "repo": { "type": "string" }, "prefixes": { "type": "array" } }, "required": [] } },
96
+ { name: 'secure_split', description: 'Split a secret below 2^256 into shares locally, so that no single share reveals it (additive sharing over Z/2^256, randomness from the operating system). action split takes secret and parts; action join takes shares and recovers the secret. Computed on this machine; nothing is sent anywhere.', inputSchema: { type: 'object', properties: { action: { type: 'string', enum: ['split', 'join'] }, secret: { type: 'string' }, parts: { type: 'number' }, shares: { type: 'array' } }, required: ['action'] } },
97
+ { name: 'factor_verify', description: 'Check a claimed factorisation of an integer without trusting the claim: the factors must multiply to the integer exactly, each at least 2, and each is tested for primality. VERIFIED when every factor is proved prime; PROBABLE when a factor above 3.3e24 only passes a probabilistic test; REFUSED on a wrong product, a factor below 2, or a composite factor.', inputSchema: { type: 'object', properties: { n: { type: 'string', description: 'the integer, decimal digits' }, factors: { type: 'array', items: { type: 'string' }, description: 'the claimed factors, decimal digits' } }, required: ['n', 'factors'] } },
98
+ { name: 'digit_mirror', description: 'The digit mirror: each digit d becomes 10 − d, so 369 mirrors to 741. Defined only when no digit is 0. Checks that mirroring twice gives back the number (the involution).', inputSchema: { type: 'object', properties: { n: { type: 'string' } }, required: ['n'] } },
99
+ { name: 'semiprime_search', description: 'Semiprimes n = p × q (p ≠ q, both prime) for n in [lo, hi], exact by trial division. noZero excludes numbers with a zero digit, so each has a digit mirror. The limit caps the number of results.', inputSchema: { type: 'object', properties: { lo: { type: 'number' }, hi: { type: 'number' }, noZero: { type: 'boolean' }, limit: { type: 'number' } }, required: ['lo', 'hi'] } },
100
+ { name: 'shor_wave', description: 'Send a wave of integers to the QPU Shor tool and check every factorisation it returns with the verifier, not with a product alone. Reports per input: what the QPU returned, and VERIFIED, PROBABLE, REFUSED or NOT_FACTORED.', inputSchema: { type: 'object', properties: { inputs: { type: 'array', items: { type: 'string' } } }, required: ['inputs'] } },
101
+ { name: 'qpu_wave', description: 'A whole wave in one call: search the range [lo, hi] for semiprimes with no zero digit, mirror each one, send every input and its mirror to the QPU Shor tool in parallel, and verify each factorisation with the verifier. Returns the counts and every row.', inputSchema: { type: 'object', properties: { lo: { type: 'number' }, hi: { type: 'number' }, count: { type: 'number', description: 'semiprimes to take from the range' } }, required: ['lo', 'hi'] } },
102
+ { name: 'trinity', description: 'The trinity in one call: the four gates of the scheduled trinity workflow (gaps, seal, wholeness, lean-claims), run in order, each with its exit status and last lines, so a failure names the gate and the reason.', inputSchema: { type: 'object', properties: {}, required: [] } },
103
+ { name: 'family', description: 'One QPU family by name (one lowercase word, such as analytics): runs the family tests through qpu_families and returns only that family\'s lines.', inputSchema: { type: 'object', properties: { name: { type: 'string' } }, required: ['name'] } },
104
+ { name: 'api_gates', description: 'Every API in the registry as a gate: filesystem gates are checked now (a missing file or a file that no longer states the expected fact refuses); online and gated ones are named, never requested. Offline; reaches no network.', inputSchema: { type: 'object', properties: {} } },
105
+ { name: 'package_gates', description: 'Every lockfile package as a gate at its deepest path: a pinned version and an integrity hash each, refused and named when either is missing. With dockerfiles, each apk add package is a gate too. Offline; reads files only.', inputSchema: { type: 'object', properties: { dockerfiles: { type: 'array', items: { type: 'string' } } } } },
106
+ { name: 'memory_check', description: 'Check the memory directory: every index line links a file, every memory has its frontmatter (name, description, metadata.type), and every [[link]] resolves to a memory. Reads files only; never writes.', inputSchema: { type: 'object', properties: {} } },
107
+ { name: 'memory_derive', description: 'Print the measured block the memory directory is derived from: counts and verdicts read from the ledger, the Lean files and package.json at this moment. Prints only; it never writes the memory files.', inputSchema: { type: 'object', properties: {} } },
108
+ { name: 'api_lattice', description: 'The API lattice: every tool that reaches the network, keyed by its handle (first eight hex digits of its name\'s content address) and set against its declared needs. The catalogue as a grid.', inputSchema: { type: 'object', properties: {}, required: [] } },
109
+ { name: 'policy', description: 'Classify a request to build a capability against the repository rules: ALLOWED (read-only public sources), GATED (changes state, enabled by the owner per credential), or NEEDS_OWNER (money or prices, or no rule names it). A rule-based classification, not a legal ruling; it grants nothing.', inputSchema: { type: 'object', properties: { request: { type: 'string' } }, required: ['request'] } },
110
+ { name: 'factor', description: 'The production factor: the factors of an integer of any width in any binary variant — decimal, 0b binary or 0x hex. FACTORED when every factor is proved (trial division, or a deterministic primality test below 3.3e24). PARTIAL when a cofactor has no factor below 10^6 and is not proved prime: the factors found and the blocking step are returned, nothing is guessed. REFUSED for a non-integer or a value below 2. Every answer carries its witness: the served register qpu.lean pins (faces = coins × rays = 2 × 7) rotated over the fact — the integer and its digit mirror, each rendered in radix 2^k for k = 1..7 and parsed back, each state checked; agree is true only when all fourteen hold and every factorisation multiplies back. Served from every install.', inputSchema: { type: 'object', properties: { n: { type: 'string', description: 'the integer in decimal digits, any length' } }, required: ['n'] } },
111
+ { name: 'hexbit_route', description: 'Route a bit string to its hexbit folder: the content address of the input gives its handle (the first 8 hex digits, per the handle family), and the folder is that handle. Returns the files of the repository that share the handle, each rechecked from its own bytes. Nothing is created. With index true, returns the whole index of the repository\'s Lean sources by folder.', inputSchema: { type: 'object', properties: { input: { type: 'string', description: 'the bit string to route' }, index: { type: 'boolean', description: 'true for the whole index instead of one route' } }, required: [] } },
112
+ { name: 'qpu_crosscheck', description: 'Cross-check the GHZ cancellation claim against the qpu connector: qpu\'s X-basis amplitudes, if it returns them, compared with the values computed from the Lean definitions. Corroboration only, never proof; reports NOT MEASURED until qpu returns the amplitudes. Token free: the comparison is a script.', inputSchema: { type: 'object', properties: {}, required: [] } },
113
+ { name: 'prose_check', description: "Check the staged prose of the commit against the Lean ledger, through the same precommit script the hook runs. Judges citations; reports the verdict and the count of staged prose files.", inputSchema: { type: 'object', properties: {}, required: [] } },
114
+ { name: 'theorem_only', description: "Run the theorem-only check over this repository: every runtime test is a violation, and each one names its candidate Lean proofs. Exits non-zero while any runtime test remains.", inputSchema: { type: 'object', properties: {}, required: [] } },
115
+ { name: 'constants_check', description: "Check that README.md and index.md agree with the numbers scripts/pages.ts derives. Reports each disagreement; regenerate with the pages tool.", inputSchema: { type: 'object', properties: {}, required: [] } },
116
+ { name: 'pre_commit_e2e', description: "Run the whole pre-commit hook end to end without committing: prose, forensics, Lean claims, the parallel gates, the court. Returns the hook output and its exit code. The commit tool runs the same hook and is the way to commit.", inputSchema: { type: 'object', properties: {}, required: [] } },
117
+ { name: 'qpu_court_local', description: "Run qpu's own gate-court test from its build, offline. Reports pass and fail counts. The public court is a separate check, through the qpu connector.", inputSchema: { type: 'object', properties: {}, required: [] } },
118
+ { name: 'qpu_families', description: "Run every qpu family test file from its build, in one invocation, and return the pass and fail counts. Each family's own test decides its verdict.", inputSchema: { type: 'object', properties: {}, required: [] } },
119
+ { name: 'clay_online', description: 'The online evidence for each Clay problem, gathered the same way every time: OpenAlex and Crossref literature hits, and the Clay Institute page, each source read through its robots.txt first (a disallowed path is skipped and named). Reports what the sources return. A literature hit is not a proof, and the Clay page status is not determined from its text; the verdicts stay with the answer tool.', inputSchema: { type: 'object', properties: {}, required: [] } },
120
+ { name: 'links_check', description: 'Check every external link in README.md and index.md, once, the same way every time: each host\'s robots.txt is read first, a disallowed path is skipped and named, one request is in flight per host, a HEAD is retried as GET where refused, and a 429 is backed off. Each link is LIVE, DEAD (with its status), or UNREACHABLE (with the reason).', inputSchema: { type: 'object', properties: {}, required: [] } },
121
+ { name: 'explain', description: 'What a named theorem or Lean file is, from its Lean documentation by default: the doc comment or the file header, as the Lean source carries it. Writes no prose of its own; a name with no doc in the Lean source is reported as having none.', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'a theorem name, or a Lean file name' } }, required: ['name'] } },
122
+ { name: 'novelty_batch', description: 'Run the deposit\'s prior-art search over the theorems that are unknown or stale: the incremental runner of scripts/novelty.ts. Takes at most limit theorems and at most minutes of work per call; a source that refuses is cooled down and reported as NOT_MEASURED, never as absence. Resumes where the previous call stopped.', inputSchema: { type: 'object', properties: { limit: { type: 'number', description: 'at most this many theorems in this call' }, minutes: { type: 'number', description: 'the time budget of this call, in minutes' } }, required: [] } },
123
+ { name: 'connect_status', description: 'The state of a background connector call started with connect async true: RUNNING, DONE with the connector\'s reply, or FAILED with its reason.', inputSchema: { type: 'object', properties: { job: { type: 'string', description: 'the job id that connect returned' } }, required: ['job'] } },
124
+ { name: 'evidence', description: 'The deposit\'s evidence, as data: each evidence folder under evidence/ with its files and each file\'s content address. Read from the repository on each call; nothing is typed. Takes an optional folder to list only that folder.', inputSchema: { type: 'object', properties: { folder: { type: 'string', description: 'an evidence folder to list, such as constants; omit for all' } }, required: [] } },
125
+ { name: 'court_trial', description: 'A claim tried by both sides, decided by the Lean kernel: the defence compiles the claim as a theorem, the prosecution compiles its negation. SEALED when only the defence proves; REFUSED when only the prosecution proves; UNKNOWN when neither does; NOT TRIABLE when the claim is not a Lean proposition. Takes the claim as a Lean proposition in the claim field.', inputSchema: { type: 'object', properties: { claim: { type: 'string', description: 'a Lean proposition, such as 2 + 2 = 4' } }, required: ['claim'] } },
51
126
  { name: 'leads', description: 'The deposit\'s own open questions, derived from the tree rather than listed: uncontrolled refusing gates, unminted depositions, theorems that read back a hand-set value, MCP tools an install cannot reach. Also CROSSES them by cause — publication, authority, instrument, derivation, environment — because two leads sharing a cause are one problem with two faces and only one of them may be closable. Reports and does not gate: an open question is work not done, which is not work that is wrong.',
52
127
  inputSchema: { type: 'object', properties: { area: { type: 'string' } } } },
128
+ { name: 'gates_fire', description: 'Run every refusing gate\'s negative control: each gate must reject its own mutation. It writes into tracked files to do that, so it refuses while the tree has uncommitted changes, while a commit or gate is running, or while a restore marker from a killed run is still present. Controls that fail on a clean tree or match nothing are reported as untrusted.', inputSchema: { type: 'object', properties: {} } },
53
129
  { name: 'readers', description: 'Ask the scientific and medical sources this deposit investigates through — Europe PMC, PubMed, PubChem, ChEMBL, UniProt, Ensembl, KEGG, Reactome, GBIF, RxNorm, openFDA, MeSH, ClinicalTrials.gov and more — whether each still answers with a fact known BEFORE it was asked. Three verdicts kept apart: PROVEN, WRONG (the reader is broken OR the expectation was), and NOT MEASURED (it did not answer — silence is not absence). 8 further sources are named as credential- or licence-gated rather than omitted, because an unrecorded gap becomes an implicit claim of completeness. CITATION INSTRUMENTS, NOT MEDICAL ADVICE: a documented traditional use is an anthropological fact, never evidence a use works, and never a dose.',
54
130
  inputSchema: { type: 'object', properties: { domain: { type: 'string' }, list: { type: 'boolean' } } } },
55
131
  { name: 'live', description: 'What this deposit has actually SHIPPED, asked of the registries rather than the tree: the npm version against package.json, the newest provenance tag, and the site against the ledger this tree holds. A green publish workflow says npm was called, not that the version on the registry is the one here — that gap has been real for three releases. Reports, never gates: network state must not decide whether a local build is allowed.',
@@ -79,15 +155,76 @@ export const NEEDS = {
79
155
  novelty: ['net'],
80
156
  entanglements: ['tree'],
81
157
  leads: ['tree'],
158
+ gates_fire: ['net', 'tree'],
82
159
  readers: ['net', 'tree'],
83
160
  live: ['net', 'tree'],
84
- connect: ['net'],
161
+ connect: ['net', 'tree', 'git'],
85
162
  api_joins: ['net', 'tree'],
86
163
  coils: ['tree'],
87
164
  discoveries: ['tree'],
88
165
  formulas: ['tree'],
89
166
  handle: ['core'],
90
167
  lean_verify: ['lean', 'tree'],
168
+ lean_ask: ['lean', 'tree'],
169
+ answer: ['net', 'lean', 'tree'],
170
+ git_commit_paths: ['git', 'tree'],
171
+ session_report: ['tree'],
172
+ stall_check: ['tree'],
173
+ run_suite: ['net', 'tree'],
174
+ task_route: ['tree'],
175
+ lean_split: ['lean', 'tree'],
176
+ web_fetch: ['net', 'tree'],
177
+ clay_conditions: ['net', 'tree'],
178
+ leaks: ['tree'],
179
+ hexbit_route: ['tree'],
180
+ apis_guru_cross: ['tree'],
181
+ apis_guru_gaps: ['tree'],
182
+ factor: ['core'],
183
+ trinity: ['tree'],
184
+ family: ['tree'],
185
+ memory_check: ['tree'],
186
+ memory_derive: ['tree'],
187
+ api_gates: ['tree'],
188
+ package_gates: ['tree'],
189
+ api_lattice: ['core'],
190
+ policy: ['core'],
191
+ digit_mirror: ['core'],
192
+ semiprime_search: ['tree'],
193
+ shor_wave: ['net', 'tree'],
194
+ qpu_wave: ['net'],
195
+ factor_verify: ['core'],
196
+ secure_split: ['core'],
197
+ contradictions: ['tree'],
198
+ answer_gate: ['tree'],
199
+ answer_verify_arith: ['tree'],
200
+ answer_verify_arxiv: ['tree'],
201
+ answer_verify_doi: ['net', 'tree'],
202
+ answer_verify_lean: ['lean', 'tree'],
203
+ anti_fake: ['tree'],
204
+ apis_guru: ['net', 'tree'],
205
+ apis_guru_live: ['net', 'tree'],
206
+ apis_theorems: ['tree'],
207
+ pre_commit_court: ['net', 'tree'],
208
+ prefix_check: ['tree'],
209
+ understand: ['tree'],
210
+ api_adapters: ['net', 'tree'],
211
+ prose_check: ['tree'],
212
+ theorem_only: ['tree'],
213
+ constants_check: ['tree'],
214
+ pre_commit_e2e: ['tree', 'git', 'lean', 'ledger', 'net'],
215
+ qpu_court_local: ['tree'],
216
+ qpu_families: ['tree'],
217
+ qpu_crosscheck: ['net', 'tree'],
218
+ clay_online: ['net', 'tree'],
219
+ links_check: ['net', 'tree'],
220
+ explain: ['tree'],
221
+ court_trial: ['lean', 'tree'],
222
+ evidence: ['tree'],
223
+ novelty_batch: ['net', 'tree'],
224
+ connect_status: ['tree'],
225
+ cern: ['net', 'tree'],
226
+ web_search: ['net', 'tree'],
227
+ lean_audit_library: ['lean', 'tree'],
91
228
  lean_seal: ['lean', 'tree'],
92
229
  lean_generate: ['lean', 'tree'],
93
230
  ledger_trial: ['tree'],
@@ -106,7 +243,7 @@ export const NEEDS = {
106
243
  recompute: ['ledger'],
107
244
  rosetta: ['core'],
108
245
  forensics: ['ledger'],
109
- audit: ['core'],
246
+ audit: ['lean', 'tree'],
110
247
  };
111
248
  export const SELF_SUFFICIENT = Object.entries(NEEDS)
112
249
  .filter(([, n]) => n.length === 1 && n[0] === 'core').map(([k]) => k).sort();
@@ -35,12 +35,12 @@ export declare const forensicsOf: (rows: Row[], seed?: string) => {
35
35
  note: string;
36
36
  };
37
37
  export declare const verifyIn: (rows: Row[], uuid: string) => {
38
+ index?: undefined;
39
+ name?: undefined;
38
40
  uuid: string;
39
41
  found: boolean;
40
42
  note: string;
41
- index?: undefined;
42
43
  key?: undefined;
43
- name?: undefined;
44
44
  live?: undefined;
45
45
  supersededBy?: undefined;
46
46
  reason?: undefined;
@@ -58,6 +58,16 @@ export declare const verifyIn: (rows: Row[], uuid: string) => {
58
58
  note: string;
59
59
  };
60
60
  export declare const CANNOT_SHIP: Record<string, string>;
61
+ export declare const BAKEABLE: string[];
62
+ export type Bake = {
63
+ stamp: Record<string, unknown>;
64
+ answers: Record<string, string>;
65
+ notBaked: Record<string, string>;
66
+ };
67
+ export declare const withBake: (b: Bake) => void;
68
+ export declare const hasBake: () => boolean;
69
+ export declare const FROM_BAKE: Record<string, string>;
70
+ export declare const whyNot: (name: string) => string;
61
71
  export declare const SERVED_CORE: string[];
62
72
  export declare const SERVED_WITH_LEDGER: string[];
63
73
  export declare const served: () => string[];
@@ -1,4 +1,8 @@
1
1
  import { toUuid, merkleFold, merge } from '../0/index.js';
2
+ import { factorWitnessed } from '../factor/index.js';
3
+ import { verifyFactors } from '../factor/verify.js';
4
+ import { mirror as digitMirror } from '../mirror/index.js';
5
+ import { decide as policyDecide } from '../policy/index.js';
2
6
  import { handle, resolve, HANDLE_HEX } from '../handle/index.js';
3
7
  import { checkFace } from '../face/index.js';
4
8
  import { CORE as ROSETTA_CORE, DOMAINS as ROSETTA_DOMAINS } from '../the/rosetta/index.js';
@@ -50,6 +54,7 @@ export const verifyIn = (rows, uuid) => {
50
54
  note: 'The address was found and its chain link recomputed. Integrity and position, never truth of the statement.' };
51
55
  };
52
56
  export const CANNOT_SHIP = {
57
+ secure_split: 'its shares are drawn from node:crypto randomBytes, and this entry opens no node module — clone the repository for it',
53
58
  discover: 'its candidate set is scripts/discover.ts — repository logic, not a module',
54
59
  recompute: 'it re-runs every candidate\'s formula, and the formulas are in scripts/discover.ts — the same repository logic. Reading the ledger is not enough: this tool recomputes what the ledger RECORDS, which needs the code that computed it',
55
60
  };
@@ -60,12 +65,37 @@ const LEDGER_TOOLS = Object.entries(NEEDS)
60
65
  .filter(([k, n]) => n.length === 1 && n[0] === 'ledger' && !CANNOT_SHIP[k])
61
66
  .map(([k]) => k);
62
67
  const DATA_TOOLS = ['formulas'];
68
+ const OUTSIDE_ANY_PACKAGE = new Set(['lean', 'net', 'git', 'shared']);
69
+ export const BAKEABLE = TOOLS.map((t) => t.name).filter((n) => !CORE_TOOLS.includes(n) && !LEDGER_TOOLS.includes(n) && !DATA_TOOLS.includes(n)
70
+ && (NEEDS[n] ?? ['tree']).every((x) => !OUTSIDE_ANY_PACKAGE.has(x))
71
+ && !WRITES.has(n)
72
+ && (TOOLS.find((t) => t.name === n)?.inputSchema?.required ?? []).length === 0).sort();
73
+ let BAKE = null;
74
+ export const withBake = (b) => { BAKE = b; };
75
+ export const hasBake = () => BAKE !== null;
76
+ const bakedNames = () => (BAKE ? Object.keys(BAKE.answers).filter((n) => BAKEABLE.includes(n)) : []);
77
+ export const FROM_BAKE = { family: 'qpu_families' };
78
+ const fromBakeNames = () => Object.entries(FROM_BAKE).filter(([, src]) => BAKE?.answers[src] !== undefined).map(([n]) => n);
79
+ export const whyNot = (name) => {
80
+ if (CANNOT_SHIP[name])
81
+ return CANNOT_SHIP[name];
82
+ if (BAKE?.notBaked[name])
83
+ return BAKE.notBaked[name];
84
+ if (WRITES.has(name))
85
+ return 'it writes to the tree, and a package has no tree to write to';
86
+ const req = TOOLS.find((t) => t.name === name)?.inputSchema?.required ?? [];
87
+ if (req.length && BAKEABLE.every((n) => n !== name) && (NEEDS[name] ?? []).every((x) => !OUTSIDE_ANY_PACKAGE.has(x)))
88
+ return `it takes \`${req.join(', ')}\`, and no bare answer stands in for an argument the caller chooses — clone the repository for it`;
89
+ return `it needs ${(NEEDS[name] ?? ['the repository']).join('+')}: clone the repository and run \`npm run mcp\``;
90
+ };
63
91
  export const SERVED_CORE = [...CORE_TOOLS].sort();
64
92
  export const SERVED_WITH_LEDGER = [...CORE_TOOLS, ...LEDGER_TOOLS, ...DATA_TOOLS].sort();
65
93
  export const served = () => [
66
94
  ...SERVED_CORE,
67
95
  ...(hasLedger() ? LEDGER_TOOLS : []),
68
96
  ...(hasFormulas() ? DATA_TOOLS : []),
97
+ ...bakedNames(),
98
+ ...fromBakeNames(),
69
99
  ].sort();
70
100
  export const formulasFrom = (rows, a = {}) => {
71
101
  let out = rows;
@@ -102,6 +132,16 @@ const rowsOrRefuse = (tool) => {
102
132
  return ROWS;
103
133
  };
104
134
  const H = {
135
+ factor: (a) => JSON.stringify(factorWitnessed(String(a?.n ?? ''))),
136
+ factor_verify: (a) => JSON.stringify(verifyFactors(String(a?.n ?? ''), Array.isArray(a?.factors) ? a.factors.map(String) : [])),
137
+ digit_mirror: (a) => JSON.stringify(digitMirror(String(a?.n ?? ''))),
138
+ policy: (a) => JSON.stringify(policyDecide(String(a?.request ?? ''))),
139
+ api_lattice: () => {
140
+ const rows = TOOLS.filter((t) => (NEEDS[t.name] ?? []).includes('net')).map((t) => ({
141
+ handle: toUuid(t.name).replace(/-/g, '').slice(0, 8), tool: t.name, needs: NEEDS[t.name] ?? [],
142
+ })).sort((a, b) => a.handle.localeCompare(b.handle));
143
+ return JSON.stringify({ tools: rows.length, lattice: rows });
144
+ },
105
145
  formulas: (a) => {
106
146
  if (!FORMS)
107
147
  throw new Error('formulas: the formula catalogue is not loaded. The published package carries it '
@@ -145,6 +185,17 @@ const H = {
145
185
  return JSON.stringify({ handle: handle(text), hex: HANDLE_HEX, address: toUuid(text),
146
186
  note: 'The first four hex of the address. Nothing but the message ever travels — the handle plus the message determine the whole address.' });
147
187
  },
188
+ family: (a) => {
189
+ const src = BAKE?.answers[FROM_BAKE.family];
190
+ if (src === undefined)
191
+ throw new Error('family filters the lines of qpu_families, and that answer is not loaded here — the published package carries it at dist/data/baked/qpu_families.json');
192
+ const name = String(a?.name ?? '').trim().toLowerCase();
193
+ if (!/^[a-z][a-z0-9]*$/.test(name))
194
+ return JSON.stringify({ status: 'REFUSED', why: 'a family name is one lowercase word, such as analytics' });
195
+ const lines = src.split('\n').filter((l) => l.toLowerCase().includes(name));
196
+ return JSON.stringify({ family: name, lines: lines.length, status: lines.length ? 'FOUND' : 'NOT_FOUND', tests: lines.slice(0, 12),
197
+ baked: true, ...(BAKE?.stamp ?? {}), note: 'filtered from the qpu_families answer baked at build — the same filter the full server applies, over the same lines' });
198
+ },
148
199
  honesty_gate: (a) => {
149
200
  const text = String(a?.text ?? '');
150
201
  if (!text)
@@ -172,7 +223,7 @@ const H = {
172
223
  const missing = here.filter((n) => !H[n]);
173
224
  const extra = Object.keys(H).filter((n) => !here.includes(n));
174
225
  return JSON.stringify({
175
- entry: 'self-sufficient', ledgerLoaded: hasLedger(), served: here.length, of: TOOLS.length,
226
+ entry: 'self-sufficient', ledgerLoaded: hasLedger(), bakeLoaded: hasBake(), served: here.length, of: TOOLS.length,
176
227
  declaredWithoutHandler: missing, handlerWithoutDeclaration: extra,
177
228
  writes: [...WRITES].filter((w) => here.includes(w)),
178
229
  root: merkleFold(here.map((n) => toUuid(n + ':' + (TOOLS.find((t) => t.name === n)?.description ?? '')))),
@@ -189,14 +240,16 @@ export const listTools = (name) => {
189
240
  throw new Error(`unknown tool: ${String(name)} — call list_tools with no name for the list`);
190
241
  const avail = served().includes(t.name);
191
242
  return JSON.stringify({ name: t.name, description: t.description, inputSchema: t.inputSchema, available: avail,
192
- ...(avail ? {} : { needs: NEEDS[t.name], why: CANNOT_SHIP[t.name] ?? 'needs the repository: clone it and run `npm run mcp` for the full surface' }) });
243
+ ...(bakedNames().includes(t.name) ? { baked: true, ...(BAKE?.stamp ?? {}) } : {}),
244
+ ...(avail ? {} : { needs: NEEDS[t.name], why: whyNot(t.name) }) });
193
245
  }
194
246
  return JSON.stringify({
195
247
  entry: 'self-sufficient — runs from the published package with no account, key, model, network or clone',
196
248
  serves: `${served().length} of ${TOOLS.length} tools`,
197
- ledgerLoaded: hasLedger(),
249
+ ledgerLoaded: hasLedger(), bakeLoaded: hasBake(),
198
250
  tools: served().map((n) => ({ name: n, description: first(TOOLS.find((t) => t.name === n)?.description ?? '') })),
199
- elsewhere: TOOLS.filter((t) => !served().includes(t.name)).map((t) => ({ name: t.name, needs: NEEDS[t.name], why: CANNOT_SHIP[t.name] ?? 'needs the repository' })),
251
+ baked: bakedNames().length ? { tools: bakedNames().length, ...(BAKE?.stamp ?? {}) } : null,
252
+ elsewhere: TOOLS.filter((t) => !served().includes(t.name)).map((t) => ({ name: t.name, needs: NEEDS[t.name], why: whyNot(t.name) })),
200
253
  note: 'The other tools are not hidden and not broken: each names what it needs. Clone the repository for the full surface.',
201
254
  });
202
255
  };
@@ -206,11 +259,23 @@ export const run = (name, a) => {
206
259
  if (name === 'call_tool')
207
260
  return run(String(a?.name ?? ''), a?.arguments ?? {});
208
261
  const h = H[name];
262
+ if (!h && BAKE && BAKE.answers[name] !== undefined && BAKEABLE.includes(name)) {
263
+ const args = a && typeof a === 'object' ? Object.keys(a) : [];
264
+ if (args.length)
265
+ throw new Error(`${name} is served BAKED — its bare answer, computed at build from the repository — and a call with `
266
+ + `arguments (${args.join(', ')}) asks for an answer the package cannot recompute. Call it without arguments, or clone the repository and run \`npm run mcp\`.`);
267
+ let answer = BAKE.answers[name];
268
+ try {
269
+ answer = JSON.parse(BAKE.answers[name]);
270
+ }
271
+ catch { }
272
+ return JSON.stringify({ baked: true, ...BAKE.stamp, tool: name, answer,
273
+ note: 'The bare answer this tool gave at build, from the tree the stamp names — not a recomputation here. Integrity of the stamp, not truth of the answer.' });
274
+ }
209
275
  if (!h) {
210
276
  const declared = TOOLS.find((t) => t.name === name);
211
277
  if (declared)
212
- throw new Error(`${name} is a tool of this deposit but is not served by the self-sufficient entry: `
213
- + (CANNOT_SHIP[name] ?? `it needs ${(NEEDS[name] ?? []).join('+')}`) + '. Clone the repository and run `npm run mcp`.');
278
+ throw new Error(`${name} is a tool of this deposit but is not served by the self-sufficient entry: ${whyNot(name)}`);
214
279
  throw new Error(`unknown tool: ${name} — call list_tools for what this entry serves`);
215
280
  }
216
281
  return h(a);
@@ -0,0 +1 @@
1
+ export declare const SUITES: Record<string, string[]>;
@@ -0,0 +1,14 @@
1
+ export const SUITES = {
2
+ 'mcp-gate': ['node', 'scripts/mcp-gate.ts'],
3
+ 'hardcode-gate': ['node', 'scripts/hardcode-gate.ts'],
4
+ 'mcp-check': ['node', 'scripts/mcp-check.ts'],
5
+ 'mcp-calls': ['node', 'scripts/mcp-calls.ts'],
6
+ 'net-tools-test': ['node', 'scripts/net-tools-test.ts'],
7
+ 'clay-conditions-self-test': ['node', 'scripts/clay-conditions-test.ts', '--self-test'],
8
+ 'clay-conditions': ['node', 'scripts/clay-conditions-test.ts'],
9
+ 'environment': ['node', 'scripts/environment.ts'],
10
+ 'doi-precedence': ['node', 'scripts/doi-precedence-test.ts'],
11
+ 'answer-doi': ['node', 'scripts/answer-doi-test.ts'],
12
+ 'answer-tool': ['node', 'scripts/answer-tool-test.ts'],
13
+ 'fallbacks': ['node', 'scripts/fallbacks-test.ts'],
14
+ };
@@ -0,0 +1,18 @@
1
+ export declare const mirror: (n: string) => {
2
+ status: 'MIRRORED';
3
+ mirror: string;
4
+ involution: boolean;
5
+ } | {
6
+ status: 'REFUSED';
7
+ why: string;
8
+ };
9
+ export interface Semiprime {
10
+ n: string;
11
+ p: number;
12
+ q: number;
13
+ mirror: string | null;
14
+ }
15
+ export declare const semiprimes: (lo: number, hi: number, opts?: {
16
+ noZero?: boolean;
17
+ limit?: number;
18
+ }) => Semiprime[];
@@ -0,0 +1,37 @@
1
+ export const mirror = (n) => {
2
+ if (!/^\d+$/.test(n))
3
+ return { status: 'REFUSED', why: 'not a non-negative decimal integer' };
4
+ if (n.includes('0'))
5
+ return { status: 'REFUSED', why: 'a zero digit has no mirror: 10 − 0 is not a digit' };
6
+ const m = [...n].map((c) => String(10 - Number(c))).join('');
7
+ const back = [...m].map((c) => String(10 - Number(c))).join('');
8
+ return { status: 'MIRRORED', mirror: m, involution: back === n };
9
+ };
10
+ const smallestFactor = (n) => {
11
+ if (n < 2)
12
+ return null;
13
+ if (n % 2 === 0)
14
+ return 2;
15
+ for (let d = 3; d * d <= n; d += 2)
16
+ if (n % d === 0)
17
+ return d;
18
+ return null;
19
+ };
20
+ export const semiprimes = (lo, hi, opts = {}) => {
21
+ const out = [];
22
+ const limit = opts.limit ?? 20;
23
+ const start = lo % 2 === 0 ? lo + 1 : lo;
24
+ for (let n = start; n <= hi && out.length < limit; n += 2) {
25
+ const s = String(n);
26
+ if (opts.noZero && s.includes('0'))
27
+ continue;
28
+ const p = smallestFactor(n);
29
+ if (p === null)
30
+ continue;
31
+ const q = n / p;
32
+ if (q === p || smallestFactor(q) !== null)
33
+ continue;
34
+ out.push({ n: s, p, q, mirror: s.includes('0') ? null : mirror(s).status === 'MIRRORED' ? mirror(s).mirror : null });
35
+ }
36
+ return out;
37
+ };
@@ -0,0 +1,8 @@
1
+ export type Verdict = 'ALLOWED' | 'GATED' | 'NEEDS_OWNER';
2
+ export interface Decision {
3
+ verdict: Verdict;
4
+ request: string;
5
+ reason: string;
6
+ rule: string;
7
+ }
8
+ export declare const decide: (request: string) => Decision;
@@ -0,0 +1,23 @@
1
+ const RULES = [
2
+ { rule: 'access-grant', verdict: 'NEEDS_OWNER', pattern: /\b(tokens?|credentials?|grant|authori[sz]ed access|access keys?|accounts?|logins?|sign-?ups?|invitations?|invite links?|register|registration|computational access|real users?|registers? as|user accounts?|client (?:browser|os|sessions?)|online sessions?|browser sessions?)\b/i,
3
+ reason: 'grants access to people or issues credentials: only the owner decides who gets access, and with what' },
4
+ { rule: 'agent-payload-path', verdict: 'GATED', pattern: /\b(payload\s+mcp\s+plugin|rbac)\b/i,
5
+ reason: 'agents act on Payload only through the Payload MCP plugin under RBAC: that is the one path, and the roles behind it are set by the owner' },
6
+ { rule: 'billing', verdict: 'NEEDS_OWNER', pattern: /\b(billing|billable|payment|charge|subscription|price|pricing|meter)\b/i,
7
+ reason: 'takes money or sets prices: needs a payment account, a price and terms that only the owner can set' },
8
+ { rule: 'public-write', verdict: 'GATED', pattern: /\b(write|publish|commit|seal|push|deploy|create|(?:create|write|edit|change|update|set)\s+(?:\w+\s+){0,2}configs?|payload\s+write|cms\s+write)\b/i,
9
+ reason: 'changes state: stays behind the write gate and is enabled only by the owner, per credential' },
10
+ { rule: 'read-only', verdict: 'ALLOWED', pattern: /\b(read[- ]?only|reads?|readers?|lattice|apis?|guru|look ?ups?|query)\b/i,
11
+ reason: 'reads public sources and changes nothing: allowed, with a timeout and a result limit' },
12
+ ];
13
+ export const decide = (request) => {
14
+ const text = request.trim();
15
+ if (!text)
16
+ return { verdict: 'NEEDS_OWNER', request, reason: 'the request is empty', rule: 'empty' };
17
+ const order = ['NEEDS_OWNER', 'GATED', 'ALLOWED'];
18
+ const hits = RULES.filter((r) => r.pattern.test(text));
19
+ if (!hits.length)
20
+ return { verdict: 'NEEDS_OWNER', request: text, reason: 'no rule of this repository names the request, so the owner decides', rule: 'unmatched' };
21
+ const strictest = hits.sort((a, b) => order.indexOf(a.verdict) - order.indexOf(b.verdict))[0];
22
+ return { verdict: strictest.verdict, request: text, reason: strictest.reason, rule: strictest.rule };
23
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ceccec/millennium-solutions",
3
- "version": "9.8.2",
3
+ "version": "9.8.3",
4
4
  "description": "Verifiable, recomputable ℤ/9 vortex framework in ONE package — content-addressing, audit ledger, exact arithmetic, and the honesty toolkit. Facts only.",
5
5
  "author": {
6
6
  "name": "Tsvetan Rouschev",
@@ -103,7 +103,7 @@
103
103
  "latex-gate": "node scripts/latex-gate.ts",
104
104
  "contradictions": "node scripts/contradictions.ts",
105
105
  "prior-art": "node scripts/priorart.ts",
106
- "gates": "node scripts/prose-trial.ts && node scripts/crypto-kat.ts && node scripts/attribution-gate.ts && node scripts/hardcode-gate.ts && node scripts/import-gate.ts && node scripts/one-author-gate.ts && node scripts/orphan-gate.ts && node scripts/security-gate.ts && node scripts/translate-gate.ts && node scripts/lean-agree.ts && node scripts/trial-all.ts && node scripts/readme.ts && node scripts/gaps.ts && node scripts/constants-gate.ts && node scripts/fixture-addresses.ts && node scripts/forensic-audit.ts && node scripts/notice.ts && node scripts/recover.ts && node scripts/independent.ts && node scripts/supersede.ts && node scripts/covered-gate.ts && node scripts/group.ts --emit && node scripts/bridge.ts --emit && node scripts/vacuity.ts && node scripts/citations-gate.ts && node scripts/cite-audit.ts && node scripts/lanes-check.ts && node scripts/runnable-gate.ts && node scripts/formulas.ts && node scripts/coils.ts && node scripts/settled.ts && node scripts/derived-gate.ts && node scripts/mcp-gate.ts",
106
+ "gates": "node scripts/apis-theorems.ts && node scripts/prose-trial.ts && node scripts/crypto-kat.ts && node scripts/attribution-gate.ts && node scripts/hardcode-gate.ts && node scripts/import-gate.ts && node scripts/one-author-gate.ts && node scripts/orphan-gate.ts && node scripts/security-gate.ts && node scripts/translate-gate.ts && node scripts/lean-agree.ts && node scripts/trial-all.ts && node scripts/readme.ts && node scripts/gaps.ts && node scripts/constants-gate.ts && node scripts/fixture-addresses.ts && node scripts/forensic-audit.ts && node scripts/notice.ts && node scripts/recover.ts && node scripts/independent.ts && node scripts/supersede.ts && node scripts/covered-gate.ts && node scripts/group.ts --emit && node scripts/bridge.ts --emit && node scripts/vacuity.ts && node scripts/citations-gate.ts && node scripts/cite-audit.ts && node scripts/lanes-check.ts && node scripts/runnable-gate.ts && node scripts/formulas.ts && node scripts/coils.ts && node scripts/settled.ts && node scripts/derived-gate.ts && node scripts/mcp-gate.ts && npm run --silent gate:thousand:control && node scripts/qpu-gate.ts && node scripts/discoveries.ts",
107
107
  "gates:fire": "node scripts/gates-fire.ts",
108
108
  "ci:local": "node scripts/ci-local.ts",
109
109
  "metrics": "node scripts/metrics.ts",
@@ -119,6 +119,7 @@
119
119
  "docs-gate": "node scripts/docs-gate.ts",
120
120
  "priorart:gen": "node scripts/priorart-gen.ts",
121
121
  "priorart-check": "node scripts/priorart-gen.ts --check",
122
+ "priorart:arxiv": "node scripts/arxiv-search.ts",
122
123
  "apply": "node scripts/apply.ts",
123
124
  "ci-drift": "node scripts/ci-drift.ts",
124
125
  "carry": "node scripts/carry.ts",
@@ -195,9 +196,20 @@
195
196
  "ci:watch": "node scripts/ci-watch.ts",
196
197
  "ci:watch-wait": "node scripts/ci-watch.ts --wait",
197
198
  "cycle": "npm run gates && npm run docs:build",
198
- "cycle:ship": "git fetch -q --force --tags origin && npm run cycle && git add -A && { git diff --cached --quiet || git commit -m 'regenerate the derived artefacts the chain rewrote'; } && git push origin main && node scripts/ci-watch.ts --wait --for 5400",
199
+ "cycle:ship": "git fetch -q --force --tags origin && npm update --no-audit --no-fund @uuidna/qpu @uuidna/uuidna && npm run cycle && git add -A && { git diff --cached --quiet || git commit -m 'regenerate the derived artefacts the chain rewrote'; } && git push origin main && node scripts/ci-watch.ts --wait --for 5400 && node scripts/thousand-bit-gate.ts --decode",
199
200
  "bridge": "node scripts/bridge.ts",
200
- "qpu": "node scripts/qpu-gate.ts"
201
+ "qpu": "node scripts/qpu-gate.ts",
202
+ "mcp:call": "node scripts/mcp-call.ts",
203
+ "gate:thousand": "node scripts/thousand-bit-gate.ts",
204
+ "gate:thousand:control": "node scripts/thousand-bit-gate.ts --control",
205
+ "gate:leads": "node scripts/leads-closed.ts",
206
+ "gate:api": "node scripts/api-gates.ts",
207
+ "gate:packages": "node scripts/package-gates.ts",
208
+ "test:online-verify": "node scripts/online-verify-e2e-test.ts",
209
+ "test:run-suite-security": "node scripts/run-suite-security-test.ts",
210
+ "cern:lean": "node scripts/cern-lean.ts",
211
+ "push:green": "node scripts/push-when-green.ts",
212
+ "dataset:court": "node scripts/dataset-court.ts"
201
213
  },
202
214
  "devDependencies": {
203
215
  "@types/node": "^26.2.0",
@@ -238,5 +250,8 @@
238
250
  "dependencies": {
239
251
  "@uuidna/qpu": "^1.0.0",
240
252
  "@uuidna/uuidna": "^0.2.6"
253
+ },
254
+ "overrides": {
255
+ "postcss-selector-parser": "^7.1.6"
241
256
  }
242
257
  }