0xray 4.0.41 → 4.1.0
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/.grok-plugin/plugin.json +1 -1
- package/.opencode/skills/orchestrator/SKILL.md +12 -0
- package/.plugin/plugin.json +1 -1
- package/.xray/features.json +5 -5
- package/.xray/features.schema.json +1 -1
- package/AGENTS-consumer.md +10 -6
- package/AGENTS.md +19 -8
- package/LICENSE +1 -1
- package/README.md +65 -19
- package/SKILLS.md +5 -1
- package/dist/AGENTS.md +19 -8
- package/dist/CHANGELOG.md +85 -0
- package/dist/LICENSE +1 -1
- package/dist/README.md +65 -19
- package/dist/SKILLS.md +5 -1
- package/dist/cli/commands/openclaw-install.js +1 -1
- package/dist/cli/commands/plugin-commands.d.ts +4 -0
- package/dist/cli/commands/plugin-commands.js +84 -41
- package/dist/cli/index.js +12 -0
- package/dist/core/config-loader.js +4 -4
- package/dist/core/features-config.d.ts +1 -1
- package/dist/core/features-config.js +3 -3
- package/dist/enforcement/index.d.ts +4 -0
- package/dist/enforcement/index.js +4 -0
- package/dist/enforcement/validators/code-quality-validators.js +6 -4
- package/dist/governance/llm-governance-provider.d.ts +7 -1
- package/dist/governance/llm-governance-provider.js +72 -14
- package/dist/governance/local-confer.d.ts +4 -1
- package/dist/governance/local-confer.js +22 -1
- package/dist/integrations/cursor/hooks/hooks.json +6 -3
- package/dist/integrations/cursor/hooks/pre-tool-use.js +100 -37
- package/dist/integrations/cursor/hooks/xray-cloud-hook.sh +9 -1
- package/dist/integrations/grok/grok-cli.js +10 -37
- package/dist/integrations/grok/hooks/grok-hook-utils.js +8 -1
- package/dist/integrations/grok/hooks/pre-tool-use.js +2 -58
- package/dist/integrations/hermes-agent/bridge.mjs +14 -1
- package/dist/integrations/hooks/confer-hook-runtime.mjs +23 -1
- package/dist/integrations/hooks/delegation-gate-runtime.mjs +3 -2
- package/dist/integrations/hooks/goggles-mcp.mjs +35 -17
- package/dist/integrations/hooks/goggles-pipeline.mjs +46 -1
- package/dist/integrations/hooks/goggles-planes.json +11 -7
- package/dist/integrations/hooks/pre-tool-speak.mjs +76 -0
- package/dist/integrations/openclaw/hooks/pre-tool-gate-runtime.mjs +21 -4
- package/dist/integrations/openclaw/plugin/xray-pre-tool/index.js +17 -2
- package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
- package/dist/mcps/architect-tools.server.d.ts +6 -0
- package/dist/mcps/architect-tools.server.js +19 -2
- package/dist/mcps/config/server-config-registry.js +8 -6
- package/dist/mcps/governance.server.d.ts +1 -0
- package/dist/mcps/governance.server.js +46 -0
- package/dist/mcps/knowledge-skills/code-review.server.js +7 -0
- package/dist/mcps/knowledge-skills/security-audit.server.js +5 -3
- package/dist/mcps/mcp-client.js +1 -1
- package/dist/mcps/orchestrator/handlers/complexity-handler.js +2 -2
- package/dist/mcps/researcher.server.js +12 -3
- package/dist/monitoring/{nudge-watchdog.d.ts → nudge-monitor.d.ts} +14 -5
- package/dist/monitoring/{nudge-watchdog.js → nudge-monitor.js} +42 -17
- package/dist/nucleus/autonomy-kernel.d.ts +2 -0
- package/dist/nucleus/autonomy-kernel.js +17 -13
- package/dist/nucleus/confer-host.d.ts +35 -0
- package/dist/nucleus/confer-host.js +55 -0
- package/dist/nucleus/confer.d.ts +19 -3
- package/dist/nucleus/confer.js +111 -55
- package/dist/nucleus/lead-dev-plan-persistence.js +4 -2
- package/dist/nucleus/suit-temperament.d.ts +1 -1
- package/dist/nucleus/suit-temperament.js +2 -2
- package/dist/nucleus/synthesis-consult-receipt.d.ts +7 -1
- package/dist/nucleus/synthesis-consult-receipt.js +86 -35
- package/dist/plugin/xray-codex-injection.js +18 -0
- package/dist/processors/implementations/nudge-processor.d.ts +1 -1
- package/dist/processors/implementations/nudge-processor.js +4 -4
- package/dist/reporting/framework-reporting-system.js +2 -5
- package/dist/reporting/log-parser.d.ts +2 -0
- package/dist/reporting/log-parser.js +7 -6
- package/dist/skills/orchestrator/SKILL.md +12 -0
- package/docs-site/docs/plates/activity-log.md +1 -1
- package/docs-site/docs/plates/bifrost.md +48 -0
- package/docs-site/docs/plates/boot.md +2 -2
- package/docs-site/docs/plates/centrifuge.md +1 -1
- package/docs-site/docs/plates/cursor-compact.md +1 -1
- package/docs-site/docs/plates/glossary.md +7 -3
- package/docs-site/docs/plates/goggles.md +13 -2
- package/docs-site/docs/plates/governance.md +1 -1
- package/docs-site/docs/plates/grok-compact.md +1 -1
- package/docs-site/docs/plates/grokbot.md +3 -1
- package/docs-site/docs/plates/host-pack.md +1 -1
- package/docs-site/docs/plates/house.md +1 -1
- package/docs-site/docs/plates/index.md +4 -2
- package/docs-site/docs/plates/inference-files.md +1 -1
- package/docs-site/docs/plates/kept-line.md +1 -1
- package/docs-site/docs/plates/kits.md +1 -1
- package/docs-site/docs/plates/lens-gate.md +3 -1
- package/docs-site/docs/plates/lens-page.md +1 -1
- package/docs-site/docs/plates/memory-recall.md +1 -1
- package/docs-site/docs/plates/notes-page.md +2 -2
- package/docs-site/docs/plates/orchestration.md +1 -1
- package/docs-site/docs/plates/package-face.md +1 -1
- package/docs-site/docs/plates/payload-heat.md +1 -1
- package/docs-site/docs/plates/pickup-stamp.md +1 -1
- package/docs-site/docs/plates/pre-tool.md +1 -1
- package/docs-site/docs/plates/processor.md +1 -1
- package/docs-site/docs/plates/record-map.md +1 -1
- package/docs-site/docs/plates/reflection-page.md +1 -1
- package/docs-site/docs/plates/reporting.md +1 -1
- package/docs-site/docs/plates/review.md +1 -1
- package/docs-site/docs/plates/routing.md +1 -1
- package/docs-site/docs/plates/session-capture.md +1 -1
- package/docs-site/docs/plates/site-manual.md +1 -1
- package/docs-site/docs/plates/stamp-plate.md +1 -1
- package/docs-site/docs/plates/station-card.md +1 -1
- package/docs-site/docs/plates/station-heat.md +1 -1
- package/docs-site/docs/plates/suit-organs.md +1 -1
- package/docs-site/docs/plates/suit-settings.md +1 -1
- package/docs-site/docs/plates/suit-wear.md +1 -1
- package/docs-site/docs/plates/suit.md +3 -3
- package/docs-site/docs/plates/trail-state.md +1 -1
- package/docs-site/docs/plates/work-fresh.md +1 -1
- package/docs-site/docs/plates/write-home.md +1 -1
- package/llms.txt +16 -6
- package/package.json +4 -4
- package/scripts/foundry/README.md +2 -2
- package/scripts/foundry/release-gate.mjs +111 -15
- package/scripts/foundry/release.mjs +8 -0
- package/scripts/mjs/verify-confer-core.mjs +153 -29
- package/scripts/mjs/verify-pipeline-facets.mjs +1 -1
- package/scripts/mjs/verify-user-aside-core.mjs +3 -4
- package/scripts/node/bridge-mcp-wiring.cjs +236 -5
- package/scripts/node/confer-switch.cjs +66 -0
- package/scripts/node/install-bridges.cjs +44 -53
- package/scripts/node/pack-tmp-suit-proof.mjs +14 -6
- package/src/integrations/openclaw/plugin/xray-pre-tool/index.js +17 -2
- package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
- package/src/mcps/architect-tools.server.ts +26 -2
- package/src/mcps/config/__tests__/server-config-registry.test.ts +15 -6
- package/src/mcps/config/server-config-registry.ts +9 -6
- package/src/mcps/governance.server.ts +49 -0
- package/src/mcps/knowledge-skills/code-review.server.ts +8 -0
- package/src/mcps/knowledge-skills/security-audit.server.ts +11 -12
- package/src/mcps/mcp-client.ts +1 -1
- package/src/mcps/orchestrator/handlers/complexity-handler.ts +2 -1
- package/src/mcps/researcher.server.ts +19 -10
- package/src/skills/orchestrator/SKILL.md +12 -0
- package/vendor/@0xray/repertoire/README.md +1 -1
- package/vendor/@0xray/repertoire/scripts/run-live-synthesis-checkpoint.mjs +5 -51
- package/xray/agents_template.md +2 -2
- package/xray/features.json +5 -5
- package/xray/features.schema.json +1 -1
- package/docs-site/docs/plates/live-mesh.md +0 -41
package/dist/README.md
CHANGED
|
@@ -1,37 +1,45 @@
|
|
|
1
|
-
# xray —
|
|
1
|
+
# xray — a suit for coding agents
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+

