@mutagent/helix 0.1.0-alpha.14
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/.claude/skills/mutagent-helix/SKILL.md +113 -0
- package/.claude/skills/mutagent-helix/scripts/cli/codex-transcode.ts +143 -0
- package/.claude/skills/mutagent-helix/scripts/cli/doctor.ts +111 -0
- package/.claude/skills/mutagent-helix/scripts/cli/init.ts +382 -0
- package/.claude/skills/mutagent-helix/scripts/cli/run.sh +61 -0
- package/CLAUDE.md +193 -0
- package/LICENSE +201 -0
- package/NOTICE +22 -0
- package/README.md +209 -0
- package/assets/adl-loop.svg +162 -0
- package/assets/system-status.svg +422 -0
- package/bin/mutagent-cli.mjs +9950 -0
- package/bin/mutagent-helix.mjs +78 -0
- package/mutagent-agentspec/.claude/skills/mutagent-agentspec/CLAUDE.md +28 -0
- package/mutagent-agentspec/.claude/skills/mutagent-agentspec/SKILL.md +138 -0
- package/mutagent-agentspec/.claude/skills/mutagent-agentspec/assets/templates/agentspec.yaml.tpl +247 -0
- package/mutagent-agentspec/.claude/skills/mutagent-agentspec/references/frameworks/doc-pins.md +53 -0
- package/mutagent-agentspec/.claude/skills/mutagent-agentspec/references/principles.md +91 -0
- package/mutagent-agentspec/.claude/skills/mutagent-agentspec/references/requirements.yaml +295 -0
- package/mutagent-agentspec/.claude/skills/mutagent-agentspec/references/workflows/orchestrator-protocol.md +302 -0
- package/mutagent-agentspec/.claude/skills/mutagent-agentspec/scripts/cli/doctor.ts +116 -0
- package/mutagent-agentspec/.claude/skills/mutagent-agentspec/scripts/cli/init.ts +230 -0
- package/mutagent-agentspec/.claude/skills/mutagent-agentspec/scripts/cli/run.sh +60 -0
- package/mutagent-agentspec/.claude/skills/mutagent-agentspec/scripts/config/resolve-spec-dir.ts +199 -0
- package/mutagent-agentspec/.claude/skills/mutagent-agentspec/scripts/contract/agentspec.schema.ts +455 -0
- package/mutagent-agentspec/.claude/skills/mutagent-agentspec/scripts/setup/detect.ts +67 -0
- package/mutagent-agentspec/.claude/skills/mutagent-agentspec/scripts/validate/validate-spec.ts +93 -0
- package/mutagent-agentspec/LICENSE +201 -0
- package/mutagent-agentspec/NOTICE +19 -0
- package/mutagent-agentspec/README.md +44 -0
- package/mutagent-builder/.claude/skills/mutagent-builder/SKILL.md +100 -0
- package/mutagent-builder/.claude/skills/mutagent-builder/assets/agents/ai-architect.md +312 -0
- package/mutagent-builder/.claude/skills/mutagent-builder/assets/agents/ai-engineer.md +357 -0
- package/mutagent-builder/.claude/skills/mutagent-builder/assets/templates/build-report.md.tpl +39 -0
- package/mutagent-builder/.claude/skills/mutagent-builder/references/principles.md +31 -0
- package/mutagent-builder/.claude/skills/mutagent-builder/references/workflows/build-protocol.md +61 -0
- package/mutagent-builder/.claude/skills/mutagent-builder/references/workflows/improve-handoff.md +23 -0
- package/mutagent-builder/.claude/skills/mutagent-builder/scripts/cli/run.sh +60 -0
- package/mutagent-builder/.claude/skills/mutagent-builder/scripts/handoff/validate-build-input.ts +72 -0
- package/mutagent-builder/.claude/skills/mutagent-builder/scripts/sync-spec/check-sync-spec.ts +499 -0
- package/mutagent-builder/.claude/skills/mutagent-builder/scripts/verify/spec-impl-coverage.ts +182 -0
- package/mutagent-builder/CLAUDE.md +25 -0
- package/mutagent-builder/README.md +26 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/README.md +192 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/SKILL.md +352 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/agents/ai-architect.md +256 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/agents/ai-engineer.md +344 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/agents/diagnostics-analyzer.md +576 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/agents/discovery.md +425 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/audit.json.tpl +24 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/audit.md.tpl +49 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/config.yaml.tpl +100 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/pr-body.md.tpl +56 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/report.html.tpl +327 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/shared/README.md +27 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/shared/iter-N-handover.md.tpl +125 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/shared/self-diagnosis-contract.v0.1.0.yaml.tpl +234 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/shared/spec.yaml.tpl +152 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/shared/team.yaml.tpl +127 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/shared/wave-N-dashboard.html.tpl +1712 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/diagnostics/WF-2.1-nl-query.md +59 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/diagnostics/WF-2.2-tier0-progress.md +58 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/diagnostics/WF-2.3-analysis-progress.md +44 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/diagnostics/WF-2.4-html-report.md +61 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/diagnostics/WF-2.5-rca-detail.md +69 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/diagnostics/WF-2.6-stale-warning.md +53 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/onboarding/WF-1.1-welcome.md +60 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/onboarding/WF-1.2-source-platform-picker.md +41 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/onboarding/WF-1.3-source-auth.md +75 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/onboarding/WF-1.4-target-picker.md +48 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/onboarding/WF-1.5-ask-tool.md +43 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/onboarding/WF-1.6-config-review.md +57 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/onboarding/WF-1.7-filter-defaults.md +52 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/onboarding/WF-1.8-first-run.md +59 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/examples/sample-findings.json +92 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/examples/sample-meta.json +47 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/adapter-strategy.md +75 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/config-migration.md +84 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/config.md +159 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/filter-search-matrix.md +66 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/harness-knowledge.md +22 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/memory-format.md +78 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/onboarding-decisions.yaml +187 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/operation-inventory.md +59 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/overview.md +167 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/reference.md +119 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/script-index.md +101 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/source-adapter-contract.md +93 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/source-platforms/claude-code-transcripts.md +66 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/source-platforms/codex-transcripts.md +78 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/source-platforms/codex.md +145 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/source-platforms/install-paths.md +57 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/source-platforms/langfuse.md +178 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/source-platforms/local-jsonl.md +55 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/source-platforms/openobserve.md +102 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/source-platforms/otel.md +63 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/target-platforms/cloud-rest.md +84 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/target-platforms/local-claude.md +65 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/target-platforms/local-cloud-agent-sdk.md +92 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/target-platforms/local-codex.md +72 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/target-platforms/local-cursor.md +108 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/target-platforms/local-mastra.md +77 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/target-platforms/local-opencode.md +70 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/workflows/apply-pr-comment-format.md +82 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/workflows/diagnostics.md +35 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/workflows/handover-contract.md +247 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/workflows/onboarding.md +300 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/workflows/orchestrator-protocol.md +1861 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/workflows/rca.md +331 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/workflows/rendering-anatomy.md +314 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/workflows/schedule-prep.md +100 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/workflows/scope-model.md +128 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/workflows/verification-methodology.md +174 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/aggregate/sort-findings.ts +0 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/awareness/blind-spots.ts +167 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/awareness/llm-sample.ts +681 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/cli/doctor.ts +215 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/cli/init.ts +1013 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/cli/install-agents.ts +350 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/cli/run.sh +61 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/cli/shared-templates.ts +79 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/config/load.ts +392 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/config/resolve-credential.ts +120 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/config/schema.ts +641 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/config/validate.ts +134 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/context/build-diagnosis-context.ts +417 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/context/load-context.ts +105 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/contract/types.ts +166 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/enrich/build-render-input.ts +1964 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/enrich/corpus-severity.ts +172 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/enrich/dismissal-match.ts +270 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/enrich/rank-remedies.ts +75 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/hooks/install-hooks.sh +46 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/hooks/pre-push.sh +78 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/invocation/parse-brief.ts +188 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/library/match.ts +114 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/library/paths.ts +95 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/library/store.ts +535 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/library/types.ts +181 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/lint/template-inline-js.ts +267 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/memory/append.ts +188 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/memory/read.ts +218 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/normalize/platforms/entity-context.ts +686 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/normalize/read-unitf.ts +267 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/normalize/trace.ts +1078 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/normalize/unitf-adapter.ts +0 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/normalize/unitf-types.ts +213 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/report/persist-selections.ts +174 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/report/render.ts +3254 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/run/diagnose.ts +64 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/run/session.ts +167 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/sample/caps.ts +345 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/sample/deep-read-gate.ts +424 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/sample/representative.ts +584 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/scan/objection.ts +224 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/scan/trajectory.ts +489 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/self-diagnostics/dispatch.ts +135 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/self-diagnostics/probe.ts +170 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/setup/detect.ts +307 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/setup/ensure-cli.ts +315 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/setup/reconfigure.ts +77 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/setup/verify-agents.ts +207 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/slicer.ts +166 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/source/adapters/claude-code.ts +17 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/source/adapters/codex.ts +11 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/source/adapters/langfuse.ts +17 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/source/adapters/local-jsonl.ts +12 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/source/adapters/otel.ts +12 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/source/index.ts +54 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/source/registry.ts +45 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/source/types.ts +86 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/stale-detector.ts +74 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/test/render-playwright.cli.ts +477 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/tier0/claude-code.ts +133 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/tier0/langfuse.ts +143 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/tier0-scan.ts +423 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/validate/completeness-check.ts +436 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/validate/doc-refs.ts +190 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/validate/finalize-gate.ts +417 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/validate/findings-contract.ts +628 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/validate/render-js-syntax.ts +188 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/validate/report-checklist.yaml +217 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/validate/trace-shape.ts +262 -0
- package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/validate/wave6-checklist.ts +326 -0
- package/mutagent-diagnostics/CLAUDE.md +41 -0
- package/mutagent-diagnostics/LICENSE +201 -0
- package/mutagent-diagnostics/NOTICE +18 -0
- package/mutagent-diagnostics/README.md +343 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/SKILL.md +548 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/assets/agents/audit-executor.md +169 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/assets/agents/dataset-builder.md +160 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/assets/agents/discovery.md +425 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/assets/agents/evaluator.md +1108 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/assets/brand/theme.css +213 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/assets/brand/wordmark.html +9 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/lenses/context-flow-lens.md +85 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/lenses/data-lens.md +47 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/lenses/decision-lens.md +48 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/lenses/methodology-critic-lens.md +53 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/lenses/trajectory-lens.md +44 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/build-review-interface.md +83 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/edd-loop.md +134 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/error-analysis.md +113 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/eval-audit.md +154 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/eval-stage.md +168 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/generate-synthetic-data.md +81 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/grounded-adjudication.md +221 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/memory-format.md +65 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/methodology.md +201 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/operation-inventory.md +197 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/validate-evaluator.md +125 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/workflows/orchestrator-protocol.md +300 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/write-judge-prompt.md +123 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/schemas/behavior-tree.schema.yaml +73 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/schemas/dataset.schema.yaml +66 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/schemas/edd-change-request.schema.yaml +114 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/schemas/eval-matrix.schema.yaml +74 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/schemas/flow-graph.schema.yaml +69 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/schemas/flow-profile.schema.yaml +49 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/schemas/methodology-review.schema.yaml +40 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/schemas/scorecard.schema.yaml +85 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/agent-dispatch.ts +0 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/aggregate-discover.ts +543 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/artifact-paths.ts +115 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/assemble-scorecard.ts +172 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/build-dataset.ts +186 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/build-evals.ts +93 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/build-review-ui.ts +393 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/check-method-router.ts +170 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cli/aggregate.ts +112 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cli/audit-run.ts +182 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cli/doctor.ts +211 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cli/dogfood.ts +133 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cli/init.ts +601 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cli/methodology-review.ts +122 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cli/prep.ts +295 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cli/profile-subject.ts +165 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cli/run.sh +56 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cli/variance-check.ts +105 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/code-eval.ts +248 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/code-quality-verdict.ts +285 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/codegen-evals.ts +173 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cold-start-project.ts +151 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cold-start-sampler.ts +267 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/config/load.ts +343 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/config/schema.ts +380 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/contracts/agentspec-evals.ts +85 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/contracts/dataset.ts +149 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/contracts/eval-engine.ts +118 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/contracts/eval-matrix.ts +577 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/contracts/eval-types.ts +1074 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/contracts/flow-graph.ts +194 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/contracts/types.ts +303 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/contracts/validation.ts +193 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/derive-dataset.ts +152 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/determine-outcome.ts +219 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/diff-discriminate.ts +160 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/discover-criteria.ts +348 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/edd/change-request.ts +232 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/edd/edd-types.ts +210 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/edd/variance-gate.ts +186 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/emit-completeness.ts +111 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/eval-engine.ts +160 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/evaluate.ts +333 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/flow-graph.ts +230 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/judge-prompt-template.ts +253 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/judge-provider.ts +135 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/lint-grounding.ts +229 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/lint-uniformity.ts +168 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/living-suite.ts +109 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/load-bundle.ts +203 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/load-profile-vocab.ts +64 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/load-profile.ts +106 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/mask.ts +138 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/materialize-dataset.ts +113 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/matrix-judge.ts +750 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/memory/append.ts +215 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/memory/read.ts +168 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/persist-eval-criteria.ts +232 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/prep-tasks.ts +125 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/profile-subject.ts +310 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/publish-report.ts +131 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/read-unitf-traces.ts +81 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/render-build-cards.ts +195 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/render-discover-report.ts +1640 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/render-eval-report.ts +3838 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/render-report.ts +212 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/resolve-credential.ts +110 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/resolve-ref.ts +98 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/result-verify.ts +129 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/route-failures.ts +330 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/run-deterministic.ts +367 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/run-evaluate.ts +719 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/run-judge.ts +155 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/run-pipeline.ts +175 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/sample-traces.ts +210 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/self-audit.ts +387 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/source-map.ts +106 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/subject-profile.ts +134 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/substrate.ts +162 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/sync-eval-criteria.ts +244 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/ui-slots.ts +119 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/unitf-to-evaltrace.ts +284 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/validate-judge.ts +358 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/variance-compare.ts +177 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/subjects/mutagent-diagnostics/behavior-tree.yaml +140 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/subjects/mutagent-diagnostics/eval-matrix.yaml +1270 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/subjects/mutagent-diagnostics/methodology-review.yaml +105 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/workflows/audit.workflow.js +82 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/workflows/data-leak.workflow.js +236 -0
- package/mutagent-evaluator/.claude/skills/mutagent-evaluator/workflows/variance.workflow.js +163 -0
- package/mutagent-evaluator/CLAUDE.md +45 -0
- package/mutagent-evaluator/LICENSE +201 -0
- package/mutagent-evaluator/NOTICE +23 -0
- package/mutagent-evaluator/README.md +88 -0
- package/mutagent-optimize/.claude/skills/mutagent-optimize/SKILL.md +287 -0
- package/mutagent-optimize/.claude/skills/mutagent-optimize/scripts/contracts/amend-request.ts +503 -0
- package/mutagent-optimize/.claude/skills/mutagent-optimize/scripts/improve-loop-run.ts +304 -0
- package/mutagent-optimize/.claude/skills/mutagent-optimize/scripts/loop-state-cli.ts +300 -0
- package/mutagent-optimize/.claude/skills/mutagent-optimize/scripts/loop-state.ts +440 -0
- package/mutagent-optimize/CLAUDE.md +49 -0
- package/mutagent-optimize/README.md +26 -0
- package/mutagent-orchestrator/CLAUDE.md +102 -0
- package/mutagent-orchestrator/README.md +20 -0
- package/mutagent-orchestrator/assets/agents/discovery.md +425 -0
- package/mutagent-orchestrator/assets/agents/dogfood-monitor.md +266 -0
- package/mutagent-orchestrator/assets/agents/monitor.md +258 -0
- package/mutagent-orchestrator/orchestrator.md +782 -0
- package/mutagent-orchestrator/references/MONITORING.md +209 -0
- package/mutagent-orchestrator/references/config-fields.md +132 -0
- package/mutagent-orchestrator/references/config-migration.md +132 -0
- package/mutagent-orchestrator/references/index-registry.md +92 -0
- package/mutagent-orchestrator/routing.yaml +391 -0
- package/mutagent-orchestrator/scripts/config-schema.ts +1010 -0
- package/mutagent-orchestrator/scripts/dispatch.ts +439 -0
- package/mutagent-orchestrator/scripts/dogfood/extract-feedback.ts +203 -0
- package/mutagent-orchestrator/scripts/dogfood/reconstruct-trajectory.ts +327 -0
- package/mutagent-orchestrator/scripts/dogfood/render-dogfood-report.ts +347 -0
- package/mutagent-orchestrator/scripts/dogfood/resolve-subagents.ts +160 -0
- package/mutagent-orchestrator/scripts/dogfood/run-report.ts +264 -0
- package/mutagent-orchestrator/scripts/dogfood/slack-thread.ts +106 -0
- package/mutagent-orchestrator/scripts/dogfood/types.ts +257 -0
- package/mutagent-orchestrator/scripts/eval-routing.ts +753 -0
- package/mutagent-orchestrator/scripts/gate.ts +219 -0
- package/mutagent-orchestrator/scripts/handover-contract.ts +362 -0
- package/mutagent-orchestrator/scripts/index/build-index.ts +351 -0
- package/mutagent-orchestrator/scripts/index/render-index.ts +110 -0
- package/mutagent-orchestrator/scripts/monitor/slack-notify.ts +111 -0
- package/mutagent-orchestrator/scripts/monitor/triggers.ts +162 -0
- package/mutagent-orchestrator/scripts/onboarding-check.ts +369 -0
- package/mutagent-orchestrator/scripts/render-roster.ts +308 -0
- package/mutagent-orchestrator/scripts/resolve-credential.ts +185 -0
- package/mutagent-orchestrator/scripts/resolve-paths.ts +114 -0
- package/mutagent-orchestrator/scripts/slack/format.ts +63 -0
- package/mutagent-orchestrator/scripts/slack/post.ts +115 -0
- package/mutagent-orchestrator/scripts/sync-index.ts +311 -0
- package/package.json +64 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scripts/memory/append.ts — project-level AutoMemory: APPEND (dated + classified).
|
|
3
|
+
* ---------------------------------------------------------------------------
|
|
4
|
+
* Append an operator-feedback entry to the project-level AutoMemory store
|
|
5
|
+
* (`.mutagent/memory/`) in the Claude-Code AutoMemory format
|
|
6
|
+
* (`references/memory-format.md`). The SUBJECT is the TOOL + operator preferences
|
|
7
|
+
* — NOT the evaluated agent (subject findings go to the living-suite, never here).
|
|
8
|
+
*
|
|
9
|
+
* The store: one FACT per `<slug>.md` file + an index `MEMORY.md`
|
|
10
|
+
* (`- [Title](<slug>.md) — <hook>` one line/entry). Every entry is DATED
|
|
11
|
+
* (`metadata.created`) + lifecycle-tagged. DEDUPE on append: an entry with the
|
|
12
|
+
* same slug is UPDATED (body + refreshed date), never duplicated.
|
|
13
|
+
*
|
|
14
|
+
* Determinism (coding-rules): the CORES are PURE — `now` (the date) is INJECTED,
|
|
15
|
+
* never read from a clock; fs is done only in the thin writer at the bottom. Tests
|
|
16
|
+
* exercise the pure cores with a fixed `now`. Standalone: no cross-skill import
|
|
17
|
+
* (mirrors the diagnostics library-store APPEND DISCIPLINE, not its per-entity
|
|
18
|
+
* keying — this store is flat + tool-scoped).
|
|
19
|
+
*/
|
|
20
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
21
|
+
import { join } from "node:path";
|
|
22
|
+
|
|
23
|
+
// ── Categorical constants (no magic strings) ─────────────────────────────────
|
|
24
|
+
|
|
25
|
+
/** Claude Code's four memory types (the classification target). */
|
|
26
|
+
export const MemoryType = {
|
|
27
|
+
User: "user",
|
|
28
|
+
Feedback: "feedback",
|
|
29
|
+
Project: "project",
|
|
30
|
+
Reference: "reference",
|
|
31
|
+
} as const;
|
|
32
|
+
export type MemoryTypeValue = (typeof MemoryType)[keyof typeof MemoryType];
|
|
33
|
+
|
|
34
|
+
/** The ADL lifecycle tag (the recall filter axis). */
|
|
35
|
+
export const Lifecycle = {
|
|
36
|
+
Spec: "spec",
|
|
37
|
+
Build: "build",
|
|
38
|
+
Evaluate: "evaluate",
|
|
39
|
+
Diagnose: "diagnose",
|
|
40
|
+
Improve: "improve",
|
|
41
|
+
General: "general",
|
|
42
|
+
} as const;
|
|
43
|
+
export type LifecycleValue = (typeof Lifecycle)[keyof typeof Lifecycle];
|
|
44
|
+
|
|
45
|
+
// ── Classification (the memory-format.md rubric — first match wins) ───────────
|
|
46
|
+
|
|
47
|
+
/** The raw operator feedback to classify + persist. */
|
|
48
|
+
export interface FeedbackInput {
|
|
49
|
+
/** the fact to store (verbatim operator text or a distilled summary). */
|
|
50
|
+
text: string;
|
|
51
|
+
/** optional caller hint (a URL / path) — strengthens the `reference` signal. */
|
|
52
|
+
resourceHint?: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Classify feedback into one of the four Claude-Code types by the memory-format.md
|
|
57
|
+
* decision order (FIRST match wins): reference → user → feedback → project. PURE,
|
|
58
|
+
* deterministic — regex + explicit hint, no I/O, no LLM. A caller may OVERRIDE the
|
|
59
|
+
* classification explicitly (an operator who knows the type); this is the default.
|
|
60
|
+
*/
|
|
61
|
+
export function classifyFeedback(fb: FeedbackInput): MemoryTypeValue {
|
|
62
|
+
const t = fb.text.trim();
|
|
63
|
+
// 1 — external resource (URL / dashboard / ticket / dataset path).
|
|
64
|
+
if (
|
|
65
|
+
fb.resourceHint !== undefined ||
|
|
66
|
+
/\bhttps?:\/\/\S+/i.test(t) ||
|
|
67
|
+
/\b(?:dashboard|ticket|dataset|\S+\.(?:ndjson|jsonl|csv|parquet)(?:\.gz)?)\b/i.test(t)
|
|
68
|
+
) {
|
|
69
|
+
return MemoryType.Reference;
|
|
70
|
+
}
|
|
71
|
+
// 2 — who the operator is (identity / standing preference about themselves).
|
|
72
|
+
if (/\bI['’]?m\b|\bI am\b|\bmy (?:role|team|preference)\b|\bas the (?:lead|operator|owner)\b/i.test(t)) {
|
|
73
|
+
return MemoryType.User;
|
|
74
|
+
}
|
|
75
|
+
// 3 — how the TOOL should behave (behavioral steer).
|
|
76
|
+
if (/\b(?:stop|don['’]?t|do not|too verbose|next time|always|never|prefer)\b/i.test(t)) {
|
|
77
|
+
return MemoryType.Feedback;
|
|
78
|
+
}
|
|
79
|
+
// 4 — ongoing work / goals / constraints (default).
|
|
80
|
+
return MemoryType.Project;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ── Slug + entry formatting ───────────────────────────────────────────────────
|
|
84
|
+
|
|
85
|
+
/** Kebab-case a title into a stable slug (deterministic — no random). */
|
|
86
|
+
export function slugify(title: string): string {
|
|
87
|
+
const s = title
|
|
88
|
+
.toLowerCase()
|
|
89
|
+
.replace(/['’"]/g, "")
|
|
90
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
91
|
+
.replace(/^-+|-+$/g, "");
|
|
92
|
+
return s === "" ? "untitled" : s;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface MemoryEntry {
|
|
96
|
+
/** kebab-case slug (the file name stem + `name:` frontmatter). */
|
|
97
|
+
slug: string;
|
|
98
|
+
/** one-line description (recall relevance). */
|
|
99
|
+
description: string;
|
|
100
|
+
type: MemoryTypeValue;
|
|
101
|
+
lifecycle: LifecycleValue;
|
|
102
|
+
/** YYYY-MM-DD (INJECTED — never a live clock). */
|
|
103
|
+
created: string;
|
|
104
|
+
/** the fact body (feedback/project carry **Why:** + **How to apply:** lines). */
|
|
105
|
+
body: string;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
109
|
+
|
|
110
|
+
/** Render a MemoryEntry to its `<slug>.md` file text (Claude-Code AutoMemory format). */
|
|
111
|
+
export function renderEntryMarkdown(entry: MemoryEntry): string {
|
|
112
|
+
if (!DATE_RE.test(entry.created)) {
|
|
113
|
+
throw new Error(
|
|
114
|
+
`renderEntryMarkdown: created must be YYYY-MM-DD (got '${entry.created}'). Every memory is DATED — ` +
|
|
115
|
+
"inject `now`, never read a clock.",
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
return (
|
|
119
|
+
"---\n" +
|
|
120
|
+
`name: ${entry.slug}\n` +
|
|
121
|
+
`description: ${entry.description}\n` +
|
|
122
|
+
"metadata:\n" +
|
|
123
|
+
` type: ${entry.type}\n` +
|
|
124
|
+
` lifecycle: ${entry.lifecycle}\n` +
|
|
125
|
+
` created: ${entry.created}\n` +
|
|
126
|
+
"---\n\n" +
|
|
127
|
+
entry.body.trimEnd() +
|
|
128
|
+
"\n"
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** The one index line for an entry (`- [Title](<slug>.md) — <hook>`). */
|
|
133
|
+
export function indexLine(entry: MemoryEntry): string {
|
|
134
|
+
return `- [${entry.slug}](${entry.slug}.md) — ${entry.description}`;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Fold an entry's index line into an existing `MEMORY.md`, DEDUPED by slug (an
|
|
139
|
+
* existing line for the same slug is REPLACED in place; a new slug is appended).
|
|
140
|
+
* PURE — string in, string out. Preserves a leading title/header block.
|
|
141
|
+
*/
|
|
142
|
+
export function upsertIndex(existingIndex: string, entry: MemoryEntry): string {
|
|
143
|
+
const newLine = indexLine(entry);
|
|
144
|
+
const lineRe = new RegExp(`^- \\[${entry.slug}\\]\\(${entry.slug}\\.md\\).*$`);
|
|
145
|
+
const lines = existingIndex.split("\n");
|
|
146
|
+
let replaced = false;
|
|
147
|
+
const out = lines.map((l) => {
|
|
148
|
+
if (lineRe.test(l)) {
|
|
149
|
+
replaced = true;
|
|
150
|
+
return newLine;
|
|
151
|
+
}
|
|
152
|
+
return l;
|
|
153
|
+
});
|
|
154
|
+
if (replaced) return out.join("\n");
|
|
155
|
+
// Append (ensure a header exists + trailing newline hygiene).
|
|
156
|
+
const base =
|
|
157
|
+
existingIndex.trim() === ""
|
|
158
|
+
? "# AutoMemory — index\n\n> Project-level operator-feedback + tool self-learning. One line per entry.\n"
|
|
159
|
+
: existingIndex.replace(/\n*$/, "\n");
|
|
160
|
+
return base + newLine + "\n";
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// ── Filesystem writer (the ONLY impure edge) ──────────────────────────────────
|
|
164
|
+
|
|
165
|
+
export interface AppendResult {
|
|
166
|
+
slug: string;
|
|
167
|
+
entryFile: string;
|
|
168
|
+
indexFile: string;
|
|
169
|
+
/** true when an existing entry was UPDATED (dedupe hit) rather than created. */
|
|
170
|
+
updated: boolean;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Append (or UPDATE) an AutoMemory entry under `<memoryDir>/`. Writes the
|
|
175
|
+
* `<slug>.md` file + upserts the `MEMORY.md` index line. DEDUPE: an existing
|
|
176
|
+
* `<slug>.md` is overwritten (not duplicated) and its index line replaced.
|
|
177
|
+
* `now` (YYYY-MM-DD) is INJECTED. The pure cores above do the formatting; this is
|
|
178
|
+
* the thin fs edge.
|
|
179
|
+
*/
|
|
180
|
+
export function appendMemory(
|
|
181
|
+
memoryDir: string,
|
|
182
|
+
input: { title: string; description: string; lifecycle: LifecycleValue; feedback: FeedbackInput; type?: MemoryTypeValue },
|
|
183
|
+
now: string,
|
|
184
|
+
): AppendResult {
|
|
185
|
+
const slug = slugify(input.title);
|
|
186
|
+
const type = input.type ?? classifyFeedback(input.feedback);
|
|
187
|
+
const entry: MemoryEntry = {
|
|
188
|
+
slug,
|
|
189
|
+
description: input.description,
|
|
190
|
+
type,
|
|
191
|
+
lifecycle: input.lifecycle,
|
|
192
|
+
created: now,
|
|
193
|
+
body: input.feedback.text.trim(),
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
mkdirSync(memoryDir, { recursive: true });
|
|
197
|
+
const entryFile = join(memoryDir, `${slug}.md`);
|
|
198
|
+
const updated = existsSync(entryFile);
|
|
199
|
+
writeFileSync(entryFile, renderEntryMarkdown(entry));
|
|
200
|
+
|
|
201
|
+
const indexFile = join(memoryDir, "MEMORY.md");
|
|
202
|
+
const existingIndex = existsSync(indexFile) ? readFileSync(indexFile, "utf8") : "";
|
|
203
|
+
writeFileSync(indexFile, upsertIndex(existingIndex, entry));
|
|
204
|
+
|
|
205
|
+
return { slug, entryFile, indexFile, updated };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/** List the entry slugs currently in a memory dir (PURE-ish fs read; [] if absent). */
|
|
209
|
+
export function listEntrySlugs(memoryDir: string): string[] {
|
|
210
|
+
if (!existsSync(memoryDir)) return [];
|
|
211
|
+
return readdirSync(memoryDir)
|
|
212
|
+
.filter((f) => f.endsWith(".md") && f !== "MEMORY.md")
|
|
213
|
+
.map((f) => f.replace(/\.md$/, ""))
|
|
214
|
+
.sort();
|
|
215
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scripts/memory/read.ts — project-level AutoMemory: READ (filter by lifecycle).
|
|
3
|
+
* ---------------------------------------------------------------------------
|
|
4
|
+
* Read the project-level AutoMemory store (`.mutagent/memory/`) at run START and
|
|
5
|
+
* return the entries relevant to THIS stage. The evaluator reads entries whose
|
|
6
|
+
* `lifecycle ∈ {evaluate, general}` (the run-start injection surface). The subject
|
|
7
|
+
* is the TOOL + operator preferences — NOT the evaluated agent.
|
|
8
|
+
*
|
|
9
|
+
* Determinism (coding-rules): the PARSE + FILTER cores are PURE (string in, data
|
|
10
|
+
* out); fs is confined to `readMemoryDir`. Tests exercise the pure cores against
|
|
11
|
+
* committed fixture text. Standalone — no cross-skill import.
|
|
12
|
+
*
|
|
13
|
+
* Format: one FACT per `<slug>.md`, Claude-Code AutoMemory frontmatter
|
|
14
|
+
* (`references/memory-format.md`). A malformed / partial entry is SKIPPED (never
|
|
15
|
+
* throws) so one bad file can't blind a run.
|
|
16
|
+
*/
|
|
17
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
18
|
+
import { join } from "node:path";
|
|
19
|
+
import {
|
|
20
|
+
Lifecycle,
|
|
21
|
+
MemoryType,
|
|
22
|
+
type LifecycleValue,
|
|
23
|
+
type MemoryTypeValue,
|
|
24
|
+
} from "./append.ts";
|
|
25
|
+
|
|
26
|
+
export interface ParsedMemoryEntry {
|
|
27
|
+
slug: string;
|
|
28
|
+
description: string;
|
|
29
|
+
type: MemoryTypeValue;
|
|
30
|
+
lifecycle: LifecycleValue;
|
|
31
|
+
created: string;
|
|
32
|
+
body: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const LIFECYCLE_VALUES = new Set<string>(Object.values(Lifecycle));
|
|
36
|
+
const TYPE_VALUES = new Set<string>(Object.values(MemoryType));
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Parse ONE `<slug>.md` entry (frontmatter + body). Returns null on a malformed /
|
|
40
|
+
* partial entry (missing frontmatter, unknown type/lifecycle, absent date) — a bad
|
|
41
|
+
* file is SKIPPED, never fatal. PURE — string in, entry out. `fallbackSlug` is the
|
|
42
|
+
* file stem, used when the `name:` field is absent.
|
|
43
|
+
*/
|
|
44
|
+
export function parseMemoryEntry(text: string, fallbackSlug: string): ParsedMemoryEntry | null {
|
|
45
|
+
const m = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/.exec(text);
|
|
46
|
+
if (m === null) return null;
|
|
47
|
+
const front = m[1] ?? "";
|
|
48
|
+
const body = (m[2] ?? "").trim();
|
|
49
|
+
|
|
50
|
+
const scalar = (key: string): string | undefined => {
|
|
51
|
+
// top-level `key: value` OR nested ` key: value` (metadata block).
|
|
52
|
+
const re = new RegExp(`^\\s*${key}:\\s*(.+?)\\s*$`, "m");
|
|
53
|
+
const mm = re.exec(front);
|
|
54
|
+
return mm ? (mm[1] as string).trim() : undefined;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const slug = scalar("name") ?? fallbackSlug;
|
|
58
|
+
const description = scalar("description") ?? "";
|
|
59
|
+
const type = scalar("type");
|
|
60
|
+
const lifecycle = scalar("lifecycle");
|
|
61
|
+
const created = scalar("created");
|
|
62
|
+
|
|
63
|
+
if (type === undefined || !TYPE_VALUES.has(type)) return null;
|
|
64
|
+
if (lifecycle === undefined || !LIFECYCLE_VALUES.has(lifecycle)) return null;
|
|
65
|
+
if (created === undefined || !/^\d{4}-\d{2}-\d{2}$/.test(created)) return null;
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
slug,
|
|
69
|
+
description,
|
|
70
|
+
type: type as MemoryTypeValue,
|
|
71
|
+
lifecycle: lifecycle as LifecycleValue,
|
|
72
|
+
created,
|
|
73
|
+
body,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Keep only entries whose `lifecycle` is in `stages` (the recall filter). PURE.
|
|
79
|
+
* For the evaluator run start: `stages = [Evaluate, General]`.
|
|
80
|
+
*/
|
|
81
|
+
export function filterByLifecycle(
|
|
82
|
+
entries: ParsedMemoryEntry[],
|
|
83
|
+
stages: LifecycleValue[],
|
|
84
|
+
): ParsedMemoryEntry[] {
|
|
85
|
+
const want = new Set<string>(stages);
|
|
86
|
+
return entries.filter((e) => want.has(e.lifecycle));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** The default recall filter for an EVALUATE run: {evaluate, general}. */
|
|
90
|
+
export const EVALUATE_RECALL: LifecycleValue[] = [Lifecycle.Evaluate, Lifecycle.General];
|
|
91
|
+
|
|
92
|
+
export interface ReadMemoryResult {
|
|
93
|
+
exists: boolean;
|
|
94
|
+
/** entries matching the lifecycle filter, sorted by slug (deterministic). */
|
|
95
|
+
entries: ParsedMemoryEntry[];
|
|
96
|
+
/** files that failed to parse (skipped) — surfaced for honesty, never fatal. */
|
|
97
|
+
skipped: string[];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Read `<memoryDir>/*.md` (excluding the `MEMORY.md` index), parse each, and
|
|
102
|
+
* return the entries matching `stages` (default = EVALUATE_RECALL). A missing dir
|
|
103
|
+
* → `{ exists:false, entries:[] }`. A malformed file is SKIPPED (listed in
|
|
104
|
+
* `skipped`). Deterministic: entries sorted by slug. The ONLY impure edge.
|
|
105
|
+
*/
|
|
106
|
+
export function readMemoryDir(
|
|
107
|
+
memoryDir: string,
|
|
108
|
+
stages: LifecycleValue[] = EVALUATE_RECALL,
|
|
109
|
+
): ReadMemoryResult {
|
|
110
|
+
if (!existsSync(memoryDir)) return { exists: false, entries: [], skipped: [] };
|
|
111
|
+
|
|
112
|
+
const files = readdirSync(memoryDir)
|
|
113
|
+
.filter((f) => f.endsWith(".md") && f !== "MEMORY.md")
|
|
114
|
+
.sort();
|
|
115
|
+
|
|
116
|
+
const parsed: ParsedMemoryEntry[] = [];
|
|
117
|
+
const skipped: string[] = [];
|
|
118
|
+
for (const f of files) {
|
|
119
|
+
const stem = f.replace(/\.md$/, "");
|
|
120
|
+
let text: string;
|
|
121
|
+
try {
|
|
122
|
+
text = readFileSync(join(memoryDir, f), "utf8");
|
|
123
|
+
} catch {
|
|
124
|
+
skipped.push(f);
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const entry = parseMemoryEntry(text, stem);
|
|
128
|
+
if (entry === null) {
|
|
129
|
+
skipped.push(f);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
parsed.push(entry);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return { exists: true, entries: filterByLifecycle(parsed, stages), skipped };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Render the recalled entries as a compact operator-preference context block for
|
|
140
|
+
* injection at run start (one bullet per entry: type · slug · description). PURE.
|
|
141
|
+
* EMPTY string when nothing recalled (a run with no AutoMemory is byte-identical
|
|
142
|
+
* to the legacy no-memory path).
|
|
143
|
+
*/
|
|
144
|
+
export function renderRecallContext(entries: ParsedMemoryEntry[]): string {
|
|
145
|
+
if (entries.length === 0) return "";
|
|
146
|
+
const bullets = entries
|
|
147
|
+
.map((e) => `- [${e.type}] ${e.slug} — ${e.description}`)
|
|
148
|
+
.join("\n");
|
|
149
|
+
return `AutoMemory (operator preferences · evaluate + general):\n${bullets}`;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// ── CLI — thin wrapper (print the recalled entries for a project root) ─────────
|
|
153
|
+
// bun scripts/memory/read.ts [project-root]
|
|
154
|
+
|
|
155
|
+
function memoryDirFor(projectRoot: string): string {
|
|
156
|
+
return join(projectRoot, ".mutagent", "memory");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const isMain =
|
|
160
|
+
typeof import.meta !== "undefined" &&
|
|
161
|
+
(import.meta as unknown as { main?: boolean }).main === true;
|
|
162
|
+
if (isMain) {
|
|
163
|
+
const argv = typeof Bun !== "undefined" ? Bun.argv : process.argv;
|
|
164
|
+
const projectRoot = argv[2] ?? process.cwd();
|
|
165
|
+
const result = readMemoryDir(memoryDirFor(projectRoot));
|
|
166
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
167
|
+
process.exit(0);
|
|
168
|
+
}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scripts/persist-eval-criteria.ts — the EVAL-LEG on-disk WRITER (Wave-2 FU57 · KP-003).
|
|
3
|
+
* ---------------------------------------------------------------------------
|
|
4
|
+
* The IO half of the eval-leg reconcile. `sync-eval-criteria.ts` COMPUTES the grown
|
|
5
|
+
* criteria set as DATA (`reconcileEvalCriteria` — pure upsert-by-id, monotonic, never
|
|
6
|
+
* drops); it never touches disk. This module is the deterministic WRITER the evaluator
|
|
7
|
+
* SESSION calls to PERSIST that computed set back to the located eval-suite criteria
|
|
8
|
+
* artifact — the write that bumps the artifact's freshness and thereby returns the eval
|
|
9
|
+
* leg of `#sync-spec` to `in-sync` (the builder freshness probe reads the artifact's
|
|
10
|
+
* mtime / `updatedAt`; a fresh write makes the eval criteria as new as the amended impl).
|
|
11
|
+
*
|
|
12
|
+
* SEPARATION OF CONCERNS (mirrors `artifact-paths.ts` + `aggregate-discover.ts` doing IO
|
|
13
|
+
* while `living-suite.ts` stays pure): the reconcile COMPUTE is pure/C-PIN; this WRITE is
|
|
14
|
+
* the IO layer. The SERIALIZATION here is still deterministic (stable key order, no clock
|
|
15
|
+
* embedded unless the caller passes an explicit `updatedAt`), so a persisted artifact
|
|
16
|
+
* round-trips byte-faithful.
|
|
17
|
+
*
|
|
18
|
+
* JUDGE-ONLY PRESERVED (EV-051): this file writes CRITERIA (the evaluator maintaining its
|
|
19
|
+
* own eval-suite / code-quality criteria set) — it NEVER scores a subject, NEVER decides a
|
|
20
|
+
* pass/fail, and NEVER dispatches an agent (Model-B: code is a deterministic writer; the
|
|
21
|
+
* reconcile REASONING is the ai-architect's, session-dispatched).
|
|
22
|
+
*
|
|
23
|
+
* LOCATION + FORMAT (mirror the living-suite persistence; FLAGGED-for-operator, see
|
|
24
|
+
* `EVAL_CRITERIA_ARTIFACT_FILENAMES`): the artifact lands under the evaluator's namespaced
|
|
25
|
+
* `.mutagent/evaluator/living-suite/` root (`artifact-paths.ts` `livingSuiteDir`, auto-
|
|
26
|
+
* gitignored, no-spillover-guarded) as one JSON file per LEG — the same dir + extension the
|
|
27
|
+
* builder `check-sync-spec.ts` `locateEvalCriteria` auto-discovers.
|
|
28
|
+
*/
|
|
29
|
+
import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
30
|
+
import { dirname, join } from "node:path";
|
|
31
|
+
import { type Static, Type } from "@sinclair/typebox";
|
|
32
|
+
import { Value } from "@sinclair/typebox/value";
|
|
33
|
+
|
|
34
|
+
import { assertUnderRoot, livingSuiteDir } from "./artifact-paths.ts";
|
|
35
|
+
import {
|
|
36
|
+
EvalCriterionSchema,
|
|
37
|
+
EvalLegKind,
|
|
38
|
+
reconcileEvalCriteria,
|
|
39
|
+
type EvalCriteriaReconcileRequest,
|
|
40
|
+
type EvalCriteriaReconcileResult,
|
|
41
|
+
type EvalCriterion,
|
|
42
|
+
type EvalLegKindValue,
|
|
43
|
+
} from "./sync-eval-criteria.ts";
|
|
44
|
+
|
|
45
|
+
// ── the on-disk artifact shape (mirror LivingSuite `{ …, provenance }`) ───────
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The persisted eval-criteria artifact — one per LEG. Mirrors the living-suite shape
|
|
49
|
+
* (a keyed collection + provenance), specialized to the reconcile result: the maintained
|
|
50
|
+
* `criteria` set, the reconcile `provenance` counters, and an OPTIONAL `updatedAt`
|
|
51
|
+
* freshness marker. `updatedAt` is the ONE clock-bearing field and it is NEVER generated
|
|
52
|
+
* here — the caller (the session, Model-B) passes it when it wants a content-level
|
|
53
|
+
* freshness stamp the builder probe's `parseEvalUpdatedAt` can read; omitted, freshness
|
|
54
|
+
* rides on the file's mtime alone (write bumps it). `additionalProperties: false` keeps the
|
|
55
|
+
* header tight while each criterion stays forward-parsing (EvalCriterionSchema is open).
|
|
56
|
+
*/
|
|
57
|
+
export const EvalCriteriaArtifactSchema = Type.Object(
|
|
58
|
+
{
|
|
59
|
+
subjectId: Type.String({ minLength: 1 }),
|
|
60
|
+
leg: Type.Union([
|
|
61
|
+
Type.Literal(EvalLegKind.EvalSuite),
|
|
62
|
+
Type.Literal(EvalLegKind.CodeQuality),
|
|
63
|
+
]),
|
|
64
|
+
criteria: Type.Array(EvalCriterionSchema),
|
|
65
|
+
provenance: Type.Object(
|
|
66
|
+
{ added: Type.Number(), updated: Type.Number(), total: Type.Number() },
|
|
67
|
+
{ additionalProperties: false },
|
|
68
|
+
),
|
|
69
|
+
updatedAt: Type.Optional(Type.String({ minLength: 1 })),
|
|
70
|
+
},
|
|
71
|
+
{ additionalProperties: false },
|
|
72
|
+
);
|
|
73
|
+
export type EvalCriteriaArtifact = Static<typeof EvalCriteriaArtifactSchema>;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* FLAGGED-for-operator: the per-leg artifact FILENAME under `.mutagent/evaluator/living-suite/`.
|
|
77
|
+
* The sensible default that mirrors the living-suite location AND the builder probe's
|
|
78
|
+
* conventional fallback names (`eval-criteria` / `code-quality-criteria`), one file per leg
|
|
79
|
+
* so the two legs never collide. Both are `.json` under the dir `check-sync-spec.ts`
|
|
80
|
+
* `locateEvalCriteria` walks (`*.{yaml,yml,json}`), so a written artifact is auto-discovered
|
|
81
|
+
* as the eval-leg freshness anchor with no extra wiring. (A workspace evaluates ONE subject,
|
|
82
|
+
* so only its leg's file exists; multi-subject-per-workspace would want a `<subjectId>/`
|
|
83
|
+
* sub-dir — deferred, flagged.)
|
|
84
|
+
*/
|
|
85
|
+
export const EVAL_CRITERIA_ARTIFACT_FILENAMES: Readonly<Record<EvalLegKindValue, string>> = {
|
|
86
|
+
[EvalLegKind.EvalSuite]: "eval-suite.criteria.json",
|
|
87
|
+
[EvalLegKind.CodeQuality]: "code-quality.criteria.json",
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Resolve the located eval-criteria artifact path for a leg:
|
|
92
|
+
* `<cwd>/.mutagent/evaluator/living-suite/<leg>.criteria.json`. Routes through the
|
|
93
|
+
* `artifact-paths.ts` no-spillover guard (`assertUnderRoot`), so the writer can NEVER
|
|
94
|
+
* escape the evaluator's namespaced root. `cwd` passed in (pure path construction).
|
|
95
|
+
*/
|
|
96
|
+
export function evalCriteriaArtifactPath(leg: EvalLegKindValue, cwd?: string): string {
|
|
97
|
+
return assertUnderRoot(join(livingSuiteDir(cwd), EVAL_CRITERIA_ARTIFACT_FILENAMES[leg]), cwd);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ── serialize / build (pure, deterministic — no clock) ───────────────────────
|
|
101
|
+
|
|
102
|
+
/** Build the on-disk artifact from a reconcile RESULT. Pure. `updatedAt` passed in. */
|
|
103
|
+
export function evalCriteriaArtifactFromResult(
|
|
104
|
+
result: EvalCriteriaReconcileResult,
|
|
105
|
+
updatedAt?: string,
|
|
106
|
+
): EvalCriteriaArtifact {
|
|
107
|
+
return {
|
|
108
|
+
subjectId: result.subjectId,
|
|
109
|
+
leg: result.leg,
|
|
110
|
+
criteria: result.criteria,
|
|
111
|
+
provenance: result.provenance,
|
|
112
|
+
...(updatedAt !== undefined ? { updatedAt } : {}),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Serialize an artifact to its on-disk JSON — DETERMINISTIC: explicit key order, 2-space
|
|
118
|
+
* indent, trailing newline. Same artifact → byte-identical string (round-trip faithful);
|
|
119
|
+
* no clock unless the artifact already carries a caller-supplied `updatedAt`.
|
|
120
|
+
*/
|
|
121
|
+
export function serializeEvalCriteriaArtifact(artifact: EvalCriteriaArtifact): string {
|
|
122
|
+
const ordered: EvalCriteriaArtifact = {
|
|
123
|
+
subjectId: artifact.subjectId,
|
|
124
|
+
leg: artifact.leg,
|
|
125
|
+
criteria: artifact.criteria,
|
|
126
|
+
provenance: artifact.provenance,
|
|
127
|
+
...(artifact.updatedAt !== undefined ? { updatedAt: artifact.updatedAt } : {}),
|
|
128
|
+
};
|
|
129
|
+
return `${JSON.stringify(ordered, null, 2)}\n`;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Guarded parse of a persisted artifact. THROWS with the first schema error. PURE. */
|
|
133
|
+
export function parseEvalCriteriaArtifact(value: unknown): EvalCriteriaArtifact {
|
|
134
|
+
if (!Value.Check(EvalCriteriaArtifactSchema, value)) {
|
|
135
|
+
const first = [...Value.Errors(EvalCriteriaArtifactSchema, value)][0];
|
|
136
|
+
throw new Error(
|
|
137
|
+
`parseEvalCriteriaArtifact: schema violation at '${first?.path ?? "(root)"}': ` +
|
|
138
|
+
`${first?.message ?? "invalid eval-criteria artifact"}`,
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
return value;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// ── the WRITER + reader (the IO layer) ───────────────────────────────────────
|
|
145
|
+
|
|
146
|
+
/** The result of a persist: WHERE it landed + WHAT was written (artifact + bytes). */
|
|
147
|
+
export interface PersistEvalCriteriaResult {
|
|
148
|
+
/** the located artifact path the criteria were written to. */
|
|
149
|
+
path: string;
|
|
150
|
+
/** the artifact that was serialized. */
|
|
151
|
+
artifact: EvalCriteriaArtifact;
|
|
152
|
+
/** the exact bytes written (for a byte-faithful round-trip assertion). */
|
|
153
|
+
json: string;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* PERSIST a reconcile result's `criteria` back to the located eval-suite criteria artifact
|
|
158
|
+
* — the WRITE that returns the eval leg to `in-sync`. Resolves the per-leg path under
|
|
159
|
+
* `.mutagent/evaluator/living-suite/` (no-spillover-guarded via `artifact-paths.ts`),
|
|
160
|
+
* ensures the dir, and writes the deterministic JSON. Handles BOTH legs by `result.leg`:
|
|
161
|
+
* the eval-suite leg (agent/skill/composite subject) and the code-quality leg (a code
|
|
162
|
+
* subject, incl. an operator-overridden code-quality set). The freshness bump is the file
|
|
163
|
+
* write itself (mtime advances → the builder probe reads the eval leg as fresh); pass
|
|
164
|
+
* `options.updatedAt` (ISO 8601) to ALSO stamp a content-level freshness marker the probe's
|
|
165
|
+
* `parseEvalUpdatedAt` reads. IO — NOT pure (that is its job); serialization is deterministic.
|
|
166
|
+
*/
|
|
167
|
+
export function persistEvalCriteria(
|
|
168
|
+
result: EvalCriteriaReconcileResult,
|
|
169
|
+
options: { cwd?: string; updatedAt?: string } = {},
|
|
170
|
+
): PersistEvalCriteriaResult {
|
|
171
|
+
const artifact = evalCriteriaArtifactFromResult(result, options.updatedAt);
|
|
172
|
+
const path = evalCriteriaArtifactPath(result.leg, options.cwd);
|
|
173
|
+
const json = serializeEvalCriteriaArtifact(artifact);
|
|
174
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
175
|
+
writeFileSync(path, json);
|
|
176
|
+
return { path, artifact, json };
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** Read + validate a persisted artifact (round-trip). THROWS on a schema violation. */
|
|
180
|
+
export function readEvalCriteriaArtifact(path: string): EvalCriteriaArtifact {
|
|
181
|
+
return parseEvalCriteriaArtifact(JSON.parse(readFileSync(path, "utf8")) as unknown);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Load the CURRENTLY-persisted criteria for a leg (the `existing` set the next reconcile
|
|
186
|
+
* grows). Returns `[]` when no artifact exists yet (the cold / first-reconcile case) so a
|
|
187
|
+
* caller can feed it straight into an `EvalCriteriaReconcileRequest.existing`. Reads only.
|
|
188
|
+
*/
|
|
189
|
+
export function loadExistingEvalCriteria(leg: EvalLegKindValue, cwd?: string): EvalCriterion[] {
|
|
190
|
+
const path = evalCriteriaArtifactPath(leg, cwd);
|
|
191
|
+
if (!existsSync(path)) return [];
|
|
192
|
+
return readEvalCriteriaArtifact(path).criteria;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* The eval-criteria artifact's effective freshness epoch (seconds) — the evaluator-side
|
|
197
|
+
* MIRROR of the builder `check-sync-spec.ts` eval-leg compare: `max(updatedAt, mtime)`
|
|
198
|
+
* (git omitted — kept in-package + git-independent). `null` when the artifact is absent.
|
|
199
|
+
* Feed this as `evalCriteriaEpoch` to `flagEvalLegDrift` to confirm a fresh write closed
|
|
200
|
+
* the loop (`in-sync`). Reads mtime (IO).
|
|
201
|
+
*/
|
|
202
|
+
export function evalCriteriaEffectiveEpoch(path: string): number | null {
|
|
203
|
+
if (!existsSync(path)) return null;
|
|
204
|
+
const epochs: number[] = [];
|
|
205
|
+
try {
|
|
206
|
+
const parsed = readEvalCriteriaArtifact(path);
|
|
207
|
+
if (parsed.updatedAt !== undefined) {
|
|
208
|
+
const ms = Date.parse(parsed.updatedAt);
|
|
209
|
+
if (Number.isFinite(ms)) epochs.push(Math.floor(ms / 1000));
|
|
210
|
+
}
|
|
211
|
+
} catch {
|
|
212
|
+
// a corrupt artifact still has an mtime — fall back to it for freshness.
|
|
213
|
+
}
|
|
214
|
+
epochs.push(Math.floor(statSync(path).mtimeMs / 1000));
|
|
215
|
+
return Math.max(...epochs);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Convenience for the session: COMPUTE the reconcile (pure) THEN PERSIST it (IO) in one
|
|
220
|
+
* call — the exact "reconcile → write → in-sync" step the `#sync-spec` eval leg performs.
|
|
221
|
+
* Still Model-B: the criteria DELTA (`request.proposed`) is the ai-architect's reasoning;
|
|
222
|
+
* this only applies it deterministically and writes it. Returns the compute result + the
|
|
223
|
+
* persist result together.
|
|
224
|
+
*/
|
|
225
|
+
export function reconcileAndPersistEvalCriteria(
|
|
226
|
+
request: EvalCriteriaReconcileRequest,
|
|
227
|
+
options: { cwd?: string; updatedAt?: string } = {},
|
|
228
|
+
): { result: EvalCriteriaReconcileResult; persisted: PersistEvalCriteriaResult } {
|
|
229
|
+
const result = reconcileEvalCriteria(request);
|
|
230
|
+
const persisted = persistEvalCriteria(result, options);
|
|
231
|
+
return { result, persisted };
|
|
232
|
+
}
|