Skip to content

Redesign agent-matrix eval scenarios around NodeSpace's actual dev-workflow use case #1977

Closed

Description

@malibio

Overview

All 16 scenarios in the agent-matrix eval (scripts/eval/fixtures/agent-matrix.ts) are generic personal/hobby CRUD tasks — tracking equipment, music albums, and venue bookings — rather than scenarios reflecting NodeSpace's actual positioning as context infrastructure for AI-native development. Model-lock decisions (ADR-046, ADR-056) and ongoing model re-evaluation work are scored against this matrix, meaning native-model selection is currently being decided by a model's ability to track laser cutters and music albums, not by its ability to do NodeSpace's actual job.

Problem Statement

The current scenario prompts:

  • "I want to keep a record of the equipment my team checks out, whether it's been returned, and what each item costs to replace" (schema creation)
  • "Start tracking albums I mean to listen to"
  • "I also need a tracker for the venues I book"
  • "Put down Kind of Blue, it's by Miles Davis"
  • "Add a task to schedule the chip upgrade on the Polestar"

These exercise the right tool mechanics — create_schema, create_node, update_node, search_nodes, resolve_query — with realistic argument complexity (nested fields, enum coreValues, multi-step read-then-write sequences). But the domain is generic personal-database CRUD, unrelated to what NodeSpace is actually for.

Per the strategy docs (../nodespace-docs/strategy/vision.md, beliefs.md, principles.md), NodeSpace's target user is a developer or dev team using it as "context infrastructure for AI-native development": specifications, architecture decisions, tasks tied to features, and playbook-driven workflows, connecting "why it was built" to "what was built."

None of the current 16 scenarios touch specs, architecture decisions, playbooks, task-to-feature linkage, or architecture-decision retrieval — the dev-workflow use cases the product claims to serve. A model that excels at "track my albums" tells us little about whether it can, for example, retrieve the architecture decision that constrains a task before implementing it, or correctly link a bug fix back to the spec it violated.

This surfaced during #1956 (Gemma 4 12B re-evaluation): the matrix was the basis for judging whether 12B (in either GGUF source) or an experimental MoE variant cleared an "acceptable bar," but that bar itself has never been validated against NodeSpace's actual use case.

Proposed Solution

Design a scenario set themed around NodeSpace's actual dev-workflow use cases, for example:

  • Creating a spec node and linking it to the architecture decision that constrains it.
  • Retrieving the ADR that governs a given task before answering a question about it.
  • Creating or updating a playbook's trigger/condition.
  • Linking a bug fix back to the spec or acceptance criterion it violated.
  • Querying "what decisions constrain this feature" (relationship traversal, not just property filtering).
  • Task-to-feature linkage (creating a task and associating it with the feature/spec it implements).

Decide whether this replaces the existing 16 scenarios outright or runs alongside them as a second fixture (the existing set may still hold value as a generic tool-mechanics floor, separate from domain-fit).

Acceptance Criteria

  • New scenario set (or replacement scenarios) designed around specs, architecture decisions, playbooks, and task-to-feature linkage, matching the vision/beliefs/principles docs' description of NodeSpace's target use case
  • Decision made and documented on whether this replaces scripts/eval/fixtures/agent-matrix.ts's existing 16 scenarios or runs as an additional fixture
  • New/changed prompts do not share wording with seeded guidance or skill content, verified by guidance_is_not_contaminated_by_eval_prompts (packages/agent/src/agent_guidance.rs), which parses prompt: literals out of every file in scripts/eval/fixtures/
  • Scoring/expectation model reused or extended following the existing Expectation types in scripts/eval/fixtures/agent-matrix.ts (toolOnce, toolSequence, minProperties, etc.) rather than inventing a parallel scoring mechanism
  • bun run test:scripts passes (the scoring-logic unit tests for the fixture)
  • Documented in ../nodespace-docs/development/agent-eval.md if the fixture structure or scoring approach changes

Technical Specifications

Reference Files

  • Scenario fixture: scripts/eval/fixtures/agent-matrix.ts — current 16 scenarios, Expectation type model, scoring logic
  • Scoring tests: scripts/eval/fixtures/agent-matrix.test.ts — unit tests for the scoring function (no model/daemon needed)
  • Contamination guard: packages/agent/src/agent_guidance.rs (guidance_is_not_contaminated_by_eval_prompts) — enforces that scenario prompts don't overlap with seeded guidance/skill wording
  • Eval harness docs: ../nodespace-docs/development/agent-eval.md — the shared runner, preflight gate, and setup instructions
  • Strategy docs: ../nodespace-docs/strategy/vision.md, beliefs.md, principles.md — the target-user/use-case framing this issue proposes scenarios align to