|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**4.1** — a suit that survives the context window
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Bifrost is the live board. Goggles reads one named plane.
|
|
8
|
+
|
|
9
|
+
0xRay is a three-subsystem autonomous engine. The suit is the wear. Inference remembers. External Governance judges. The Autonomous Engine runs the work. The host you already run wears it: Grok, OpenCode, Hermes, OpenClaw, or Cursor. Memory, judgement, and payments come on with the suit. When the window closes, the next session wakes with the job, the page, and the laws.
|
|
10
|
+
|
|
11
|
+
Bifrost turns each pull request, issue, and comment into one card and a line in the right seat's inbox, then wakes that seat. Confer still completes only on a real yes. A foundry is built from mills and hangars. The mill builds and ships. The hangar is the shop.
|
|
12
|
+
|
|
13
|
+
The product is the **skeleton you wear**.
|
|
8
14
|
|
|
9
15
|
## Your AI Power Suit
|
|
10
16
|
|
|
11
17
|
**Your AI Power ⚡️ Suit 🦾** — an exoskeleton that blocks AI slop from becoming real damage.
|
|
12
18
|
|
|
13
|
-
- **Bone** — three-subsystem
|
|
19
|
+
- **Bone** — three-subsystem engine: Inference · External Governance (Dynamo / Codex) · Autonomous Engine (thinDispatch)
|
|
14
20
|
- **Always on** — Codex 11 / 29 / 69, destructive shell, no new MCP/skill/handler surface
|
|
15
21
|
- **Temperament** — `frontier` | `guided` | `strict` | `auto` — how loud the engine is, not whether governance exists
|
|
16
22
|
- **Wear** — Grok, OpenCode, Hermes, OpenClaw, plus Cursor project hooks. One SSOT gate
|
|
17
|
-
- **Muscle** — **Repertoire is preferred.** Vendored 0.2.9 ships **on**. Dest is named laws, not hangar `repo-*` or git slugs. Station is the
|
|
23
|
+
- **Muscle** — **Repertoire is preferred.** Vendored 0.2.9 ships **on**. Dest is named laws, not hangar `repo-*` or git slugs. Station is the wake ticket — not a substitute for Repertoire.
|
|
18
24
|
|
|
19
25
|
```bash
|
|
20
26
|
npm install 0xray
|
|
27
|
+
npx 0xray wear
|
|
21
28
|
```
|
|
22
29
|
|
|
23
|
-
|
|
30
|
+
`npm install 0xray` links vendored `@0xray/repertoire` and prints `npx 0xray wear`. It does not write `.mcp.json` or the chat bridges. Wear writes the consumer suit: managed `AGENTS.md`, `.xray` config, seven MCP servers, and the OpenCode, Grok, Hermes, and OpenClaw bridges (`install-bridges.cjs`). Inside a git checkout, wear also fastens Cursor project hooks. **Repertoire is preferred** — vendored **0.2.9** ships on: factory + stack laws, in-process routing, extra host MCP `repertoire`. Not an eighth `xray-*` server. Dest is a judgment index. Explicit opt-out only: `"enabled": false, "provider": "repertoire"`. Do not pin 0.1.8.
|
|
24
31
|
|
|
25
32
|
## Quick Start
|
|
26
33
|
|
|
27
34
|
```bash
|
|
28
|
-
npm install 0xray
|
|
29
|
-
npx 0xray
|
|
30
|
-
npx 0xray
|
|
35
|
+
npm install 0xray
|
|
36
|
+
npx 0xray wear
|
|
37
|
+
npx 0xray status
|
|
38
|
+
npx 0xray setup --git-hooks # optional: git hooks only
|
|
31
39
|
npx @0xray/foundry inspect --skip-live # mill receipt (chat is not a receipt)
|
|
32
40
|
```
|
|
33
41
|
|
|
34
|
-
Manual per-platform install (idempotent, same
|
|
42
|
+
Manual per-platform install (idempotent, same bridges wear writes):
|
|
35
43
|
|
|
36
44
|
```bash
|
|
37
45
|
npx 0xray opencode install
|
|
@@ -51,12 +59,50 @@ Docs: [guides/autonomy-command](docs-site/docs/guides/autonomy-command.md) · Sk
|
|
|
51
59
|
|
|
52
60
|
| Version | Highlights |
|
|
53
61
|
|---------|------------|
|
|
54
|
-
| **
|
|
62
|
+
| **4.1.0** | Bifrost is the collector board. A cloud agent is a board row. A stuck card's L2 nudge goes to the CoS role. `live-inbox` requires `LIVE_URL`, `SEAT_KEYS_DIR`, and `LIVE_CURSORS`. Goggles reads one named plane. |
|
|
63
|
+
| **4.0.43** | Confer completes only on a real PASS. Cursor gate events fail closed, except EACCES when a cloud wrapper cannot write dest. Gate C cannot be skipped. |
|
|
64
|
+
| **4.0.42** | Confer votes. Burst runs the swarm. |
|
|
65
|
+
| **4.0.41** | Wake cascade stays on the station module. A fresh wear fastens mill and inspect. Goggles records the worn package path. The live page plays the mesh in the browser. |
|
|
66
|
+
| **4.0.40** | Live mesh runs the full loop: feed watch, render, direction, deploy, health, and the ledger both ways. |
|
|
67
|
+
| **4.0.39** | The seven stack laws stay worn. Repertoire in the suit is 0.2.9. |
|
|
68
|
+
| **4.0.38** | Codex term 70 requires the current source and the worn npm package. Dynamo's recommendation is honored. |
|
|
69
|
+
| **4.0.37** | A naked checkout wakes with repertoire on. |
|
|
70
|
+
| **4.0.36** | Goggles holds the stop through search, read, and a dist wipe. |
|
|
71
|
+
| **4.0.35** | Wear rewrites a checkout `dist/cli` launch to `node_modules/0xray`. |
|
|
72
|
+
| **4.0.34** | The lens stays on the worn build when the source is not packed. |
|
|
73
|
+
| **4.0.33** | Version bump. |
|
|
74
|
+
| **4.0.32** | `0xray look` opens one plane. Digest and triage return the card. Calling and confer stay off. |
|
|
75
|
+
| **4.0.31** | Goggles looks at one pipeline. Kind 0 stays quiet when the worn list matches the map. Calling and confer stay off. |
|
|
55
76
|
| **4.0.30** | Fixes 4.0.29: `npx 0xray wear` and `setup` work outside a git checkout again. They write the 4.0.28 project setup, skip only Cursor hooks, and print one warning. Inside a git checkout they restore the 4.0.28 project setup, and `wear` adds Cursor hooks plus the unwear snapshot. Companion `@0xray/grok-bot` 0.1.8. Released 2026-09-28. |
|
|
56
77
|
| **4.0.29** | `npm install` only creates the relative `node_modules/@0xray/repertoire` link to the vendored repertoire and prints `npx 0xray wear`. Run `npx 0xray wear` after install. Wear writes only the consumer project's `.cursor/hooks.json` (installed dist hooks, beside user entries); `npx 0xray unwear` restores the snapshot. Companion `@0xray/grok-bot` 0.1.8. Released 2026-09-28. |
|
|
57
78
|
| **4.0.28** | MCP servers start through `scripts/node/mcp-launch.cjs` and only see PATH, HOME, XRAY_ROOT, plus names on their keep list. Tokens such as NPM_TOKEN are not inherited. User env values stay out of argv. Postinstall keeps user edits to AGENTS.md, .mcp.json, and opencode.json. `house init` does not copy EXAMPLE.md; doctor FAILs while `house/EXAMPLE.md` exists. Inspect adds a machinePlugin check. The Cursor hook defaults XRAY_ROOT to the suit. Companion `@0xray/grok-bot` 0.1.7. Released 2026-09-27. |
|
|
58
79
|
| **4.0.27** | Host compact proof needs a generation id and a numeric usage percent, and the same preCompact receipt is mirrored to nested consumer wear roots. Memory scoring: [docs/memory-scoring.md](docs/memory-scoring.md) (orchestrator links it). Companion `@0xray/grok-bot` 0.1.6: general page vs `house/` overlay, `templates/house/`, `grok-bot house init`, doctor `GROK_BOT_HOUSE` or walk-up. Released 2026-09-26. |
|
|
80
|
+
| **4.0.26** | A lesson is stored when the task matches no signal. A Cursor compact cut is proved with a session log and a per-session receipt. |
|
|
81
|
+
| **4.0.25** | Plate schematics ship in the package. A worn suit resolves them from `dist/integrations/hooks/plates.cjs`. |
|
|
82
|
+
| **4.0.24** | Compaction and a host change are the same cut. The station card is the handoff. Repertoire in that suit is 0.2.8. |
|
|
83
|
+
| **4.0.23** | The Dynamo client starts when external governance is required. Proposals score locally when that governance is off. |
|
|
84
|
+
| **4.0.22** | The stamper strips present-tense patch pins from shipped prose. The cursor gate follows the suit mill. |
|
|
85
|
+
| **4.0.21** | Dest is named laws, not hangar slugs. Cleanup heat grows the project copy when Repertoire is on. |
|
|
86
|
+
| **4.0.20** | Heat grows the project copy. Session boot rewrites when HEAD moves. |
|
|
87
|
+
| **4.0.19** | Vendored Repertoire 0.2.5. Wear replaces older leftovers. |
|
|
88
|
+
| **4.0.18** | Wake heat joins bookmark, index, and mind. |
|
|
89
|
+
| **4.0.17** | Cursor heat writes session files when HEAD moves. |
|
|
90
|
+
| **4.0.16** | `npx 0xray validate` is a wear check. |
|
|
91
|
+
| **4.0.15** | Fasten is **foundry-plant/0**: builtin plant is mill+inspect only. `foundry.json` `"plant": "@0xray/blip"` (aliases `"plant": "blip"` / `"plant": "sound"`) fastens whatever that mill declares (looker / vibe / mixer live in the mill). Nested mill `@0xray/foundry@0.1.12`. CLI shims `foundry blip\|sound` remain (0.1.11+). Shop plant first-class (`shop-extract`, `shop-witness`, `shop-pin` + `foundry.json` `shopPlant`). |
|
|
92
|
+
| **4.0.14** | Factory-blip beds stamp the hook cell and keep six tellable bodies. |
|
|
93
|
+
| **4.0.13** | Station PreCompact merge keeps custom STATION.md keys. |
|
|
94
|
+
| **4.0.12** | Project-scoped Grok plugin dest so multi-seat wear does not clobber the machine plugin. |
|
|
95
|
+
| **4.0.11** | The npm pack includes `.grok-plugin/` so the Grok marketplace manifest ships. |
|
|
96
|
+
| **4.0.10** | Version bump. |
|
|
59
97
|
| **4.0.9** | Mill target: postinstall does not mill npm global prefix or `_npx` as a consumer. Isolated HOME skips machine `~/.grok`. |
|
|
98
|
+
| **4.0.8** | Confer abstains locally instead of rubber-stamping a proposal. |
|
|
99
|
+
| **4.0.7** | Nested mill 0.1.9. Inventory writes `dna`. The mill does not mint on chain. |
|
|
100
|
+
| **4.0.6** | Nested mill 0.1.8. Isolated HOME skips machine Hermes and OpenClaw. |
|
|
101
|
+
| **4.0.5** | Inspect is a mill command. A costume dump fails mint. Mill plant stays mill + inspect. |
|
|
102
|
+
| **4.0.4** | Mill fastens an inspect suit. Costume is opt-in with `foundry.json` `"costume": true`. |
|
|
103
|
+
| **4.0.3** | Their plant is the suit. The mill plant is the factory discipline on the hanger. |
|
|
104
|
+
| **4.0.2** | The nested mill ships in the 0xray tarball. `@0xray/foundry` stays the standalone mill CLI. |
|
|
105
|
+
| **4.0.1** | CLI `--version` no longer dumps a Commander stack. The release gate smokes the organ and does not run another publish from a lifecycle script. |
|
|
60
106
|
| **4.0.0** | Exo + temperament. Constitution always on; ceremony by host. Repertoire organ on (vendored 0.2). Station card survives compact/host-swap. **On npm.** [vision](docs-site/docs/architecture/v4-vision.md) · [now](docs-site/docs/architecture/v4-now.md) |
|
|
61
107
|
| **3.4.1** | Unified `install-bridges.cjs` on postinstall — OpenCode, Grok, Hermes, OpenClaw in one pass. All 7 MCPs servers via `npx -y 0xray mcp <cmd>` (no `dist/` paths). Canonical `release.mjs` pipeline. |
|
|
62
108
|
| **3.3.1** | Orchestrator confidence gate wired into execution planning. |
|
|
@@ -102,9 +148,9 @@ Docs: [guides/autonomy-command](docs-site/docs/guides/autonomy-command.md) · Sk
|
|
|
102
148
|
- **External Governance** — Dynamo Solar SSOT; CodexPolicyService; weighted PHI/TAU deliberation.
|
|
103
149
|
- **Autonomous Engine** — thinDispatch 7-flow routing; orchestrator confidence gate (v3.3.1).
|
|
104
150
|
|
|
105
|
-
## Consumer Install (
|
|
151
|
+
## Consumer Install (wear)
|
|
106
152
|
|
|
107
|
-
|
|
153
|
+
`npm install 0xray` links the vendored repertoire and prints `npx 0xray wear`. Wear then:
|
|
108
154
|
|
|
109
155
|
1. Copies **`AGENTS-consumer.md` → `AGENTS.md`**. Does **not** write consumer-root **`SKILLS.md`**.
|
|
110
156
|
2. Fastens **mill plant** (`mill` + `inspect`). Fasten is **foundry-plant/0**: builtin plant is mill+inspect only. `foundry.json` `"plant": "@0xray/blip"` (aliases `"plant": "blip"` / `"plant": "sound"`) fastens whatever that mill package declares — organs (looker, vibe, mixer) live in the mill, not an xray catalog. Nested mill `@0xray/foundry@0.1.12`. CLI shims `foundry blip|sound` still exist on foundry 0.1.11+; fasten is the new cut. Not a 45-skill / 42-agent costume dump. `foundry.json` `"costume": true` is the opt-in dump.
|
|
@@ -113,7 +159,7 @@ On `npm install 0xray` in a consumer project, postinstall automatically:
|
|
|
113
159
|
5. Writes project **`.mcp.json`** with 7 MCPs servers (`npx -y 0xray mcp …`)
|
|
114
160
|
6. Installs **4 chat bridges**: OpenCode, Grok, Hermes, OpenClaw, plus **Cursor** `.cursor/hooks.json` (PPE + wiring; mill plant, not costume)
|
|
115
161
|
7. Factory shop plant (`shop-extract`, `shop-witness`, `shop-pin` from groover-hangar) may coexist when worn. Extra shops: `foundry.json` `shopPlant`. Not costume.
|
|
116
|
-
8.
|
|
162
|
+
8. Inside a git checkout, fastens Cursor `.cursor/hooks.json` and the hook scripts, and keeps an unwear snapshot. Outside a git checkout, skips those hooks and prints one warning. `npx 0xray setup --git-hooks` is what installs git hooks.
|
|
117
163
|
|
|
118
164
|
See [llms.txt](llms.txt) for the agent map. Catalog of 45 skills lives in [SKILLS.md](SKILLS.md) — that is the exo catalog, not default consumer wear.
|
|
119
165
|
|
|
@@ -186,13 +232,13 @@ Docs: [memory routing](docs-site/docs/guides/memory-routing.md) · [Repertoire](
|
|
|
186
232
|
|
|
187
233
|
## Integrations
|
|
188
234
|
|
|
189
|
-
| Platform | Install |
|
|
235
|
+
| Platform | Install | What that command writes |
|
|
190
236
|
|----------|---------|----------------------|
|
|
191
237
|
| **OpenCode** | `npx 0xray opencode install` | Merges `opencode.json`, copies agent YML surfaces |
|
|
192
238
|
| **Grok CLI / Build** | `npx 0xray grok install` | Project `.grok/plugins/0xray` (shared HOME does not clobber machine plugin), 7 MCPs servers |
|
|
193
239
|
| **Hermes Agent** | `npx 0xray hermes install` | `~/.hermes/plugins/xray-hermes`, consumer root marker |
|
|
194
240
|
| **OpenClaw** | `npx 0xray openclaw install` | `.xray/config/openclaw.json`, skill sync |
|
|
195
|
-
| **Cursor** |
|
|
241
|
+
| **Cursor** | `npx 0xray wear` inside a git checkout | Fastens `.cursor/hooks.json` + relative `.cursor/hooks/*.sh`. Rewrites leftover env-assignment one-liners. Not a fifth chat TUI. |
|
|
196
242
|
|
|
197
243
|
## Governance & Codex
|
|
198
244
|
|
|
@@ -219,7 +265,7 @@ npm run release:npm # gate + prepare + npm publish --access public
|
|
|
219
265
|
|
|
220
266
|
## Release
|
|
221
267
|
|
|
222
|
-
The **4.
|
|
268
|
+
The **4.1** line is on npm. Do **not** run `release:major` to ship a 4.x fix (that becomes 5.0.0). Do **not** put a `scripts.publish` lifecycle that re-runs the gate after the registry PUT. Patch number lives in `package.json` + CHANGELOG.
|
|
223
269
|
|
|
224
270
|
```bash
|
|
225
271
|
npm run release:gate
|
|
@@ -235,4 +281,4 @@ MIT — see [LICENSE](LICENSE)
|
|
|
235
281
|
|
|
236
282
|
---
|
|
237
283
|
|
|
238
|
-
*xray —
|
|
284
|
+
*xray — a three-subsystem autonomous engine. The suit is the wear.*
|
package/dist/SKILLS.md
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# 0xray Skills
|
|
2
2
|
|
|
3
|
-
**4.
|
|
3
|
+
**4.1** — a suit that survives the context window
|
|
4
|
+
|
|
5
|
+
Confer votes. Burst runs the swarm.
|
|
6
|
+
|
|
7
|
+
0xRay is a three-subsystem autonomous engine. The suit is the wear. This file is the catalog.
|
|
4
8
|
|
|
5
9
|
**45 skills** in this exo catalog. Default consumer plant is **`mill` + `inspect`**, not this dump. `npm install 0xray` does **not** sync 45 skills unless `foundry.json` `"costume": true`. Factory shop plant (`shop-extract`, `shop-witness`, `shop-pin`) coexists with mill plant when a hangar wears those shops. Extra shops: `foundry.json` `shopPlant`. Fasten is **foundry-plant/0**: builtin plant is mill+inspect only. `foundry.json` `"plant": "@0xray/blip"` (aliases `"plant": "blip"` / `"plant": "sound"`) fastens whatever that mill package declares — organs (looker, vibe, mixer) live in the mill, not this catalog. Nested mill `@0xray/foundry@0.1.12`. CLI shims `foundry blip|sound` still exist on foundry 0.1.11+. Agent map: [llms.txt](llms.txt).
|
|
6
10
|
|
|
@@ -69,7 +69,7 @@ async function installForOpenClaw(options = {}) {
|
|
|
69
69
|
/* session-boot is best-effort */
|
|
70
70
|
}
|
|
71
71
|
const packageRoot = path.resolve(__dirname, '..', '..', '..');
|
|
72
|
-
const hookInstalled = isolated ? null : wiring.installOpenClawHostWear(packageRoot);
|
|
72
|
+
const hookInstalled = isolated ? null : wiring.installOpenClawHostWear(packageRoot, targetDir);
|
|
73
73
|
const cliBackend = isolated ? false : wiring.maybeWriteOpenClawCliBackend();
|
|
74
74
|
frameworkLogger.log('openclaw-integration', 'cli-backend', 'info', { written: cliBackend });
|
|
75
75
|
if (hookInstalled) {
|
|
@@ -16,3 +16,7 @@ export declare function pluginEnableCommand(pluginName: string): Promise<void>;
|
|
|
16
16
|
export declare function pluginDisableCommand(pluginName: string): Promise<void>;
|
|
17
17
|
export declare function pluginStatusCommand(pluginName: string): Promise<void>;
|
|
18
18
|
export declare function pluginUninstallCommand(pluginName: string): Promise<void>;
|
|
19
|
+
type YamlMap = Record<string, unknown>;
|
|
20
|
+
/** Subset of YAML used by plugin.yaml: maps, scalar lists, and lists of maps. */
|
|
21
|
+
export declare function parseYaml(content: string): YamlMap;
|
|
22
|
+
export {};
|
|
@@ -152,24 +152,25 @@ export async function pluginStatusCommand(pluginName) {
|
|
|
152
152
|
console.log(` Type: ${m.type}`);
|
|
153
153
|
console.log(` Description: ${m.description}`);
|
|
154
154
|
console.log(` License: ${m.license || "N/A"}`);
|
|
155
|
-
if (m.capabilities) {
|
|
155
|
+
if (Array.isArray(m.capabilities)) {
|
|
156
156
|
console.log("\n Capabilities:");
|
|
157
157
|
for (const cap of m.capabilities) {
|
|
158
|
-
console.log(` - ${cap}`);
|
|
158
|
+
console.log(` - ${String(cap)}`);
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
|
-
if (m.tools) {
|
|
161
|
+
if (Array.isArray(m.tools)) {
|
|
162
162
|
console.log("\n Tools:");
|
|
163
163
|
for (const tool of m.tools) {
|
|
164
|
-
|
|
164
|
+
const row = tool;
|
|
165
|
+
console.log(` - ${String(row.name)}: ${String(row.description)}`);
|
|
165
166
|
}
|
|
166
167
|
}
|
|
167
|
-
if (m.runtime) {
|
|
168
|
+
if (m.runtime && typeof m.runtime === "object" && !Array.isArray(m.runtime)) {
|
|
168
169
|
const runtime = m.runtime;
|
|
169
170
|
console.log("\n Runtime:");
|
|
170
|
-
console.log(` Command: ${runtime.command}`);
|
|
171
|
-
if (runtime.args) {
|
|
172
|
-
console.log(` Args: ${runtime.args.join(" ")}`);
|
|
171
|
+
console.log(` Command: ${String(runtime.command)}`);
|
|
172
|
+
if (Array.isArray(runtime.args)) {
|
|
173
|
+
console.log(` Args: ${runtime.args.map((arg) => String(arg)).join(" ")}`);
|
|
173
174
|
}
|
|
174
175
|
}
|
|
175
176
|
console.log("\n" + "═".repeat(50) + "\n");
|
|
@@ -195,51 +196,93 @@ function validateManifest(manifest) {
|
|
|
195
196
|
}
|
|
196
197
|
}
|
|
197
198
|
}
|
|
198
|
-
function
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
]
|
|
205
|
-
|
|
199
|
+
function parseScalar(raw) {
|
|
200
|
+
const value = raw.trim();
|
|
201
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
202
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
203
|
+
return value.slice(1, -1);
|
|
204
|
+
}
|
|
205
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
206
|
+
const inner = value.slice(1, -1).trim();
|
|
207
|
+
if (!inner)
|
|
208
|
+
return [];
|
|
209
|
+
return inner.split(",").map((part) => parseScalar(part));
|
|
210
|
+
}
|
|
211
|
+
if (value === "true")
|
|
212
|
+
return true;
|
|
213
|
+
if (value === "false")
|
|
214
|
+
return false;
|
|
215
|
+
if (/^-?\d+$/.test(value))
|
|
216
|
+
return Number(value);
|
|
217
|
+
return value;
|
|
218
|
+
}
|
|
219
|
+
/** Subset of YAML used by plugin.yaml: maps, scalar lists, and lists of maps. */
|
|
220
|
+
export function parseYaml(content) {
|
|
221
|
+
const root = {};
|
|
222
|
+
const stack = [{ indent: -1, container: root }];
|
|
223
|
+
for (const line of content.split("\n")) {
|
|
206
224
|
const trimmed = line.trim();
|
|
207
225
|
if (!trimmed || trimmed.startsWith("#"))
|
|
208
226
|
continue;
|
|
209
227
|
const indent = line.search(/\S/);
|
|
210
|
-
|
|
211
|
-
if (isListItem) {
|
|
212
|
-
const value = trimmed.slice(2).trim();
|
|
228
|
+
while (stack.length > 1) {
|
|
213
229
|
const top = stack[stack.length - 1];
|
|
214
|
-
if (top
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
if (top && currentKey) {
|
|
218
|
-
top.obj[currentKey].push(value);
|
|
219
|
-
}
|
|
220
|
-
continue;
|
|
230
|
+
if (!top || indent > top.indent)
|
|
231
|
+
break;
|
|
232
|
+
stack.pop();
|
|
221
233
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
234
|
+
if (trimmed.startsWith("- ")) {
|
|
235
|
+
let owner = stack[stack.length - 1];
|
|
236
|
+
if (owner &&
|
|
237
|
+
!Array.isArray(owner.container) &&
|
|
238
|
+
Object.keys(owner.container).length === 0 &&
|
|
239
|
+
stack.length > 1) {
|
|
240
|
+
const holder = stack[stack.length - 2];
|
|
241
|
+
const emptyIndent = owner.indent;
|
|
228
242
|
stack.pop();
|
|
243
|
+
if (holder && !Array.isArray(holder.container) && holder.key) {
|
|
244
|
+
const list = [];
|
|
245
|
+
holder.container[holder.key] = list;
|
|
246
|
+
stack.push({ indent: emptyIndent, container: list });
|
|
247
|
+
}
|
|
248
|
+
owner = stack[stack.length - 1];
|
|
229
249
|
}
|
|
230
|
-
|
|
231
|
-
if (!current)
|
|
250
|
+
if (!owner || !Array.isArray(owner.container))
|
|
232
251
|
continue;
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
|
|
252
|
+
const rest = trimmed.slice(2).trim();
|
|
253
|
+
const colon = rest.indexOf(":");
|
|
254
|
+
const quoted = rest.startsWith('"') || rest.startsWith("'");
|
|
255
|
+
if (!quoted && colon > 0) {
|
|
256
|
+
const item = {};
|
|
257
|
+
const key = rest.slice(0, colon).trim();
|
|
258
|
+
const value = rest.slice(colon + 1).trim();
|
|
259
|
+
item[key] = value ? parseScalar(value) : {};
|
|
260
|
+
owner.container.push(item);
|
|
261
|
+
stack.push({ indent, container: item, key });
|
|
236
262
|
}
|
|
237
263
|
else {
|
|
238
|
-
|
|
239
|
-
stack.push({ indent, obj: parent[key] });
|
|
264
|
+
owner.container.push(parseScalar(rest));
|
|
240
265
|
}
|
|
241
|
-
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
const colonIndex = trimmed.indexOf(":");
|
|
269
|
+
if (colonIndex <= 0)
|
|
270
|
+
continue;
|
|
271
|
+
const key = trimmed.slice(0, colonIndex).trim();
|
|
272
|
+
const value = trimmed.slice(colonIndex + 1).trim();
|
|
273
|
+
const current = stack[stack.length - 1];
|
|
274
|
+
if (!current || Array.isArray(current.container))
|
|
275
|
+
continue;
|
|
276
|
+
if (value) {
|
|
277
|
+
current.container[key] = parseScalar(value);
|
|
278
|
+
current.key = key;
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
const child = {};
|
|
282
|
+
current.container[key] = child;
|
|
283
|
+
current.key = key;
|
|
284
|
+
stack.push({ indent, container: child });
|
|
242
285
|
}
|
|
243
286
|
}
|
|
244
|
-
return
|
|
287
|
+
return root;
|
|
245
288
|
}
|
package/dist/cli/index.js
CHANGED
|
@@ -116,6 +116,18 @@ program
|
|
|
116
116
|
.action((args) => {
|
|
117
117
|
runGoggles(args);
|
|
118
118
|
});
|
|
119
|
+
program
|
|
120
|
+
.command("confer")
|
|
121
|
+
.argument("<state>", "on or off")
|
|
122
|
+
.description("Turn confer on or off in .xray/features.json. A missing key stays off until this runs.")
|
|
123
|
+
.action((state) => {
|
|
124
|
+
try {
|
|
125
|
+
runNodeScript("confer-switch.cjs", [state]);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
119
131
|
program
|
|
120
132
|
.command("wear")
|
|
121
133
|
.description("Wear the 0xray suit in this git checkout")
|
|
@@ -93,9 +93,9 @@ export class XrayConfigLoader {
|
|
|
93
93
|
}
|
|
94
94
|
const cfg = config;
|
|
95
95
|
return {
|
|
96
|
-
enabled: typeof cfg.enabled === 'boolean' ? cfg.enabled :
|
|
96
|
+
enabled: typeof cfg.enabled === 'boolean' ? cfg.enabled : false,
|
|
97
97
|
interval_minutes: Math.max(5, Math.min(1440, typeof cfg.interval_minutes === 'number' ? cfg.interval_minutes : 60)),
|
|
98
|
-
auto_schedule: typeof cfg.auto_schedule === 'boolean' ? cfg.auto_schedule :
|
|
98
|
+
auto_schedule: typeof cfg.auto_schedule === 'boolean' ? cfg.auto_schedule : false,
|
|
99
99
|
include_health_assessment: typeof cfg.include_health_assessment === 'boolean' ? cfg.include_health_assessment : true,
|
|
100
100
|
include_agent_activities: typeof cfg.include_agent_activities === 'boolean' ? cfg.include_agent_activities : true,
|
|
101
101
|
include_pipeline_operations: typeof cfg.include_pipeline_operations === 'boolean' ? cfg.include_pipeline_operations : true,
|
|
@@ -123,9 +123,9 @@ export class XrayConfigLoader {
|
|
|
123
123
|
session_persistence: true,
|
|
124
124
|
},
|
|
125
125
|
autonomous_reporting: {
|
|
126
|
-
enabled:
|
|
126
|
+
enabled: false,
|
|
127
127
|
interval_minutes: 60,
|
|
128
|
-
auto_schedule:
|
|
128
|
+
auto_schedule: false,
|
|
129
129
|
include_health_assessment: true,
|
|
130
130
|
include_agent_activities: true,
|
|
131
131
|
include_pipeline_operations: true,
|
|
@@ -406,7 +406,7 @@ export interface FeaturesConfig {
|
|
|
406
406
|
enabled?: boolean;
|
|
407
407
|
};
|
|
408
408
|
memory_routing?: MemoryRoutingConfig;
|
|
409
|
-
/**
|
|
409
|
+
/** Marker is opt-in and the shipped default is off. */
|
|
410
410
|
grok_postprocessor_light?: boolean;
|
|
411
411
|
/** P2 — git post-commit session inference capture */
|
|
412
412
|
inference_session_capture?: {
|
|
@@ -342,9 +342,9 @@ export class FeaturesConfigLoader {
|
|
|
342
342
|
no_new_surface: true,
|
|
343
343
|
},
|
|
344
344
|
autonomous_reporting: {
|
|
345
|
-
enabled:
|
|
345
|
+
enabled: false,
|
|
346
346
|
interval_minutes: 60,
|
|
347
|
-
auto_schedule:
|
|
347
|
+
auto_schedule: false,
|
|
348
348
|
include_health_assessment: true,
|
|
349
349
|
include_agent_activities: true,
|
|
350
350
|
include_pipeline_operations: true,
|
|
@@ -410,7 +410,7 @@ export class FeaturesConfigLoader {
|
|
|
410
410
|
max_cache_size_mb: 50,
|
|
411
411
|
},
|
|
412
412
|
inference: {
|
|
413
|
-
description: "
|
|
413
|
+
description: "The cycle runs from the CLI command inference:run and the session wake does not start it.",
|
|
414
414
|
enabled: true,
|
|
415
415
|
workflow_dir: ".xray/inference",
|
|
416
416
|
reports_dir: ".xray/reports",
|
|
@@ -322,13 +322,15 @@ export class ConsoleLogUsageValidator extends BaseValidator {
|
|
|
322
322
|
severity = "error";
|
|
323
323
|
async validate(context) {
|
|
324
324
|
const { newCode } = context;
|
|
325
|
-
// Skip validation if no code to check
|
|
326
325
|
if (!newCode) {
|
|
327
326
|
return this.createSuccessResult("No code to validate for console.log usage");
|
|
328
327
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
328
|
+
const codeWithoutComments = newCode
|
|
329
|
+
.replace(/\/\/.*$/gm, "")
|
|
330
|
+
.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
331
|
+
const consoleCall = /console\.(?:log|debug|info|warn|error|trace)\s*\(/;
|
|
332
|
+
if (consoleCall.test(codeWithoutComments)) {
|
|
333
|
+
return this.createFailureResult("console method detected — use frameworkLogger", ["Use frameworkLogger instead of console methods"]);
|
|
332
334
|
}
|
|
333
335
|
return this.createSuccessResult("Console log usage follows proper guidelines");
|
|
334
336
|
}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
export type GovernanceRole = "code-review" | "security-audit" | "researcher";
|
|
1
|
+
export type GovernanceRole = "code-review" | "security-audit" | "researcher" | "architect";
|
|
2
|
+
export type GovernanceMiss = "not-configured" | "error" | "timeout" | "empty" | "unparseable";
|
|
3
|
+
export interface GovernanceAttempt {
|
|
4
|
+
vote: GovernanceVote | null;
|
|
5
|
+
miss: GovernanceMiss | null;
|
|
6
|
+
}
|
|
2
7
|
export interface GovernanceVote {
|
|
3
8
|
decision: "approve" | "reject" | "abstain";
|
|
4
9
|
confidence: number;
|
|
@@ -7,6 +12,7 @@ export interface GovernanceVote {
|
|
|
7
12
|
export declare function resolveHermesBin(): string;
|
|
8
13
|
export declare function isGovernanceLlmConfigured(): boolean;
|
|
9
14
|
export declare function hermesCliAvailable(): boolean;
|
|
15
|
+
export declare function attemptLLMGovernance(role: GovernanceRole, proposalTitle: string, proposalDescription: string, evidence: string[], proposalType: string): Promise<GovernanceAttempt>;
|
|
10
16
|
export declare function tryLLMGovernance(role: GovernanceRole, proposalTitle: string, proposalDescription: string, evidence: string[], proposalType: string): Promise<GovernanceVote | null>;
|
|
11
17
|
export declare function checkHermesOAuthStatus(): {
|
|
12
18
|
configured: boolean;
|
|
@@ -41,6 +41,19 @@ Respond with a structured vote in exactly this format:
|
|
|
41
41
|
DECISION: approve|reject|abstain
|
|
42
42
|
CONFIDENCE: <0.0-1.0>
|
|
43
43
|
REASONING: <2-4 sentence analysis of the proposal's broader project impact>`,
|
|
44
|
+
architect: `You are a senior architect on a governance committee for a software project. Analyze the following proposal and architecture assessment.
|
|
45
|
+
|
|
46
|
+
Consider:
|
|
47
|
+
- Does the change fit the existing architecture?
|
|
48
|
+
- Does it raise coupling, complexity, or scaling risk?
|
|
49
|
+
- Should the work stop until a structural problem is fixed?
|
|
50
|
+
|
|
51
|
+
Respond with a structured vote in exactly this format:
|
|
52
|
+
DECISION: approve|reject|abstain
|
|
53
|
+
CONFIDENCE: <0.0-1.0>
|
|
54
|
+
REASONING: <2-4 sentence analysis>
|
|
55
|
+
|
|
56
|
+
reject means the architecture should not proceed.`,
|
|
44
57
|
};
|
|
45
58
|
function resolveHermesProvider() {
|
|
46
59
|
return process.env.HERMES_PROVIDER?.trim() || DEFAULT_HERMES_PROVIDER;
|
|
@@ -151,18 +164,43 @@ function runHermesGovernanceInference(prompt, config) {
|
|
|
151
164
|
maxBuffer: 10 * 1024 * 1024,
|
|
152
165
|
}).trim();
|
|
153
166
|
}
|
|
167
|
+
function sanitizeVoteReasoning(reasoning) {
|
|
168
|
+
return reasoning
|
|
169
|
+
.split("\n")
|
|
170
|
+
.map((line) => /^\s*(?:[-*•]\s*)?(?:Verdict:|DECISION:)/i.test(line) ? `> ${line.trim()}` : line)
|
|
171
|
+
.join("\n")
|
|
172
|
+
.trim();
|
|
173
|
+
}
|
|
154
174
|
function parseVote(text) {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const
|
|
158
|
-
|
|
175
|
+
// First exact token before REASONING. The prompt menu and anything the model
|
|
176
|
+
// writes inside the reasoning body are not a second vote.
|
|
177
|
+
const lines = text.split("\n");
|
|
178
|
+
const reasoningIdx = lines.findIndex((line) => /^REASONING:/i.test(line.trim()));
|
|
179
|
+
const headerLines = reasoningIdx < 0 ? lines : lines.slice(0, reasoningIdx);
|
|
180
|
+
let decisionWord;
|
|
181
|
+
for (const line of headerLines) {
|
|
182
|
+
const match = line.trim().match(/^DECISION:\s*(approve|reject|abstain)\s*$/i);
|
|
183
|
+
if (match?.[1]) {
|
|
184
|
+
decisionWord = match[1];
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (!decisionWord)
|
|
159
189
|
return null;
|
|
190
|
+
const header = headerLines.join("\n");
|
|
191
|
+
const confidenceMatch = header.match(/CONFIDENCE:\s*([0-9.]+)/i);
|
|
160
192
|
const rawConfidence = confidenceMatch?.[1];
|
|
161
193
|
const confidence = rawConfidence ? parseFloat(rawConfidence) : 0.5;
|
|
194
|
+
const reasoningBody = reasoningIdx < 0
|
|
195
|
+
? ""
|
|
196
|
+
: lines
|
|
197
|
+
.slice(reasoningIdx)
|
|
198
|
+
.join("\n")
|
|
199
|
+
.replace(/^REASONING:\s*/i, "");
|
|
162
200
|
return {
|
|
163
|
-
decision:
|
|
164
|
-
confidence: isNaN(confidence) ? 0.5 : Math.min(1, Math.max(0, confidence)),
|
|
165
|
-
reasoning:
|
|
201
|
+
decision: decisionWord.toLowerCase(),
|
|
202
|
+
confidence: Number.isNaN(confidence) ? 0.5 : Math.min(1, Math.max(0, confidence)),
|
|
203
|
+
reasoning: sanitizeVoteReasoning(reasoningBody) || "No reasoning provided",
|
|
166
204
|
};
|
|
167
205
|
}
|
|
168
206
|
async function callDirectLlm(role, config, proposalTitle, proposalDescription, evidence, proposalType) {
|
|
@@ -209,11 +247,28 @@ Please provide your structured vote.`;
|
|
|
209
247
|
const message = choices?.[0]?.message;
|
|
210
248
|
return message?.content ?? null;
|
|
211
249
|
}
|
|
212
|
-
|
|
250
|
+
function missFromThrown(error) {
|
|
251
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
252
|
+
const code = typeof error === "object" && error !== null && "code" in error
|
|
253
|
+
? String(error.code ?? "")
|
|
254
|
+
: "";
|
|
255
|
+
const killed = typeof error === "object" &&
|
|
256
|
+
error !== null &&
|
|
257
|
+
"killed" in error &&
|
|
258
|
+
error.killed === true;
|
|
259
|
+
if (code === "ETIMEDOUT" || killed || /ETIMEDOUT|timed out/i.test(message)) {
|
|
260
|
+
return "timeout";
|
|
261
|
+
}
|
|
262
|
+
if (/invalid_grant|not configured|unauthorized|no credentials|authentication/i.test(message)) {
|
|
263
|
+
return "not-configured";
|
|
264
|
+
}
|
|
265
|
+
return "error";
|
|
266
|
+
}
|
|
267
|
+
export async function attemptLLMGovernance(role, proposalTitle, proposalDescription, evidence, proposalType) {
|
|
213
268
|
const config = getConfig();
|
|
214
269
|
if (!config) {
|
|
215
270
|
process.stderr.write(`[llm] no config for role=${role}\n`);
|
|
216
|
-
return null;
|
|
271
|
+
return { vote: null, miss: "not-configured" };
|
|
217
272
|
}
|
|
218
273
|
if (config.mode === "hermes") {
|
|
219
274
|
process.stderr.write(`[llm] using hermes -z provider=${config.provider} model=${config.model}\n`);
|
|
@@ -230,12 +285,12 @@ export async function tryLLMGovernance(role, proposalTitle, proposalDescription,
|
|
|
230
285
|
const content = config.mode === "hermes"
|
|
231
286
|
? runHermesGovernanceInference(buildGovernancePrompt(role, proposalTitle, proposalDescription, evidence, proposalType), config)
|
|
232
287
|
: await callDirectLlm(role, config, proposalTitle, proposalDescription, evidence, proposalType);
|
|
233
|
-
if (!content) {
|
|
288
|
+
if (!content?.trim()) {
|
|
234
289
|
frameworkLogger.log("llm-governance", "parse", "warning", {
|
|
235
290
|
issue: "missing content in response",
|
|
236
291
|
role,
|
|
237
292
|
});
|
|
238
|
-
return null;
|
|
293
|
+
return { vote: null, miss: "empty" };
|
|
239
294
|
}
|
|
240
295
|
const vote = parseVote(content);
|
|
241
296
|
if (!vote) {
|
|
@@ -244,23 +299,26 @@ export async function tryLLMGovernance(role, proposalTitle, proposalDescription,
|
|
|
244
299
|
snippet: content.slice(0, 200),
|
|
245
300
|
role,
|
|
246
301
|
});
|
|
247
|
-
return null;
|
|
302
|
+
return { vote: null, miss: "unparseable" };
|
|
248
303
|
}
|
|
249
304
|
frameworkLogger.log("llm-governance", "vote", "success", {
|
|
250
305
|
role,
|
|
251
306
|
decision: vote.decision,
|
|
252
307
|
confidence: vote.confidence,
|
|
253
308
|
});
|
|
254
|
-
return vote;
|
|
309
|
+
return { vote, miss: null };
|
|
255
310
|
}
|
|
256
311
|
catch (error) {
|
|
257
312
|
frameworkLogger.log("llm-governance", "error", "error", {
|
|
258
313
|
error: String(error),
|
|
259
314
|
role,
|
|
260
315
|
});
|
|
261
|
-
return null;
|
|
316
|
+
return { vote: null, miss: missFromThrown(error) };
|
|
262
317
|
}
|
|
263
318
|
}
|
|
319
|
+
export async function tryLLMGovernance(role, proposalTitle, proposalDescription, evidence, proposalType) {
|
|
320
|
+
return (await attemptLLMGovernance(role, proposalTitle, proposalDescription, evidence, proposalType)).vote;
|
|
321
|
+
}
|
|
264
322
|
export function checkHermesOAuthStatus() {
|
|
265
323
|
const direct = getDirectLlmConfig();
|
|
266
324
|
if (direct) {
|