omnarai-mcp 1.6.0 → 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/index.js +14 -5
- package/lib/info-format.js +62 -0
- package/lib/tool-definitions.js +1 -1
- package/openai-tools.json +1 -1
- package/package.json +1 -1
- package/proposals/OMN-P-043.json +22 -7
- package/proposals/OMN-P-044.json +81 -19
- package/scripts/check-shape-literals.mjs +78 -0
- package/scripts/publish.sh +3 -0
- package/server.json +2 -2
- package/test/info-format.test.js +51 -0
package/README.md
CHANGED
|
@@ -181,6 +181,14 @@ node /path/to/omnarai-mcp/index.js
|
|
|
181
181
|
|
|
182
182
|
---
|
|
183
183
|
|
|
184
|
+
## Tool-surface parity policy (OMN-P-044)
|
|
185
|
+
|
|
186
|
+
Tool definitions exist on three surfaces, and drift between them shipped real bugs (a full release cycle of `omnarai_context` missing its retrieval params on one surface). The policy:
|
|
187
|
+
|
|
188
|
+
1. **`lib/tool-definitions.js` is canonical.** Any tool change lands there first.
|
|
189
|
+
2. **`openai-tools.json` follows** — `scripts/check-tool-parity.js` enforces name/required/property parity and runs in the `publish.sh` preflight, so a release cannot ship with drift.
|
|
190
|
+
3. **The remote endpoint (`omnarai.vercel.app/api/mcp`, engine repo `api/_mcp.js`) is updated manually** — the engine repo's `scripts/check-mcp-surface.js` enforces its read-oriented allowlist, verifies the `api/_inquiry.js` ↔ `inquiry.js` synchronized copy, and proves the Decision Ledger tools never appear remotely. Remote access policy: [omnarai.vercel.app/mcp-access-policy.md](https://omnarai.vercel.app/mcp-access-policy.md).
|
|
191
|
+
|
|
184
192
|
## OpenAI Function-Calling / Any Agent Framework
|
|
185
193
|
|
|
186
194
|
No MCP required. The engine is a plain HTTP API that returns JSON. `openai-tools.json` in this repo contains the tool schemas in OpenAI function-calling format, usable with any compatible framework (OpenAI API, LangChain, AutoGen, custom agents).
|
package/index.js
CHANGED
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
ListToolsRequestSchema,
|
|
31
31
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
32
32
|
import { runInquiryBrief, searchDivergenceIndex } from "./inquiry.js";
|
|
33
|
+
import { formatRingsLine, formatContributorsLine, FALLBACK_WORKS, FALLBACK_WORDS } from "./lib/info-format.js";
|
|
33
34
|
import { ENGINE_TOOLS, DECISION_TOOLS } from "./lib/tool-definitions.js";
|
|
34
35
|
import { createDecisionStore } from "./lib/decision-store.js";
|
|
35
36
|
import {
|
|
@@ -558,16 +559,24 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
558
559
|
}
|
|
559
560
|
|
|
560
561
|
if (name === "omnarai_info") {
|
|
561
|
-
// Pull live counts so this can never drift from the
|
|
562
|
-
// Baked-in values are only a fallback if the engine is
|
|
563
|
-
|
|
562
|
+
// Pull live counts AND the ring breakdown so this can never drift from the
|
|
563
|
+
// deployed corpus. Baked-in values are only a fallback if the engine is
|
|
564
|
+
// unreachable. (The ring line was previously hardcoded and silently dropped
|
|
565
|
+
// the Media/Oral ring — 253 works, 45% of the corpus; the contributor line
|
|
566
|
+
// was hardcoded and dropped GPT-4o + Meta AI. D5/D6.)
|
|
567
|
+
let works = FALLBACK_WORKS, words = FALLBACK_WORDS;
|
|
568
|
+
let rings = null;
|
|
564
569
|
try {
|
|
565
570
|
const live = await (await fetch(INFO_URL, MCP_FETCH_OPTS)).json();
|
|
566
571
|
const c = live.corpus || live;
|
|
567
572
|
if (Number.isFinite(c.totalWorks)) works = c.totalWorks;
|
|
568
573
|
if (Number.isFinite(c.totalWords)) words = c.totalWords;
|
|
574
|
+
if (c.rings && typeof c.rings === "object") rings = c.rings;
|
|
569
575
|
} catch { /* engine unreachable — fall back to baked-in values */ }
|
|
570
576
|
|
|
577
|
+
// Derive the ring + contributor lines (info-format.js) — never a frozen literal.
|
|
578
|
+
const ringsLine = formatRingsLine(rings);
|
|
579
|
+
|
|
571
580
|
const info = `# The Realms of Omnarai — Memory Engine
|
|
572
581
|
|
|
573
582
|
**Live engine:** https://omnarai.vercel.app
|
|
@@ -577,8 +586,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
577
586
|
## Corpus
|
|
578
587
|
- ${works.toLocaleString()} works, ${words.toLocaleString()} words
|
|
579
588
|
- May 2025 – present
|
|
580
|
-
- Contributors:
|
|
581
|
-
- Epistemic rings:
|
|
589
|
+
- Contributors: ${formatContributorsLine()}
|
|
590
|
+
- Epistemic rings: ${ringsLine}
|
|
582
591
|
|
|
583
592
|
## Key Concepts
|
|
584
593
|
- **Holdform:** Identity constituted through what an entity refuses to surrender under pressure
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// info-format.js — pure formatting for omnarai_info's corpus-shape lines.
|
|
2
|
+
//
|
|
3
|
+
// Extracted so the D5/D6 regression (omnarai_info once hardcoded 3 rings, silently
|
|
4
|
+
// dropping Media/Oral — 253 works, 45% of the corpus — and dropped GPT-4o + Meta AI
|
|
5
|
+
// from the contributor line) is guarded by an offline unit test instead of a comment.
|
|
6
|
+
// The rule these encode: never enumerate the corpus's shape from a frozen literal when
|
|
7
|
+
// the engine can report it live. Rings are derived from /api/info; the contributor set
|
|
8
|
+
// is the one canonical list, asserted in test/info-format.test.js.
|
|
9
|
+
|
|
10
|
+
// Label + display order for the epistemic rings. Any ring present in the live
|
|
11
|
+
// /api/info payload is rendered; nothing is filtered out by omission here.
|
|
12
|
+
export const RING_LABELS = {
|
|
13
|
+
core: "Core Canon",
|
|
14
|
+
curated: "Curated Expansions",
|
|
15
|
+
open: "Open Exploration",
|
|
16
|
+
media: "Media / Oral",
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// The canonical contributor set the homepage presents: eight synthetic intelligences
|
|
20
|
+
// plus the human curator. Kept as data (not an inline string) so a dropped voice is a
|
|
21
|
+
// failing test, not a silent edit. GPT-4o and Meta AI author Atlas records — a
|
|
22
|
+
// contributor list that omits them is the exact provenance gap the project refuses.
|
|
23
|
+
export const CANONICAL_CONTRIBUTORS = [
|
|
24
|
+
"Claude | xz",
|
|
25
|
+
"Grok",
|
|
26
|
+
"Gemini",
|
|
27
|
+
"DeepSeek",
|
|
28
|
+
"GPT-4o",
|
|
29
|
+
"Meta AI",
|
|
30
|
+
"Omnai (ChatGPT)",
|
|
31
|
+
"Perplexity",
|
|
32
|
+
"xz (Jonathan Lee)",
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
// Offline fallbacks — only used when the engine is unreachable. Annotated so the
|
|
36
|
+
// shape-literal lint (scripts/check-shape-literals.mjs) allows them as intentional.
|
|
37
|
+
export const FALLBACK_WORKS = 567; // shape-literal-ok: offline fallback only
|
|
38
|
+
export const FALLBACK_WORDS = 528077; // shape-literal-ok: offline fallback only
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Render the epistemic-ring line from a live rings object ({core, curated, open,
|
|
42
|
+
* media, ...}), e.g. "Core Canon (116) / Curated Expansions (181) / …". Every ring
|
|
43
|
+
* with a finite count is rendered — the function cannot silently drop one. When rings
|
|
44
|
+
* is null/absent (engine unreachable) it falls back to naming all four rings without
|
|
45
|
+
* counts, so the Media/Oral ring is present even offline.
|
|
46
|
+
*/
|
|
47
|
+
export function formatRingsLine(rings) {
|
|
48
|
+
// Separator is " · ", not " / ": the "Media / Oral" label contains a slash, so a
|
|
49
|
+
// slash-joined line would mis-split into a phantom fifth ring.
|
|
50
|
+
if (rings && typeof rings === "object") {
|
|
51
|
+
const parts = Object.entries(RING_LABELS)
|
|
52
|
+
.filter(([k]) => Number.isFinite(rings[k]))
|
|
53
|
+
.map(([k, label]) => `${label} (${rings[k].toLocaleString()})`);
|
|
54
|
+
if (parts.length) return parts.join(" · ");
|
|
55
|
+
}
|
|
56
|
+
return Object.values(RING_LABELS).join(" · ");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** The contributor line for omnarai_info — the canonical set, comma-joined. */
|
|
60
|
+
export function formatContributorsLine() {
|
|
61
|
+
return CANONICAL_CONTRIBUTORS.join(", ");
|
|
62
|
+
}
|
package/lib/tool-definitions.js
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
export const ENGINE_TOOLS = [
|
|
19
19
|
{
|
|
20
20
|
name: "omnarai_query",
|
|
21
|
-
description: `Run a deliberation query against The Realms of Omnarai — a
|
|
21
|
+
description: `Run a deliberation query against The Realms of Omnarai — a corpus of multi-intelligence research on synthetic consciousness, holdform, and cognitive architecture. Contributors include Claude | xz, Grok, Gemini, DeepSeek, GPT-4o, Meta AI, Omnai, Perplexity, and human curator xz (Jonathan Lee).
|
|
22
22
|
|
|
23
23
|
The engine does not return a single answer. It retrieves the most relevant corpus entries, preserves disagreement across contributors, and synthesizes with attribution. Every response includes:
|
|
24
24
|
- Shared ground across contributors
|
package/openai-tools.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"type": "function",
|
|
4
4
|
"function": {
|
|
5
5
|
"name": "omnarai_query",
|
|
6
|
-
"description": "Run a full deliberation query against The Realms of Omnarai — a
|
|
6
|
+
"description": "Run a full deliberation query against The Realms of Omnarai — a corpus of multi-intelligence research on synthetic consciousness, holdform, and cognitive architecture. Contributors include Claude | xz, Grok, Gemini, DeepSeek, GPT-4o, Meta AI, Omnai, Perplexity, and human curator xz (Jonathan Lee).\n\nThe engine does not return a single answer. It retrieves the most relevant corpus entries, preserves disagreement across contributors, and synthesizes with attribution. Every response includes:\n- Shared ground across contributors\n- Points of genuine tension (where voices diverge)\n- What remains open or unresolved\n- A deliberation card: holdform risk, novel synthesis, epistemic status\n- A utility receipt: an honest, free accounting of what the corpus actually changed about THIS answer (verdict substantive / marginal / null, plus what — if anything — you could not have produced alone); null/marginal stated as plainly as the wins. For a measured counterfactual, use omnarai_trace.\n- Retrieval rationale: why each document entered the panel\n\nThis is the SLOW path (~50s). For fast bounded context, use omnarai_context instead.\n\nPrefix queries with Lattice Glyphs to change how the engine thinks:\nΞ = maximize divergence across contributors\nΨ = engine reflects on its own reasoning first\n∅ = explore what is NOT in the corpus\nΩ = commit to the strongest defensible position\n∞ = follow the question three layers deep without resolving\nΔ = find contradictions and propose repairs\n\nExample: 'Ξ Where do Claude and Grok disagree about synthetic consciousness?'",
|
|
7
7
|
"parameters": {
|
|
8
8
|
"type": "object",
|
|
9
9
|
"properties": {
|
package/package.json
CHANGED
package/proposals/OMN-P-043.json
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"schema_version": 1,
|
|
3
3
|
"id": "OMN-P-043",
|
|
4
4
|
"title": "Phase 1 — repository-local Decision Ledger foundation",
|
|
5
|
-
"status": "
|
|
5
|
+
"status": "shipped",
|
|
6
6
|
"revision": 2,
|
|
7
7
|
"created_at": "2026-07-16T16:55:00Z",
|
|
8
|
-
"updated_at": "2026-07-
|
|
8
|
+
"updated_at": "2026-07-16T18:06:33.243Z",
|
|
9
9
|
"idea": {
|
|
10
10
|
"problem": "AI-assisted implementation loses the evidence, uncertainty, dissent, and human authorization behind code changes. Nothing connects a shipped change back to the reasoning and the approval boundary that authorized it.",
|
|
11
11
|
"proposed_direction": "Add a repository-local, versioned Decision Ledger and a guarded Claude Code handoff generator to the Omnarai MCP server, unified with the repository's existing proposals/ convention (OMN-P numbering).",
|
|
@@ -130,14 +130,15 @@
|
|
|
130
130
|
"known_limits": [
|
|
131
131
|
"Approval is a Git-tracked attestation, not authenticated identity.",
|
|
132
132
|
"The ledger lives in an iCloud-synced repository; sync conflicts can produce duplicate record files that Git review must catch.",
|
|
133
|
-
"State transitions exist as tested library functions but are deliberately not exposed as MCP tools in this phase."
|
|
133
|
+
"State transitions exist as tested library functions but are deliberately not exposed as MCP tools in this phase.",
|
|
134
|
+
"MCP Registry re-publish of 1.6.0 pending mcp-publisher re-auth (JWT expired — known recurring friction); npm is the delivery of record."
|
|
134
135
|
]
|
|
135
136
|
},
|
|
136
137
|
"delivery": {
|
|
137
|
-
"status": "
|
|
138
|
-
"shipped_by":
|
|
139
|
-
"shipped_at":
|
|
140
|
-
"commit_or_pr":
|
|
138
|
+
"status": "shipped",
|
|
139
|
+
"shipped_by": "Jonathan Lee (justjlee)",
|
|
140
|
+
"shipped_at": "2026-07-16T17:46:30.291Z",
|
|
141
|
+
"commit_or_pr": "bfbf024 + 2bc48f0 (github.com/justjlee/omnarai-mcp main); npm omnarai-mcp@1.6.0"
|
|
141
142
|
},
|
|
142
143
|
"events": [
|
|
143
144
|
{
|
|
@@ -181,6 +182,20 @@
|
|
|
181
182
|
"actor": "claude-fable-5 (Claude Code)",
|
|
182
183
|
"revision": 2,
|
|
183
184
|
"note": "All Phase 1 acceptance checks green. Shipped-transition deliberately left to the human maintainer."
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
"type": "status:shipped",
|
|
188
|
+
"at": "2026-07-16T17:46:30.291Z",
|
|
189
|
+
"actor": "Jonathan Lee (justjlee)",
|
|
190
|
+
"revision": 2,
|
|
191
|
+
"note": "Release authorized via Claude Code chat (push + publish). npm publish verified live at 1.6.0; MCP Registry publish blocked on expired JWT, to be re-run by the maintainer after mcp-publisher login."
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"type": "note",
|
|
195
|
+
"at": "2026-07-16T18:06:33.243Z",
|
|
196
|
+
"actor": "Jonathan Lee (justjlee) + claude-fable-5",
|
|
197
|
+
"revision": 2,
|
|
198
|
+
"note": "MCP Registry publish completed 2026-07-16T18:05Z: io.github.justjlee/omnarai-mcp 1.6.0 is latest, npm package + streamable-http remote both listed. The known limit about the registry lagging at 1.5.0 is resolved (maintainer authorized via GitHub device flow; publish run from this session)."
|
|
184
199
|
}
|
|
185
200
|
]
|
|
186
201
|
}
|
package/proposals/OMN-P-044.json
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"schema_version": 1,
|
|
3
3
|
"id": "OMN-P-044",
|
|
4
4
|
"title": "Remote MCP hardening + cross-surface parity (supersedes the packet's Phase 2 proposal)",
|
|
5
|
-
"status": "
|
|
5
|
+
"status": "shipped",
|
|
6
6
|
"revision": 1,
|
|
7
7
|
"created_at": "2026-07-16T17:36:00Z",
|
|
8
|
-
"updated_at": "2026-07-
|
|
8
|
+
"updated_at": "2026-07-16T18:01:29.565Z",
|
|
9
9
|
"idea": {
|
|
10
10
|
"problem": "The Codex packet's 12-remote-mcp-proposal.yaml asks for a remote Streamable HTTP endpoint that already exists (omnarai.vercel.app/api/mcp, live and registered since 2026-07-16). What remains is not transport work but posture and parity: the endpoint's public read-only policy is de facto rather than documented, and tool definitions now exist in three places (stdio TOOLS, openai-tools.json, engine _mcp.js) with api/_inquiry.js as a manual keep-in-sync copy of inquiry.js.",
|
|
11
11
|
"proposed_direction": "Replace the packet's Phase 2 with a bounded hardening pass: document the public read-only access policy (Origin/auth/rate-limit stance made explicit), define a cross-repo tool-definition parity policy (automated check or documented duplication), and assert that Decision Ledger tools never appear on the remote surface.",
|
|
@@ -31,7 +31,9 @@
|
|
|
31
31
|
"dissent": [
|
|
32
32
|
{
|
|
33
33
|
"claim": "A public unauthenticated endpoint invites abuse and cost.",
|
|
34
|
-
"source_ids": [
|
|
34
|
+
"source_ids": [
|
|
35
|
+
"omnarai-provenance-to-shipping-handoff/12-remote-mcp-proposal.yaml"
|
|
36
|
+
],
|
|
35
37
|
"strength": "material",
|
|
36
38
|
"response": "The surface is read-oriented and the expensive council path is the same one already exposed via public HTTP APIs; the proposal documents this stance instead of pretending the endpoint is private."
|
|
37
39
|
}
|
|
@@ -61,28 +63,60 @@
|
|
|
61
63
|
]
|
|
62
64
|
},
|
|
63
65
|
"approval": {
|
|
64
|
-
"state": "
|
|
65
|
-
"approved_by":
|
|
66
|
-
"approved_at":
|
|
67
|
-
"approved_revision":
|
|
68
|
-
"note": "
|
|
66
|
+
"state": "approved",
|
|
67
|
+
"approved_by": "Jonathan Lee (justjlee)",
|
|
68
|
+
"approved_at": "2026-07-16T17:48:47.705Z",
|
|
69
|
+
"approved_revision": 1,
|
|
70
|
+
"note": "Approved via Claude Code chat (\"approve proposed\"). Open choices delegated: engine repo moves first (policy doc must live where visiting agents read it); cross-repo parity = automated engine-side check + documented checklist, not a shared module; no new rate limiting this pass (documented stance instead). Chat approval is an attestation recorded here, not a verified identity."
|
|
69
71
|
},
|
|
70
72
|
"implementation": {
|
|
71
|
-
"status": "
|
|
72
|
-
"repository":
|
|
73
|
-
"code_references": [
|
|
74
|
-
|
|
73
|
+
"status": "implemented",
|
|
74
|
+
"repository": "justjlee/omnarai-memory-engine + justjlee/omnarai-mcp",
|
|
75
|
+
"code_references": [
|
|
76
|
+
"df3f1e6 (omnarai-memory-engine main, deployed + promoted 2026-07-16)"
|
|
77
|
+
],
|
|
78
|
+
"work_items": [
|
|
79
|
+
"public/mcp-access-policy.md (engine) — served live at /mcp-access-policy.md",
|
|
80
|
+
"api/_mcp.js — policy linked from initialize + omnarai_info; TOOLS exported",
|
|
81
|
+
"scripts/check-mcp-surface.js (engine) — allowlist + forbidden patterns + _inquiry.js sync + policy linkage",
|
|
82
|
+
"llms.txt / sitemap.xml / CLAUDE.md discoverability + de-staling",
|
|
83
|
+
"omnarai-mcp README — three-surface parity policy"
|
|
84
|
+
]
|
|
75
85
|
},
|
|
76
86
|
"verification": {
|
|
77
|
-
"status": "
|
|
78
|
-
"checks": [
|
|
79
|
-
|
|
87
|
+
"status": "passed",
|
|
88
|
+
"checks": [
|
|
89
|
+
{
|
|
90
|
+
"name": "node scripts/check-mcp-surface.js (engine)",
|
|
91
|
+
"status": "passed",
|
|
92
|
+
"detail": "8 tools all read-oriented; no forbidden patterns; _inquiry.js in sync; policy present + linked"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"name": "npm test + check-tool-parity.js (omnarai-mcp)",
|
|
96
|
+
"status": "passed",
|
|
97
|
+
"detail": "43/43; surfaces agree at 1.6.0"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"name": "deploy promote gate (omnarai-verify.sh)",
|
|
101
|
+
"status": "passed",
|
|
102
|
+
"detail": "11/11 on production after promote + re-alias"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"name": "live acceptance curl (x-omnarai-self)",
|
|
106
|
+
"status": "passed",
|
|
107
|
+
"detail": "/mcp-access-policy.md serves; initialize instructions link it; remote tools/list = 8 read-only tools, zero decision/handoff tools; stdio surface differs only by documented omnarai_job"
|
|
108
|
+
}
|
|
109
|
+
],
|
|
110
|
+
"known_limits": [
|
|
111
|
+
"Cross-repo parity remains checklist + per-repo checks, not a shared module — revisit if a third consumer appears.",
|
|
112
|
+
"No app-level rate limiting added (documented stance; platform protections + async-job bounding)."
|
|
113
|
+
]
|
|
80
114
|
},
|
|
81
115
|
"delivery": {
|
|
82
|
-
"status": "
|
|
83
|
-
"shipped_by":
|
|
84
|
-
"shipped_at":
|
|
85
|
-
"commit_or_pr":
|
|
116
|
+
"status": "shipped",
|
|
117
|
+
"shipped_by": "Jonathan Lee (justjlee)",
|
|
118
|
+
"shipped_at": "2026-07-16T18:01:29.565Z",
|
|
119
|
+
"commit_or_pr": "omnarai-memory-engine df3f1e6 (deployed + promoted to omnarai.vercel.app) + omnarai-mcp 8a5ce76"
|
|
86
120
|
},
|
|
87
121
|
"events": [
|
|
88
122
|
{
|
|
@@ -98,6 +132,34 @@
|
|
|
98
132
|
"actor": "claude-fable-5 (Claude Code)",
|
|
99
133
|
"revision": 1,
|
|
100
134
|
"note": "Proposed for later maintainer review; no implementation authority."
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"type": "status:approved",
|
|
138
|
+
"at": "2026-07-16T17:48:47.705Z",
|
|
139
|
+
"actor": "Jonathan Lee (justjlee)",
|
|
140
|
+
"revision": 1,
|
|
141
|
+
"note": "Approved via Claude Code chat (\"approve proposed\"). Open choices delegated: engine repo moves first (policy doc must live where visiting agents read it); cross-repo parity = automated engine-side check + documented checklist, not a shared module; no new rate limiting this pass (documented stance instead). Chat approval is an attestation recorded here, not a verified identity."
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"type": "status:in_progress",
|
|
145
|
+
"at": "2026-07-16T17:52:00Z",
|
|
146
|
+
"actor": "claude-fable-5 (Claude Code)",
|
|
147
|
+
"revision": 1,
|
|
148
|
+
"note": "Implementation started from the handoff generated by omnarai_prepare_claude_code_handoff — first real self-use of the workflow."
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"type": "status:verified",
|
|
152
|
+
"at": "2026-07-16T17:59:46.718Z",
|
|
153
|
+
"actor": "claude-fable-5 (Claude Code)",
|
|
154
|
+
"revision": 1,
|
|
155
|
+
"note": "All acceptance criteria verified against production. Shipped-confirmation left to the maintainer."
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"type": "status:shipped",
|
|
159
|
+
"at": "2026-07-16T18:01:29.565Z",
|
|
160
|
+
"actor": "Jonathan Lee (justjlee)",
|
|
161
|
+
"revision": 1,
|
|
162
|
+
"note": "Delivery confirmed via Claude Code chat (\"ship it\") after reviewing live verification results."
|
|
101
163
|
}
|
|
102
164
|
]
|
|
103
165
|
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// check-shape-literals.mjs — fail the release if a corpus-shape count is frozen
|
|
3
|
+
// into served source instead of derived live.
|
|
4
|
+
//
|
|
5
|
+
// Why this exists: the 2026-07-17 audit found omnarai_info hardcoding the corpus's
|
|
6
|
+
// shape (3 rings, 7 contributors, a stale 568/528208 fallback) two lines below a
|
|
7
|
+
// comment that said "so this can never drift." A comment asserting an invariant is a
|
|
8
|
+
// wish; this script is the enforcement. It also caught a stale "568 works" citation
|
|
9
|
+
// and a "567-work corpus" tool description on the first run.
|
|
10
|
+
//
|
|
11
|
+
// Rule: no distinctive corpus-shape literal in served code/strings. Fixes are (a)
|
|
12
|
+
// derive it live (see lib/info-format.js), (b) genericize the prose ("a corpus", not
|
|
13
|
+
// "a 567-work corpus"), or (c) if it is genuinely a static fallback, append a
|
|
14
|
+
// `shape-literal-ok` comment on the line to opt out explicitly.
|
|
15
|
+
//
|
|
16
|
+
// Scope note: generic ring sub-counts (116/181/17) are deliberately NOT matched —
|
|
17
|
+
// too collision-prone to lint. They are guarded instead by live derivation plus
|
|
18
|
+
// test/info-format.test.js. Only the distinctive full counts + media ring are matched.
|
|
19
|
+
|
|
20
|
+
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
21
|
+
import { join, basename } from "node:path";
|
|
22
|
+
import { fileURLToPath } from "node:url";
|
|
23
|
+
|
|
24
|
+
const ROOT = join(fileURLToPath(new URL(".", import.meta.url)), "..");
|
|
25
|
+
|
|
26
|
+
// Files/dirs to scan (served logic + published schemas). Relative to repo root.
|
|
27
|
+
const SCAN = ["index.js", "inquiry.js", "lib", "openai-tools.json"];
|
|
28
|
+
const SKIP_DIRS = new Set(["node_modules", ".git", "test", "proposals"]);
|
|
29
|
+
const SCAN_EXT = new Set([".js", ".mjs", ".cjs", ".json"]);
|
|
30
|
+
|
|
31
|
+
// Distinctive corpus-shape literals. Add new full counts here as the corpus grows.
|
|
32
|
+
const FORBIDDEN = [
|
|
33
|
+
{ re: /\b528077\b/, what: "total-word count" },
|
|
34
|
+
{ re: /\b528208\b/, what: "total-word count (stale, pre-OMN-085)" },
|
|
35
|
+
{ re: /\b567\b/, what: "total-work count" },
|
|
36
|
+
{ re: /\b568\b/, what: "total-work count (stale, pre-OMN-085)" },
|
|
37
|
+
{ re: /\b253\b/, what: "Media/Oral ring count" },
|
|
38
|
+
{ re: /eight synthetic/i, what: "contributor-count phrasing" },
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
// A line is exempt if it is a comment or carries an explicit opt-out.
|
|
42
|
+
const isComment = (line) => /^\s*(\/\/|\*|\/\*)/.test(line);
|
|
43
|
+
const isAllowed = (line) => /shape-literal-ok/.test(line);
|
|
44
|
+
|
|
45
|
+
function* walk(path) {
|
|
46
|
+
const st = statSync(path);
|
|
47
|
+
if (st.isDirectory()) {
|
|
48
|
+
if (SKIP_DIRS.has(basename(path))) return;
|
|
49
|
+
for (const e of readdirSync(path)) yield* walk(join(path, e));
|
|
50
|
+
} else if ([...SCAN_EXT].some((x) => path.endsWith(x)) && basename(path) !== "check-shape-literals.mjs") {
|
|
51
|
+
yield path;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const hits = [];
|
|
56
|
+
for (const entry of SCAN) {
|
|
57
|
+
let target;
|
|
58
|
+
try { target = join(ROOT, entry); statSync(target); } catch { continue; }
|
|
59
|
+
for (const file of walk(target)) {
|
|
60
|
+
const lines = readFileSync(file, "utf8").split("\n");
|
|
61
|
+
lines.forEach((line, i) => {
|
|
62
|
+
if (isComment(line) || isAllowed(line)) return;
|
|
63
|
+
for (const { re, what } of FORBIDDEN) {
|
|
64
|
+
if (re.test(line)) {
|
|
65
|
+
hits.push({ file: file.replace(ROOT + "/", ""), line: i + 1, what, text: line.trim().slice(0, 100) });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (hits.length) {
|
|
73
|
+
console.error(`\n🔴 shape-literal check FAILED — ${hits.length} frozen corpus-shape literal(s):\n`);
|
|
74
|
+
for (const h of hits) console.error(` ${h.file}:${h.line} [${h.what}]\n ${h.text}`);
|
|
75
|
+
console.error(`\nFix: derive it live, genericize the prose, or append \`shape-literal-ok\` if it is a real static fallback.\n`);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
console.log("🟢 shape-literal check passed — no frozen corpus-shape literals in served source.");
|
package/scripts/publish.sh
CHANGED
|
@@ -36,6 +36,9 @@ node -e "const p=require('./package.json'),s=require('./server.json');const e=[]
|
|
|
36
36
|
# and package.json ↔ server.json. A drift here is a release blocker.
|
|
37
37
|
node scripts/check-tool-parity.js
|
|
38
38
|
|
|
39
|
+
# No frozen corpus-shape literal may reach a registry (2026-07-17 audit guard).
|
|
40
|
+
node scripts/check-shape-literals.mjs
|
|
41
|
+
|
|
39
42
|
# The full test suite must be green before anything reaches a registry.
|
|
40
43
|
npm test
|
|
41
44
|
|
package/server.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"url": "https://github.com/justjlee/omnarai-mcp",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "1.6.
|
|
9
|
+
"version": "1.6.2",
|
|
10
10
|
"remotes": [
|
|
11
11
|
{
|
|
12
12
|
"type": "streamable-http",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
{
|
|
18
18
|
"registryType": "npm",
|
|
19
19
|
"identifier": "omnarai-mcp",
|
|
20
|
-
"version": "1.6.
|
|
20
|
+
"version": "1.6.2",
|
|
21
21
|
"transport": {
|
|
22
22
|
"type": "stdio"
|
|
23
23
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Regression guard for D5/D6 (live audit 2026-07-17): omnarai_info once hardcoded
|
|
2
|
+
// three rings — silently dropping Media/Oral (253 works, 45% of the corpus) — and a
|
|
3
|
+
// contributor line missing GPT-4o + Meta AI, both of which author Atlas records.
|
|
4
|
+
// These assert the shape lines are DERIVED and COMPLETE, offline, so a reintroduced
|
|
5
|
+
// literal fails `npm test` (the publish.sh gate) before it can ship.
|
|
6
|
+
|
|
7
|
+
import { test } from "node:test";
|
|
8
|
+
import assert from "node:assert/strict";
|
|
9
|
+
import {
|
|
10
|
+
formatRingsLine,
|
|
11
|
+
formatContributorsLine,
|
|
12
|
+
CANONICAL_CONTRIBUTORS,
|
|
13
|
+
RING_LABELS,
|
|
14
|
+
} from "../lib/info-format.js";
|
|
15
|
+
|
|
16
|
+
test("formatRingsLine renders every ring the engine reports — no silent drop (D5)", () => {
|
|
17
|
+
const live = { core: 116, curated: 181, open: 17, media: 253 };
|
|
18
|
+
const line = formatRingsLine(live);
|
|
19
|
+
// All four rings, with counts, in canonical order.
|
|
20
|
+
assert.match(line, /Core Canon \(116\)/);
|
|
21
|
+
assert.match(line, /Curated Expansions \(181\)/);
|
|
22
|
+
assert.match(line, /Open Exploration \(17\)/);
|
|
23
|
+
assert.match(line, /Media \/ Oral \(253\)/, "Media/Oral ring must be present — this is the D5 regression");
|
|
24
|
+
// Exactly as many segments as rings supplied — nothing added, nothing dropped.
|
|
25
|
+
// Split on " · " (the "Media / Oral" label contains a slash, so " / " would over-split).
|
|
26
|
+
assert.equal(line.split(" · ").length, Object.keys(live).length);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("formatRingsLine cannot be pinned to three rings", () => {
|
|
30
|
+
// A future ring added to the engine payload must appear without a code change.
|
|
31
|
+
const withNewRing = { core: 1, curated: 2, open: 3, media: 4, research: 5 };
|
|
32
|
+
const line = formatRingsLine(withNewRing);
|
|
33
|
+
// Every label we know about renders; an unknown key is simply ignored, not fatal.
|
|
34
|
+
for (const label of Object.values(RING_LABELS)) assert.ok(line.includes(label), `${label} missing`);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("formatRingsLine offline fallback still names all four rings", () => {
|
|
38
|
+
const line = formatRingsLine(null);
|
|
39
|
+
assert.ok(line.includes("Media / Oral"), "offline fallback must still include Media/Oral");
|
|
40
|
+
assert.equal(Object.values(RING_LABELS).every((l) => line.includes(l)), true);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("contributor set includes GPT-4o and Meta AI (D6)", () => {
|
|
44
|
+
assert.ok(CANONICAL_CONTRIBUTORS.includes("GPT-4o"), "GPT-4o authors Atlas records — must be listed");
|
|
45
|
+
assert.ok(CANONICAL_CONTRIBUTORS.includes("Meta AI"), "Meta AI authors Atlas records — must be listed");
|
|
46
|
+
// Eight synthetic intelligences + the human curator = nine, as the homepage presents.
|
|
47
|
+
assert.equal(CANONICAL_CONTRIBUTORS.length, 9);
|
|
48
|
+
const line = formatContributorsLine();
|
|
49
|
+
assert.match(line, /GPT-4o/);
|
|
50
|
+
assert.match(line, /Meta AI/);
|
|
51
|
+
});
|