Non-Goals

  • Re-running model comparisons against the new scenarios — that is separate follow-up work once the new scenario set exists.
  • Changing the routing eval (scripts/eval/fixtures/routing.ts) or the tool-call parser fixtures (chat::parser::tests) — this issue is scoped to the end-to-end agent-matrix eval only.

Related Issues

Activity

  1. malibio commented on Aug 17, 2026

    @malibio
    CollaboratorAuthor

    Scope question: this issue covers the eval, but the guidance it measures is business-domain too

    Filed #2118 (golden-prompt runner) and #2119 (assembly snapshot gate) alongside this. While scoping them, measured the domain-vocabulary skew across every model-facing surface, not just the matrix:

    surface business-domain hits dev-domain hits
    packages/agent/src/local_agent/tools.rs 113 41
    packages/agent/src/skill_pipeline.rs 35 7
    scripts/eval/fixtures/routing.ts 17 7
    scripts/eval/fixtures/agent-matrix.ts 6 13

    (business = invoice/customer/receivable/billing/booking/equipment/venue/vendor/payment/client; dev = bug/PR/commit/repo/sprint/ticket/issue/deploy/release/backlog/incident/code-review/ADR/spec/milestone/epic)

    The matrix scenarios this issue targets are equipment checkout, albums, venues, and one car mod — none dev-flavored. But the guidance is worse, and it is the causal surface: skill_pipeline.rs teaches title_template = "Invoice #{{invoice_number}}", a full Invoice schema linked to customer, clarification examples built from "I found 3 invoices — Invoice #1 ($500)…", and a Node Creation description enumerating "Project, Customer, Invoice". tools.rs uses "Mark the $500 invoice as paid" as resolve_query's canonical example, in a parameter description the model reads every turn.

    Per ADR-038 Finding 2, the worked example in the guidance is what produces correct structured output — the model copies the pattern. So these examples are the template, not decoration.

    Why it matters for this issue specifically: ADR-064 rule 3 makes skill descriptions index keys tuned against a retrieval benchmark. Retargeting the benchmark to dev intents while the descriptions and worked examples stay invoice-flavored tunes the two against each other in opposite directions — results would likely get worse with nothing actually wrong.

    Recommendation: keep #1977 scoped to the eval (matrix + routing fixtures), and file the guidance/tool-schema example rewrite (skill_pipeline.rs, tools.rs) as a separate issue that lands with or before it. Keeping them apart preserves the contamination boundary #1932 exists to enforce — golden/eval prompts and guidance examples must stay lexically distinct, or a passing scenario proves only that the model memorized its own answer key.

    Proceeding on that reading unless redirected. Happy to fold it all into #1977 instead if you'd rather have one unit of work.

  2. malibio commented on Aug 17, 2026

    @malibio
    CollaboratorAuthor

    Sequencing: #2118 → #2120 → #2119 → #1977

    These four are one line of work. Recording the order and the reasoning so it survives a context reset.

    # issue why here
    1 #2118 — golden-prompt runner Nothing else can proceed without a fast tuning loop. No domain decisions, no live-measurement dependency.
    2 #2120 — retarget guidance + trim The substantive manual work. Needs #2118 to be iterable; must precede the eval retarget.
    3 #2119 — assembly snapshot gate Freezes the tuned prompt as production's target. Placed after #2120 so the golden is captured once, not churned through a wholesale rewrite.
    4 #1977 — matrix + routing fixtures Retargeting the eval before the guidance would tune the two in opposite directions — scores would likely drop with nothing actually wrong.

    Why the snapshot gate is third, not first

    It was initially argued for first, on the grounds that snapshotting today's assembly turns four independently-edited surfaces (agent_guidance.rs, tools.rs, skill_pipeline.rs, routing.rs) into a reviewable diff — which is real, and would have caught the coreValues/core_values contradiction ADR-064 records as shipped.

    But the snapshot would capture today's invoice-flavored prompt, and #2120 then rewrites it wholesale. Nearly every diff during that window is intended, so the gate's actual value — catching unintended drift — is thin exactly when it would be running. Capturing the golden once, after the rewrite settles, is cleaner than regenerating it through two rounds of deliberate change.

    The risk this ordering carries, and its mitigation

    The failure mode is the #1917 pattern repeating: tune by hand, get a good result, close the issue, never build the gate. That is not hypothetical — it is what happened, and live_stage1_golden_prompts.rs still carries the header comment saying the snapshot tests are "not yet written."

    Mitigation is in #2120's acceptance criteria rather than in the ordering: every tuned prompt is checked in as a #2118 case file. The work is durable whether or not #2119 lands promptly, and #2119 becomes the step that converts those case files into a production contract rather than the only thing standing between tuning and lost work.

    For reading the current assembled prompt while deciding what to cut, NODESPACE_PROMPT_DUMP already dumps it at the native-path chokepoint — the gate is not needed for that.

    Adjacent, not blocking

  3. malibio commented on Aug 17, 2026

    @malibio
    CollaboratorAuthor

    Revised sequencing: #2118 → #2122 → #2119 → #2120 → #1977

    Supersedes the earlier sequencing comment. The chain gained a step and #2120 was rescoped, because the previous plan had no issue that actually produced the golden corpus — #2119 would have asserted against goldens nobody authored.

    # issue deliverable touches production source?
    1 #2118 the utility (PR #2121) new bin only
    2 #2122 tuned golden prompt strings no
    3 #2119 snapshot gate test only
    4 #2120 assembly emits the goldens yes
    5 #1977 eval retargeted to match fixtures only

    The split that matters

    #2120 previously mixed what should the prompt say with edit the files that emit it. That is the exact conflation this effort exists to remove — a failure could be a bad prompt or bad plumbing, indistinguishable.

    Now:

    A failure in #2122 is a prompt failure. A failure in #2120 is a plumbing failure. By construction.

    Why #2119 moved ahead of #2120

    The gate is what defines #2120's done condition. "Make plumbing match" has no test without it.

    The governing requirement across all of them

    Goldens must be production-shaped: same blocks, same structure, same tool surface as what NodeSpace actually sends — with the content of those blocks being what is tuned. A minimal hand-authored prompt is a useful control but not a target; scenario 6 is the cautionary case, at 3/3 hand-authored vs 0/8 in production for the same task.

  4. malibio commented on Aug 21, 2026

    @malibio
    CollaboratorAuthor

    Baseline (worktree issue-1977-dev-workflow-eval): Frontend 4794 passed / 227 files, 0 failed. (An initial run showed 2 known load-flaky perf benchmarks; a clean re-run passed 227/227.)

  5. self-assigned this
    on Aug 21, 2026
  6. malibio commented on Aug 21, 2026

    @malibio
    CollaboratorAuthor

    Scope decision: re-theme in place, do not add a second fixture

    AC 2 asks for a documented decision on replace-vs-add. Recommendation: replace the domain, keep every mechanic — one fixture, not two. Proceeding on this unless redirected.

    Reasoning:

    • The stated problem is that model-lock decisions are scored on the wrong domain. Adding a second fixture alongside does not fix that — it leaves the generic matrix as an equally-citable number and makes "which one is the bar?" ambiguous exactly where ADR-046/ADR-056 need one answer.
    • The eval costs minutes of real inference per run and is manual. Doubling scenario count doubles that cost for every future model comparison, and single-run matrix numbers are already not decision-grade (per the Agent matrix 10/12 -> 6/12 does not reproduce: fixture change plus single-run variance, not a regression #1862 finding) — two half-sized signals are worse than one.
    • The "generic tool-mechanics floor" the issue floats as a reason to keep the old set is not actually lost: the mechanics (noExtraTypes, minProperties, noRetry+minCalls, toolSequence) are properties of the Expectation model, not of the album/laser-cutter vocabulary. Re-theming keeps every one of them, and every scenario id, so baseline diffing still joins.

    What changes

    Scenario ids and expectations stay byte-identical — only prompts and the chain's entities are re-themed, so no baseline row is orphaned:

    • Group 3-9 (equipment) -> spec/ADR workflow: a type for specs with an acceptance-status field and an estimate; the indirect-reference update (scenario 6) discriminates on the estimate rather than replacement cost.
    • Group 8a-8e (albums/venues) -> two dev types: ADR tracking + sprint tracking.
    • Group 10a-10c (Polestar task) -> task tied to a feature, still on the core task type, still exercising defined-but-unset due_date/status.

    What is genuinely new

    The issue's strongest point is relationship traversal, which the matrix has never covered at all. Adding one new group (new ids, so nothing existing is disturbed) for create_relationship + get_related_nodes — "which decision constrains this" traversal. This needs a new Expectation kind only if the existing ones cannot express it; I expect toolSequence covers it, and will not invent a parallel scoring mechanism (AC 4).

    Winnability constraint I am holding to

    Every re-themed prompt has to be answerable by the schema the chain itself builds (the trap documented on scenario 9 and in #1846), and no prompt may share a 5-word run with seeded guidance (guidance_is_not_contaminated_by_eval_prompts). Dev vocabulary raises that risk materially — seeded skill descriptions already say "Spec, ADR, Ticket" — so wording will be checked against the guard, not assumed.

  7. added a commit that references this issue on Aug 21, 2026
    e0167ef
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions