diff --git a/.nodeagent/config-hash.txt b/.nodeagent/config-hash.txt new file mode 100644 index 0000000..ef32123 --- /dev/null +++ b/.nodeagent/config-hash.txt @@ -0,0 +1 @@ +683f7ed3a0b65eb368fcc12dd0a306b5c21620dee8e9969ad9d770cf40f91804 diff --git a/.nodeagent/diagnostics.json b/.nodeagent/diagnostics.json new file mode 100644 index 0000000..e4d9cb7 --- /dev/null +++ b/.nodeagent/diagnostics.json @@ -0,0 +1,5 @@ +{ + "errors": [], + "schemaVersion": "nodeagent.diagnostics/v1", + "warnings": [] +} diff --git a/.nodeagent/discovery.json b/.nodeagent/discovery.json new file mode 100644 index 0000000..9728aa4 --- /dev/null +++ b/.nodeagent/discovery.json @@ -0,0 +1,35 @@ +{ + "files": [ + { + "bytes": 287, + "digest": "b1b534e86c3786c7e97631d715eeb69b01307720dc31a1dd80813134dd605fae", + "path": "evals/nodevoice-voice-room.json" + }, + { + "bytes": 1376, + "digest": "94b3f7082138a9c92d35a43717c755d3ba687e542566fe83c294191169abfcab", + "path": "packs/voice-room/pack.yaml" + }, + { + "bytes": 1334, + "digest": "c6054e486674d34fe3d1ffcbf43d65c792b9ea4e374052365716ed553d960580", + "path": "packs/voice-room/SKILL.md" + }, + { + "bytes": 1791, + "digest": "0a8ec416f7e9fee3e400de4716454c40f7550bb9e78876324b0225a07e7838a2", + "path": "src/nodeagents/fixtures.ts" + }, + { + "bytes": 6629, + "digest": "00d7e03b0d39f0710a86b7df4882e02691ca7edf0e8a1ceaa39644a66631dbb9", + "path": "src/nodeagents/nodeAgentLocalMvp.ts" + }, + { + "bytes": 1101, + "digest": "822f17f11d383d9c7f830fa530a52f0fb59b37f26cc3b9bea02eb1c381946c21", + "path": "src/nodeagents/runNodeAgentMvp.ts" + } + ], + "schemaVersion": "nodeagent.discovery/v1" +} diff --git a/.nodeagent/evaluation-plan.json b/.nodeagent/evaluation-plan.json new file mode 100644 index 0000000..b6700da --- /dev/null +++ b/.nodeagent/evaluation-plan.json @@ -0,0 +1,6 @@ +{ + "required": [ + "nodevoice-voice-room" + ], + "schemaVersion": "nodeagent.evaluation-plan/v1" +} diff --git a/.nodeagent/resolved-definition.json b/.nodeagent/resolved-definition.json new file mode 100644 index 0000000..f2a9f44 --- /dev/null +++ b/.nodeagent/resolved-definition.json @@ -0,0 +1,72 @@ +{ + "application": { + "id": "nodevoice-voice-room", + "name": "NodeVoice Voice Room", + "purpose": "Coordinate voice agents through authoritative room state and continue work through the existing local NodeAgent artifact loop without acknowledgement loops." + }, + "backend": { + "adapter": "process-local-room-reducer", + "config": { + "implementation": "./src/core/roomReducer.ts", + "persistence": "in-memory" + } + }, + "configHash": "683f7ed3a0b65eb368fcc12dd0a306b5c21620dee8e9969ad9d770cf40f91804", + "contracts": { + "event": "nodeagent.event/v1", + "trace": "nodeagent.trace/v1" + }, + "discovered": { + "evals": [ + "evals/nodevoice-voice-room.json" + ], + "integrations": [], + "packs": [ + "packs/voice-room/pack.yaml" + ], + "policies": [], + "skills": [ + "packs/voice-room/SKILL.md" + ], + "subagents": [], + "tools": [] + }, + "fileCount": 6, + "manifestDigest": "e8e37e96a9956bb5d944e71547ae825cd5847327453297e62ed1b0a4be81c898", + "orchestration": { + "mode": "server-authoritative-room-state", + "entrypoint": "./src/nodeagents/runNodeAgentMvp.ts", + "implementationSources": [ + "./src/nodeagents/nodeAgentLocalMvp.ts", + "./src/nodeagents/fixtures.ts", + "./src/core/roomReducer.ts", + "./src/voice/voiceAgent.ts", + "./src/compare/badGoodDemo.ts" + ], + "optionalProviderSources": [ + "./src/providers/ollama.ts", + "./src/providers/openai.ts" + ] + }, + "policies": { + "authority": "room-reducer", + "acknowledgementScheduling": "suppressed", + "externalProviders": "opt-in" + }, + "provider": { + "adapter": "repo-local-openai-ollama-router", + "model": { + "provider": "openai", + "id": "gpt-5.4-mini" + }, + "package": null + }, + "runtime": { + "engine": "repo-local-nodevoice", + "profile": "deterministic-no-key" + }, + "schemaVersion": "nodeagent.resolved/v1", + "secretRefs": [ + "OPENAI_API_KEY" + ] +} diff --git a/README.md b/README.md index 4c629fc..4dafeed 100644 --- a/README.md +++ b/README.md @@ -1356,6 +1356,10 @@ src/ ## Commands +The additive P1 NodeKit mapping is documented in +[`docs/nodekit-runtime-map.md`](docs/nodekit-runtime-map.md). It maps the existing +`src/nodeagents` runtime and voice-room reducer without moving either one. + | Command | Description | |---------|-------------| | `npm run ui` | Build client + start server (http://localhost:8787) | diff --git a/docs/nodekit-runtime-map.md b/docs/nodekit-runtime-map.md new file mode 100644 index 0000000..ff5e578 --- /dev/null +++ b/docs/nodekit-runtime-map.md @@ -0,0 +1,77 @@ +# NodeKit brownfield runtime map + +NodeVoice is mapped as a `nodeagent.application/v1` application without moving +or replacing its existing TypeScript runtime. The root `nodeagent.yaml` points +authoring at `src/nodeagents` and names the repo-local implementations that are +already used by the product and tests. + +## Mapped slice + +The single `voice-room` capability pack covers one coherent runtime seam: + +1. `src/core/roomReducer.ts` owns task progress, floor selection, and loop + guards. +2. `src/voice/voiceAgent.ts` advances deterministic voice turns through that + reducer. +3. `src/compare/badGoodDemo.ts` exposes the deterministic room-state comparison + and its provenance. +4. `src/nodeagents/nodeAgentLocalMvp.ts` commits the existing four-artifact work + loop into the same room-state model. + +The pack is a logical ownership map. Its implementation sources remain in place +and remain authoritative. + +## Deterministic and no-key boundary + +`npm run test:nodekit` runs the focused room reducer, deterministic comparison, +and local NodeAgent tests. These paths pass `useOllama: false` or select the +deterministic source explicitly, use repository fixtures, and require no API key +or external account. `npm run demo` remains the repository's disclosed no-key +comparison command. + +The `provider` section in `nodeagent.yaml` records the real optional OpenAI and +Ollama router already present in the repository because the v1 application +schema requires a provider reference. The `deterministic-no-key` runtime profile +does not read `OPENAI_API_KEY` and does not make a provider call. + +## Receipt boundary + +NodeVoice currently returns `ComparisonResult` and `NodeAgentRunResult` values in +memory and prints CLI summaries. It does not persist a stable receipt envelope, +content hash, verifier result, or sanitized reproduction record. Therefore: + +- `nodekit.yaml` intentionally keeps `proof.receiptSchema: null`; +- this mapping does not introduce a receipt schema; +- `.nodeagent` files are compiled composition metadata, not execution proof; and +- `npm run proof` is a useful local gate, but its success is not presented as a + portable or release-ready receipt. + +A future receipt can be declared only after the runtime itself writes and +verifies that artifact. + +## Compiler dependency + +The checked-in `.nodeagent` definition was generated with the NodeKit factory +work from [node-platform PR #4](https://github.com/HomenShum/node-platform/pull/4), +at compiler commit +[`05b4e0e`](https://github.com/HomenShum/node-platform/commit/05b4e0e52623e3be14475ded96a7b7095548675d). +That compiler follows the repository-relative `authoring.directory`, so the +discovery record content-binds all three existing `src/nodeagents` files as well +as this pack, skill, and evaluation binding. Earlier NodeKit drafts that scan +only fixed top-level directories cannot reproduce this definition. + +The compiled hash covers the authored application directory and NodeKit +manifests. It is not a transitive TypeScript dependency graph, build attestation, +or execution receipt; the imported reducer, voice, comparison, and provider +implementations remain repo-local brownfield dependencies. + +## Validation + +```bash +npm run test:nodekit +npm run check +npm run check:client +npm run build +node /src/cli.mjs compile --repo-root . +node /src/cli.mjs compile --repo-root . --check +``` diff --git a/evals/nodevoice-voice-room.json b/evals/nodevoice-voice-room.json new file mode 100644 index 0000000..b1b910e --- /dev/null +++ b/evals/nodevoice-voice-room.json @@ -0,0 +1,11 @@ +{ + "schemaVersion": "nodeagent.evaluation-binding/v1", + "id": "nodevoice-voice-room", + "status": "repo-local-deterministic", + "command": "npm run test:nodekit", + "sources": [ + "tests/comparisonMvp.test.ts", + "tests/roomReducer.test.ts", + "tests/nodeAgentMvp.test.ts" + ] +} diff --git a/nodeagent.yaml b/nodeagent.yaml new file mode 100644 index 0000000..e991766 --- /dev/null +++ b/nodeagent.yaml @@ -0,0 +1,62 @@ +# NodeVoice brownfield application map. The existing TypeScript runtime remains +# authoritative at src/nodeagents; this manifest does not relocate or replace it. +schemaVersion: nodeagent.application/v1 + +application: + id: nodevoice-voice-room + name: NodeVoice Voice Room + purpose: >- + Coordinate voice agents through authoritative room state and continue work + through the existing local NodeAgent artifact loop without acknowledgement + loops. + +authoring: + directory: ./src/nodeagents + +runtime: + engine: repo-local-nodevoice + profile: deterministic-no-key + +# The deterministic profile does not read this secret. This block records the +# real optional hosted-model path required by the v1 application contract. +provider: + adapter: repo-local-openai-ollama-router + model: + provider: openai + id: gpt-5.4-mini + secretRef: OPENAI_API_KEY + +backend: + adapter: process-local-room-reducer + config: + implementation: ./src/core/roomReducer.ts + persistence: in-memory + +orchestration: + mode: server-authoritative-room-state + entrypoint: ./src/nodeagents/runNodeAgentMvp.ts + implementationSources: + - ./src/nodeagents/nodeAgentLocalMvp.ts + - ./src/nodeagents/fixtures.ts + - ./src/core/roomReducer.ts + - ./src/voice/voiceAgent.ts + - ./src/compare/badGoodDemo.ts + optionalProviderSources: + - ./src/providers/ollama.ts + - ./src/providers/openai.ts + +packs: + - ./packs/voice-room/pack.yaml + +policies: + authority: room-reducer + acknowledgementScheduling: suppressed + externalProviders: opt-in + +evaluations: + required: + - nodevoice-voice-room + +contracts: + event: nodeagent.event/v1 + trace: nodeagent.trace/v1 diff --git a/package.json b/package.json index b850c37..ddc5643 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "doctor": "npm run check && npm run check:client", "proof": "npm run test && npm run demo:compare", "test": "vitest run --root .", + "test:nodekit": "vitest run --root . tests/comparisonMvp.test.ts tests/roomReducer.test.ts tests/nodeAgentMvp.test.ts", "demo:compare": "tsx src/compare/runComparisonMvp.ts", "dev": "vite", "build": "vite build", diff --git a/packs/voice-room/SKILL.md b/packs/voice-room/SKILL.md new file mode 100644 index 0000000..ab98970 --- /dev/null +++ b/packs/voice-room/SKILL.md @@ -0,0 +1,29 @@ +# Voice Room Coordination + +Use the existing NodeVoice reducer and local NodeAgent loop as one bounded +capability. Do not copy or replace their implementations. + +## Runtime bindings + +- `src/core/roomReducer.ts` owns authoritative room state, task progress, floor + selection, and acknowledgement-loop suppression. +- `src/voice/voiceAgent.ts` produces a deterministic next turn unless an + optional provider is explicitly selected. +- `src/compare/badGoodDemo.ts` exercises the reducer-backed voice-room path and + discloses whether text came from deterministic fixtures or a provider. +- `src/nodeagents/nodeAgentLocalMvp.ts` commits the context, answer, model delta, + and memo artifacts into the same room-state model. + +## Deterministic path + +Run `npm run test:nodekit` for the focused no-key evaluation. It must prove that +the count advances exactly in order, the room completes at its target, the +reported provenance is deterministic, and the NodeAgent artifact sequence ends +in a completed task. This path must not require a cloud account or provider key. + +## Boundary + +The current runtime returns typed in-memory results and the CLI prints a human +readable summary. It does not write a canonical, content-addressed execution +receipt. Do not describe test output, `.nodeagent` compiler metadata, or console +logs as a proof receipt. diff --git a/packs/voice-room/pack.yaml b/packs/voice-room/pack.yaml new file mode 100644 index 0000000..daae94c --- /dev/null +++ b/packs/voice-room/pack.yaml @@ -0,0 +1,54 @@ +# Logical ownership map for the existing NodeVoice room-state and NodeAgent +# implementations. Runtime code stays at its current src paths. +schemaVersion: nodeagent.pack/v1 +id: voice-room +version: 0.1.0 +name: Voice Room Coordination +description: >- + Reducer-authoritative voice turns and a four-stage local NodeAgent artifact + loop that advance shared work without transcript-driven acknowledgement loops. + +skill: ./SKILL.md + +artifacts: + - room-state + - classified-utterance + - context-bundle + - grounded-answer + - spreadsheet-delta + - notebook-memo + +tools: + - nodevoice.room-reducer + - nodevoice.voice-step + - nodevoice.local-nodeagent-loop + +jobs: + - nodevoice.deterministic-count-room + - nodevoice.nodeagent-artifact-loop + +validators: + - nodevoice.sequential-count + - nodevoice.single-floor-owner + - nodevoice.exact-target-completion + - nodevoice.artifact-order + +fixtures: + - ../../src/nodeagents/fixtures.ts + +examples: + - ../../src/nodeagents/runNodeAgentMvp.ts + - ../../src/voice/runVoiceMvp.ts + +evals: + - ../../evals/nodevoice-voice-room.json + +permissions: + migrationStatus: logical-owner + runtimeAuthority: repo-local-nodevoice + deterministicNetworkAccess: none + implementationSources: + - ../../src/nodeagents/nodeAgentLocalMvp.ts + - ../../src/core/roomReducer.ts + - ../../src/voice/voiceAgent.ts + - ../../src/compare/badGoodDemo.ts