@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,686 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scripts/normalize/platforms/entity-context.ts
|
|
3
|
+
* Wave-5 R1.7 (APPENDIX-A §A.2): shared, DETERMINISTIC EntityContext extraction
|
|
4
|
+
* helpers used by every per-platform normalizer.
|
|
5
|
+
* Type A — Pure Script (content-derived only — NO LLM, NO clock, NO random).
|
|
6
|
+
*
|
|
7
|
+
* Each platform normalizer derives an EntityContext from its TraceBody[] using
|
|
8
|
+
* these helpers so re-runs over identical input are byte-identical.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { createHash } from "crypto";
|
|
12
|
+
import type {
|
|
13
|
+
TraceBody,
|
|
14
|
+
EntityContext,
|
|
15
|
+
EntityIdentityPointers,
|
|
16
|
+
SizedText,
|
|
17
|
+
ToolInventoryEntry,
|
|
18
|
+
} from "../trace.ts";
|
|
19
|
+
import type { AgentIdentity } from "../../config/schema.ts";
|
|
20
|
+
|
|
21
|
+
// ── byte-length + token approximation (deterministic) ────────────────────────
|
|
22
|
+
|
|
23
|
+
/** UTF-8 byte length of a string (Buffer.byteLength is deterministic). */
|
|
24
|
+
export function byteLength(text: string): number {
|
|
25
|
+
return Buffer.byteLength(text, "utf8");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Approximate token count from character length (≈ 4 chars/token).
|
|
30
|
+
* Deterministic heuristic — no tokenizer, no network.
|
|
31
|
+
*/
|
|
32
|
+
export function approxTokens(text: string): number {
|
|
33
|
+
return Math.ceil(text.length / 4);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Build a SizedText with byteLength + token approximation filled in. */
|
|
37
|
+
export function sized(text: string): SizedText {
|
|
38
|
+
return { text, sizeBytes: byteLength(text), tokensApprox: approxTokens(text) };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ── Variance fix (Wave-13): deterministic synthetic trace IDs ─────────────────
|
|
42
|
+
//
|
|
43
|
+
// The non-langfuse normalizers used to mint synthetic IDs from `Date.now()`
|
|
44
|
+
// (`cc-${Date.now()}`, `codex-${Date.now()}`, `local-${Date.now()}`) when the
|
|
45
|
+
// source carried no native id. That poisons the dedup / selection primary key:
|
|
46
|
+
// the SAME input file produces a DIFFERENT id on every run, so re-runs can't be
|
|
47
|
+
// compared and identical traces look distinct.
|
|
48
|
+
//
|
|
49
|
+
// Replace with a content hash over STABLE trace content — same input always
|
|
50
|
+
// yields the same id, across runs and machines. No clock, no random.
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Deterministic synthetic trace id: `<prefix>-<first 16 hex of sha256(content)>`.
|
|
54
|
+
*
|
|
55
|
+
* `content` MUST be derived from stable, content-bearing fields of the trace
|
|
56
|
+
* (e.g. JSON.stringify of the raw events / line) — NEVER from a clock or random
|
|
57
|
+
* source. The 16-hex (64-bit) prefix is collision-safe for trace-set sizes and
|
|
58
|
+
* keeps the id short + readable.
|
|
59
|
+
*
|
|
60
|
+
* Determinism contract: same `prefix` + same `content` ⇒ byte-identical id.
|
|
61
|
+
*/
|
|
62
|
+
export function deterministicTraceId(prefix: string, content: string): string {
|
|
63
|
+
const digest = createHash("sha256").update(content, "utf8").digest("hex");
|
|
64
|
+
return `${prefix}-${digest.slice(0, 16)}`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ── PII sanitization (deterministic regex scrub) ─────────────────────────────
|
|
68
|
+
|
|
69
|
+
const EMAIL_RE = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
|
|
70
|
+
// Long bearer/api tokens (20+ base64-ish chars), AWS-style keys, sk- prefixed keys.
|
|
71
|
+
const TOKEN_RE = /\b(?:sk-[A-Za-z0-9]{16,}|AKIA[0-9A-Z]{16}|[A-Za-z0-9_-]{32,})\b/g;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Scrub obvious PII / secrets from a text blob before it lands in a report.
|
|
75
|
+
* Deterministic — same input → same output.
|
|
76
|
+
*/
|
|
77
|
+
export function sanitize(text: string): string {
|
|
78
|
+
return text.replace(EMAIL_RE, "<email>").replace(TOKEN_RE, "<token>");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ── W12-09: input-envelope unwrap (deterministic, conservative) ──────────────
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Common single-field text envelopes a trace input may be wrapped in. When the
|
|
85
|
+
* input text is `JSON.stringify(raw.input)` (langfuse normalizer behaviour) and
|
|
86
|
+
* the parsed object has exactly ONE of these as its dominant text field, we
|
|
87
|
+
* extract that field's prose so the entity card shows clean text instead of a
|
|
88
|
+
* `{"prompt":"…"}` escaped wrapper.
|
|
89
|
+
*/
|
|
90
|
+
const ENVELOPE_TEXT_KEYS = ["prompt", "input", "content", "text", "query"] as const;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* W12-09 (P2): deterministically unwrap a common JSON text-envelope.
|
|
94
|
+
*
|
|
95
|
+
* Behaviour (CONSERVATIVE — never mangle legitimately-structured input):
|
|
96
|
+
* - If `text` does NOT parse as JSON → return it unchanged (plain prose).
|
|
97
|
+
* - If it parses to a STRING → return that string (a doubly-encoded prompt).
|
|
98
|
+
* - If it parses to an OBJECT with a DOMINANT text field, extract it:
|
|
99
|
+
* • a single `ENVELOPE_TEXT_KEYS` entry whose value is a non-empty string
|
|
100
|
+
* (e.g. `{"prompt":"hello"}` → "hello"); OR
|
|
101
|
+
* • a `messages` array whose LAST entry has a string `.content`
|
|
102
|
+
* (chat-style envelope → the latest turn's text).
|
|
103
|
+
* - Otherwise (no dominant text field, multiple competing text keys, an
|
|
104
|
+
* array of non-messages, nested objects) → return the ORIGINAL text
|
|
105
|
+
* unchanged so genuinely-structured input is preserved verbatim.
|
|
106
|
+
*
|
|
107
|
+
* Deterministic — pure string→string, no clock/random/LLM.
|
|
108
|
+
*/
|
|
109
|
+
export function unwrapEnvelope(text: string): string {
|
|
110
|
+
const trimmed = text.trim();
|
|
111
|
+
// Cheap guard: only attempt a parse on JSON-looking payloads.
|
|
112
|
+
if (!trimmed || (trimmed[0] !== "{" && trimmed[0] !== "[" && trimmed[0] !== '"')) {
|
|
113
|
+
return text;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
let parsed: unknown;
|
|
117
|
+
try {
|
|
118
|
+
parsed = JSON.parse(trimmed);
|
|
119
|
+
} catch {
|
|
120
|
+
return text; // not JSON → leave as-is
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Doubly-encoded string → the inner prose.
|
|
124
|
+
if (typeof parsed === "string") return parsed;
|
|
125
|
+
|
|
126
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
127
|
+
const obj = parsed as Record<string, unknown>;
|
|
128
|
+
|
|
129
|
+
// Count how many of the known text keys carry a non-empty string value.
|
|
130
|
+
const present = ENVELOPE_TEXT_KEYS.filter(
|
|
131
|
+
(k) => typeof obj[k] === "string" && (obj[k] as string).trim().length > 0
|
|
132
|
+
);
|
|
133
|
+
// Exactly one dominant text field → unwrap it.
|
|
134
|
+
if (present.length === 1) {
|
|
135
|
+
return obj[present[0]] as string;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Chat-style envelope: `messages[]` whose last entry has string content.
|
|
139
|
+
if (present.length === 0 && Array.isArray(obj.messages) && obj.messages.length > 0) {
|
|
140
|
+
const last = obj.messages[obj.messages.length - 1];
|
|
141
|
+
if (last && typeof last === "object" && typeof (last as Record<string, unknown>).content === "string") {
|
|
142
|
+
const content = (last as Record<string, unknown>).content as string;
|
|
143
|
+
if (content.trim().length > 0) return content;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// No dominant text field (structured input) → preserve verbatim.
|
|
149
|
+
return text;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Build a sanitized, sized input sample (sliced to `maxChars`, default 4096).
|
|
154
|
+
*
|
|
155
|
+
* W12-09: first unwrap a common JSON text-envelope (`{"prompt":"…"}` etc.) so
|
|
156
|
+
* the card shows clean prose, not an escaped wrapper. Unwrap is conservative —
|
|
157
|
+
* structured input with no dominant text field passes through unchanged.
|
|
158
|
+
*/
|
|
159
|
+
export function inputSample(
|
|
160
|
+
text: string,
|
|
161
|
+
maxChars = 4096
|
|
162
|
+
): SizedText & { sanitized: boolean } {
|
|
163
|
+
const unwrapped = unwrapEnvelope(text);
|
|
164
|
+
const sliced = unwrapped.slice(0, maxChars);
|
|
165
|
+
const clean = sanitize(sliced);
|
|
166
|
+
return {
|
|
167
|
+
...sized(clean),
|
|
168
|
+
sanitized: clean !== sliced,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ── system-prompt extraction ─────────────────────────────────────────────────
|
|
173
|
+
|
|
174
|
+
const SYSTEM_TAG_RE = /<system>([\s\S]*?)<\/system>/i;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* F-S2c: the set of redaction placeholders `sanitize()` substitutes in. A prompt
|
|
178
|
+
* whose sanitized form is ONLY these placeholders + whitespace carried no real
|
|
179
|
+
* (non-secret) content — it was a credentials-only prompt, fully redacted.
|
|
180
|
+
*/
|
|
181
|
+
const REDACTION_PLACEHOLDER_RE = /<email>|<token>/g;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* F-S2c (PR-055 proposed): build a system-prompt SizedText from a FOUND raw
|
|
185
|
+
* source, distinguishing "present but fully redacted" from "genuinely absent".
|
|
186
|
+
*
|
|
187
|
+
* The caller only invokes this when a system-prompt SOURCE was located (a
|
|
188
|
+
* non-empty system-role message or <system> block). If sanitizing that source
|
|
189
|
+
* leaves NOTHING but redaction placeholders + whitespace (e.g. a credentials-only
|
|
190
|
+
* prompt: `sk-…`, an email, etc.), the prompt WAS present but carried no
|
|
191
|
+
* non-secret content — we mark `fullyRedacted: true` (text "", sizeBytes 0) so a
|
|
192
|
+
* consumer can say "system prompt present but fully redacted" rather than
|
|
193
|
+
* mistaking it for "no system prompt" (which is `undefined`).
|
|
194
|
+
*/
|
|
195
|
+
function buildSystemPromptSized(rawFound: string): SizedText {
|
|
196
|
+
const clean = sanitize(rawFound);
|
|
197
|
+
// Strip the placeholders sanitize() injected; if only whitespace remains, the
|
|
198
|
+
// source was entirely secrets → present-but-redacted.
|
|
199
|
+
const residue = clean.replace(REDACTION_PLACEHOLDER_RE, "").trim();
|
|
200
|
+
if (residue.length === 0) {
|
|
201
|
+
// Present-but-redacted: keep text empty + sizeBytes 0, flag it explicitly.
|
|
202
|
+
return { ...sized(""), fullyRedacted: true };
|
|
203
|
+
}
|
|
204
|
+
return sized(clean);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Pull a system prompt from a set of traces:
|
|
209
|
+
* 1. the first system-role message content, OR
|
|
210
|
+
* 2. a <system>…</system> block inside the first user/assistant message.
|
|
211
|
+
*
|
|
212
|
+
* Returns:
|
|
213
|
+
* - a sanitized SizedText when a prompt was found and survived sanitization,
|
|
214
|
+
* - a SizedText with `fullyRedacted: true` (text "", sizeBytes 0) when a prompt
|
|
215
|
+
* WAS found but sanitized to empty (F-S2c — distinguishes redacted from absent),
|
|
216
|
+
* - `undefined` ONLY when no system prompt was found at all.
|
|
217
|
+
*/
|
|
218
|
+
export function extractSystemPrompt(traces: TraceBody[]): SizedText | undefined {
|
|
219
|
+
for (const t of traces) {
|
|
220
|
+
const sys = t.messages.find((m) => m.role === "system" && m.content.trim());
|
|
221
|
+
if (sys) return buildSystemPromptSized(sys.content);
|
|
222
|
+
}
|
|
223
|
+
for (const t of traces) {
|
|
224
|
+
for (const m of t.messages) {
|
|
225
|
+
const match = SYSTEM_TAG_RE.exec(m.content);
|
|
226
|
+
if (match && match[1].trim()) return buildSystemPromptSized(match[1].trim());
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// ── W18-context: FULL untruncated system-prompt extraction (diagnosis-context) ─
|
|
233
|
+
|
|
234
|
+
/** Where a system prompt was located in the trace — provenance for grounding. */
|
|
235
|
+
export type SystemPromptOrigin =
|
|
236
|
+
/** Verbatim content of a `role:"system"` message. */
|
|
237
|
+
| "system-role-message"
|
|
238
|
+
/** Text inside a `<system>…</system>` block in a user/assistant message. */
|
|
239
|
+
| "system-tag-block";
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* W18-context: a FULL, untruncated system-prompt extraction WITH provenance.
|
|
243
|
+
*
|
|
244
|
+
* Distinct from `extractSystemPrompt` (the entity-CARD path), which returns a
|
|
245
|
+
* `SizedText` for a small UI card. This is the LENS path: the analyzer reads the
|
|
246
|
+
* full system prompt as grounding BEFORE searching for failure modes, so the
|
|
247
|
+
* client (no-codeAccess) case can supply the WHOLE prompt extracted from the
|
|
248
|
+
* traces — NOT a 220c card.
|
|
249
|
+
*
|
|
250
|
+
* Grounding contract (PR-026 / W18 operator principle): every field here is a
|
|
251
|
+
* directly-extracted FACT. `origin` records WHERE the text came from so the
|
|
252
|
+
* context can cite it. No truncation, no distillation, no seeded hypotheses.
|
|
253
|
+
*/
|
|
254
|
+
export interface FullSystemPrompt {
|
|
255
|
+
/** The PII-sanitized, FULL system-prompt text. Never truncated. */
|
|
256
|
+
text: string;
|
|
257
|
+
/** UTF-8 byte length of `text` (post-sanitization). */
|
|
258
|
+
sizeBytes: number;
|
|
259
|
+
/** Approximate token count (chars/4 heuristic — deterministic). */
|
|
260
|
+
tokensApprox: number;
|
|
261
|
+
/** Where the prompt was located — provenance for grounding. */
|
|
262
|
+
origin: SystemPromptOrigin;
|
|
263
|
+
/** Index of the trace (within the passed array) the prompt was found in. */
|
|
264
|
+
traceIndex: number;
|
|
265
|
+
/**
|
|
266
|
+
* True when a prompt SOURCE was found but sanitized down to nothing but
|
|
267
|
+
* redaction placeholders + whitespace (credentials-only prompt). Mirrors
|
|
268
|
+
* `SizedText.fullyRedacted` — present-but-redacted vs genuinely-absent.
|
|
269
|
+
*/
|
|
270
|
+
fullyRedacted: boolean;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* W18-context: extract the FULL system prompt (untruncated) + its provenance.
|
|
275
|
+
*
|
|
276
|
+
* Search order matches `extractSystemPrompt` for consistency:
|
|
277
|
+
* 1. the first `role:"system"` message whose content is non-empty, ELSE
|
|
278
|
+
* 2. the first `<system>…</system>` block in any user/assistant message.
|
|
279
|
+
*
|
|
280
|
+
* Returns `undefined` ONLY when no system-prompt source exists in any trace.
|
|
281
|
+
* When a source IS found but is entirely secrets, returns a record with
|
|
282
|
+
* `fullyRedacted:true` and empty `text` (distinguishes redacted from absent).
|
|
283
|
+
*
|
|
284
|
+
* Deterministic — pure function of the input traces (no clock/random/LLM).
|
|
285
|
+
*/
|
|
286
|
+
export function extractFullSystemPrompt(
|
|
287
|
+
traces: TraceBody[]
|
|
288
|
+
): FullSystemPrompt | undefined {
|
|
289
|
+
for (let i = 0; i < traces.length; i++) {
|
|
290
|
+
const sys = traces[i].messages.find(
|
|
291
|
+
(m) => m.role === "system" && m.content.trim()
|
|
292
|
+
);
|
|
293
|
+
if (sys) return buildFullSystemPrompt(sys.content, "system-role-message", i);
|
|
294
|
+
}
|
|
295
|
+
for (let i = 0; i < traces.length; i++) {
|
|
296
|
+
for (const m of traces[i].messages) {
|
|
297
|
+
const match = SYSTEM_TAG_RE.exec(m.content);
|
|
298
|
+
if (match && match[1].trim()) {
|
|
299
|
+
return buildFullSystemPrompt(match[1].trim(), "system-tag-block", i);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return undefined;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/** Build a FullSystemPrompt from a FOUND raw source (sanitize, never truncate). */
|
|
307
|
+
function buildFullSystemPrompt(
|
|
308
|
+
rawFound: string,
|
|
309
|
+
origin: SystemPromptOrigin,
|
|
310
|
+
traceIndex: number
|
|
311
|
+
): FullSystemPrompt {
|
|
312
|
+
const clean = sanitize(rawFound);
|
|
313
|
+
const residue = clean.replace(REDACTION_PLACEHOLDER_RE, "").trim();
|
|
314
|
+
if (residue.length === 0) {
|
|
315
|
+
return {
|
|
316
|
+
text: "",
|
|
317
|
+
sizeBytes: 0,
|
|
318
|
+
tokensApprox: 0,
|
|
319
|
+
origin,
|
|
320
|
+
traceIndex,
|
|
321
|
+
fullyRedacted: true,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
return {
|
|
325
|
+
text: clean,
|
|
326
|
+
sizeBytes: byteLength(clean),
|
|
327
|
+
tokensApprox: approxTokens(clean),
|
|
328
|
+
origin,
|
|
329
|
+
traceIndex,
|
|
330
|
+
fullyRedacted: false,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* W12-09 (P2): explicit label rendered when a system prompt is genuinely absent
|
|
336
|
+
* from the trace. The system prompt lives in the agent's config, not the trace
|
|
337
|
+
* input, so an absent value is EXPECTED — we surface that fact rather than a
|
|
338
|
+
* blank field. Carried as a `SizedText` so the renderer's `systemPromptCtx`
|
|
339
|
+
* branch renders it (forced-collapsed) like any other system-prompt value.
|
|
340
|
+
*/
|
|
341
|
+
export const SYSTEM_PROMPT_ABSENT_LABEL =
|
|
342
|
+
"system prompt not present in trace (lives in agent config)";
|
|
343
|
+
|
|
344
|
+
// ── majority-vote name ───────────────────────────────────────────────────────
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Majority-vote the entity name across traces (agentId, falling back to the
|
|
348
|
+
* platform). Ties broken by first-seen order for determinism.
|
|
349
|
+
*/
|
|
350
|
+
export function majorityName(traces: TraceBody[], fallback: string): string {
|
|
351
|
+
const counts = new Map<string, number>();
|
|
352
|
+
const order: string[] = [];
|
|
353
|
+
for (const t of traces) {
|
|
354
|
+
const n = t.metadata.agentId;
|
|
355
|
+
if (!n) continue;
|
|
356
|
+
if (!counts.has(n)) order.push(n);
|
|
357
|
+
counts.set(n, (counts.get(n) ?? 0) + 1);
|
|
358
|
+
}
|
|
359
|
+
if (order.length === 0) return fallback;
|
|
360
|
+
let best = order[0];
|
|
361
|
+
for (const n of order) {
|
|
362
|
+
if ((counts.get(n) ?? 0) > (counts.get(best) ?? 0)) best = n;
|
|
363
|
+
}
|
|
364
|
+
return best;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// ── tool inventory aggregation ───────────────────────────────────────────────
|
|
368
|
+
|
|
369
|
+
interface ToolAccumulator {
|
|
370
|
+
name: string;
|
|
371
|
+
calls: number;
|
|
372
|
+
latencies: number[];
|
|
373
|
+
signature?: string;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// ── W12-10: conservative tool-name canonicalization (alias dedup) ─────────────
|
|
377
|
+
|
|
378
|
+
/** Convert a snake_case identifier to camelCase. `send_message` → `sendMessage`. */
|
|
379
|
+
function snakeToCamel(name: string): string {
|
|
380
|
+
return name.replace(/_([a-z0-9])/g, (_, c: string) => c.toUpperCase());
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* W12-10 (P5/DC-2): CONSERVATIVELY canonicalize a tool name for dedup grouping.
|
|
385
|
+
* 1. Strip a single leading `tool.` prefix (`tool.send_message` → `send_message`).
|
|
386
|
+
* 2. Fold snake_case → camelCase so a snake/camel PAIR that are EXACTLY the
|
|
387
|
+
* same identifier merge (`send_message` + `sendMessage` → `sendMessage`),
|
|
388
|
+
* while two genuinely-different tools never collide.
|
|
389
|
+
*
|
|
390
|
+
* The returned value is the GROUPING KEY. Display-name selection is handled by
|
|
391
|
+
* the caller (prefers the camelCase form deterministically). Pure + deterministic.
|
|
392
|
+
*/
|
|
393
|
+
export function canonicalToolName(name: string): string {
|
|
394
|
+
const stripped = name.startsWith("tool.") ? name.slice("tool.".length) : name;
|
|
395
|
+
return snakeToCamel(stripped);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* F-S2b (PR-055 proposed): tool-inventory aggregation result WITH coverage stats.
|
|
400
|
+
* entries -- the aggregated per-tool inventory (as before).
|
|
401
|
+
* skippedCount -- tool/tool-result messages SKIPPED because they had no
|
|
402
|
+
* resolvable `toolName` (the inventory undercounts by this).
|
|
403
|
+
* toolsWithoutLatency -- distinct tools in `entries` with NO latency data
|
|
404
|
+
* (avg/p95 undefined) — lets the renderer caveat latency coverage.
|
|
405
|
+
*/
|
|
406
|
+
export interface ToolInventoryResult {
|
|
407
|
+
entries: ToolInventoryEntry[];
|
|
408
|
+
skippedCount: number;
|
|
409
|
+
toolsWithoutLatency: number;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* F-S2b (PR-055 proposed): aggregate tool usage across traces AND surface what
|
|
414
|
+
* the aggregation could not account for.
|
|
415
|
+
*
|
|
416
|
+
* Groups tool messages by the CANONICAL `toolName`, counts calls, and computes
|
|
417
|
+
* avg + p95 latency when per-message timing exists — identical to the prior
|
|
418
|
+
* `aggregateToolInventory` behaviour for the inventory itself. ADDITIONALLY:
|
|
419
|
+
* - counts messages that LOOK like tool activity but carry no resolvable
|
|
420
|
+
* `toolName` (previously silently `continue`-skipped), and
|
|
421
|
+
* - counts distinct aggregated tools that ended up with NO latency data,
|
|
422
|
+
* so the EntityContext can show "N messages skipped (no toolName)" and caveat
|
|
423
|
+
* latency coverage instead of silently undercounting.
|
|
424
|
+
*
|
|
425
|
+
* "Looks like tool activity" = a message whose role is `tool` OR which carries
|
|
426
|
+
* tool-shaped fields (`toolArgs` / `toolResult` / `isError`) but has an empty
|
|
427
|
+
* `toolName`. A plain user/assistant text turn is NOT counted as a skip — only
|
|
428
|
+
* messages that were genuinely tool-ish but un-attributable.
|
|
429
|
+
*
|
|
430
|
+
* Deterministic — sorted by callCount desc, then name asc.
|
|
431
|
+
*/
|
|
432
|
+
export function aggregateToolInventoryWithStats(
|
|
433
|
+
traces: TraceBody[]
|
|
434
|
+
): ToolInventoryResult {
|
|
435
|
+
const acc = new Map<string, ToolAccumulator>();
|
|
436
|
+
// W12-10: callsPerTrace denominator = the full population of traces passed in
|
|
437
|
+
// (NOT a sample) — the caller supplies the population it wants scoped, so the
|
|
438
|
+
// per-tool call-stats are population-scoped by construction.
|
|
439
|
+
const traceCount = traces.length || 1;
|
|
440
|
+
let skippedCount = 0;
|
|
441
|
+
|
|
442
|
+
for (const t of traces) {
|
|
443
|
+
// Pair tool_use timestamps with the following tool_result for latency.
|
|
444
|
+
const msgs = t.messages;
|
|
445
|
+
for (let i = 0; i < msgs.length; i++) {
|
|
446
|
+
const m = msgs[i];
|
|
447
|
+
if (!m.toolName) {
|
|
448
|
+
// F-S2b: a tool-ish message with no resolvable toolName is SKIPPED from the
|
|
449
|
+
// inventory (as before) but now COUNTED so the undercount is visible.
|
|
450
|
+
const looksToolish =
|
|
451
|
+
m.role === "tool" ||
|
|
452
|
+
m.toolArgs !== undefined ||
|
|
453
|
+
m.toolResult !== undefined ||
|
|
454
|
+
m.isError !== undefined;
|
|
455
|
+
if (looksToolish) skippedCount += 1;
|
|
456
|
+
continue;
|
|
457
|
+
}
|
|
458
|
+
// W12-10: group by the CANONICAL name so aliases (`tool.send_message`,
|
|
459
|
+
// `send_message`, `sendMessage`) collapse into ONE row with summed
|
|
460
|
+
// callCount — while two genuinely-different tools never merge.
|
|
461
|
+
const key = canonicalToolName(m.toolName);
|
|
462
|
+
let a = acc.get(key);
|
|
463
|
+
if (!a) {
|
|
464
|
+
// Display name = the canonical (camelCase, tool.-stripped) form, so the
|
|
465
|
+
// merged row has a single deterministic label regardless of which alias
|
|
466
|
+
// was seen first.
|
|
467
|
+
a = { name: key, calls: 0, latencies: [] };
|
|
468
|
+
acc.set(key, a);
|
|
469
|
+
}
|
|
470
|
+
a.calls += 1;
|
|
471
|
+
if (!a.signature && m.toolArgs) {
|
|
472
|
+
a.signature = m.toolArgs.slice(0, 120);
|
|
473
|
+
}
|
|
474
|
+
// Latency: this tool message timestamp → next message timestamp.
|
|
475
|
+
const next = msgs[i + 1];
|
|
476
|
+
if (m.timestamp && next?.timestamp) {
|
|
477
|
+
const dt = new Date(next.timestamp).getTime() - new Date(m.timestamp).getTime();
|
|
478
|
+
if (Number.isFinite(dt) && dt >= 0) a.latencies.push(dt);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
const entries: ToolInventoryEntry[] = [];
|
|
484
|
+
let toolsWithoutLatency = 0;
|
|
485
|
+
for (const a of acc.values()) {
|
|
486
|
+
const entry: ToolInventoryEntry = {
|
|
487
|
+
name: a.name,
|
|
488
|
+
callCount: a.calls,
|
|
489
|
+
callsPerTrace: Math.round((a.calls / traceCount) * 100) / 100,
|
|
490
|
+
};
|
|
491
|
+
if (a.latencies.length > 0) {
|
|
492
|
+
const sorted = a.latencies.slice().sort((x, y) => x - y);
|
|
493
|
+
const avg = sorted.reduce((s, v) => s + v, 0) / sorted.length;
|
|
494
|
+
entry.avgLatencyMs = Math.round(avg);
|
|
495
|
+
const rank = Math.max(0, Math.ceil(0.95 * sorted.length) - 1);
|
|
496
|
+
entry.p95LatencyMs = sorted[rank];
|
|
497
|
+
} else {
|
|
498
|
+
// F-S2b: this tool produced no usable latency sample → caveat-able.
|
|
499
|
+
toolsWithoutLatency += 1;
|
|
500
|
+
}
|
|
501
|
+
if (a.signature) entry.signature = a.signature;
|
|
502
|
+
entries.push(entry);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
entries.sort((x, y) => (y.callCount - x.callCount) || x.name.localeCompare(y.name));
|
|
506
|
+
return { entries, skippedCount, toolsWithoutLatency };
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Aggregate tool usage across traces. Groups tool messages by `toolName`,
|
|
511
|
+
* counts calls, and computes avg + p95 latency when per-message timing exists.
|
|
512
|
+
* Deterministic — sorted by callCount desc, then name asc.
|
|
513
|
+
*
|
|
514
|
+
* F-S2b: thin wrapper over `aggregateToolInventoryWithStats` that drops the
|
|
515
|
+
* coverage stats — preserves the original `ToolInventoryEntry[]` return for
|
|
516
|
+
* existing callers (e.g. the claude-code normalizer). Call
|
|
517
|
+
* `aggregateToolInventoryWithStats` to surface the skipped / no-latency counters.
|
|
518
|
+
*/
|
|
519
|
+
export function aggregateToolInventory(
|
|
520
|
+
traces: TraceBody[]
|
|
521
|
+
): ToolInventoryEntry[] {
|
|
522
|
+
return aggregateToolInventoryWithStats(traces).entries;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// ── input sample extraction ──────────────────────────────────────────────────
|
|
526
|
+
|
|
527
|
+
/** First user-role message content across traces, or the first message content. */
|
|
528
|
+
export function firstUserInput(traces: TraceBody[]): string | undefined {
|
|
529
|
+
for (const t of traces) {
|
|
530
|
+
const u = t.messages.find((m) => m.role === "user" && m.content.trim());
|
|
531
|
+
if (u) return u.content;
|
|
532
|
+
}
|
|
533
|
+
for (const t of traces) {
|
|
534
|
+
if (t.messages[0]?.content) return t.messages[0].content;
|
|
535
|
+
}
|
|
536
|
+
return undefined;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// ── generic agent EntityContext builder ──────────────────────────────────────
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Build an agent-typed EntityContext from a set of normalized traces + a model
|
|
543
|
+
* resolved by the caller (platform-specific). Shared by all source platforms.
|
|
544
|
+
*/
|
|
545
|
+
export function buildAgentEntityContext(
|
|
546
|
+
traces: TraceBody[],
|
|
547
|
+
opts: { source: string; fallbackName: string; model?: string }
|
|
548
|
+
): EntityContext {
|
|
549
|
+
const ctx: EntityContext = {
|
|
550
|
+
name: majorityName(traces, opts.fallbackName),
|
|
551
|
+
entityType: "agent",
|
|
552
|
+
codeAccess: false,
|
|
553
|
+
source: opts.source,
|
|
554
|
+
};
|
|
555
|
+
if (opts.model) ctx.model = opts.model;
|
|
556
|
+
|
|
557
|
+
// W12-09: render an explicit "absent" label instead of a blank field when the
|
|
558
|
+
// trace carries no system prompt (it lives in the agent config, not the trace).
|
|
559
|
+
const sys = extractSystemPrompt(traces);
|
|
560
|
+
ctx.systemPrompt = sys ?? sized(SYSTEM_PROMPT_ABSENT_LABEL);
|
|
561
|
+
|
|
562
|
+
// F-S2b: use the stats-bearing aggregator so the EntityContext can SURFACE
|
|
563
|
+
// messages skipped for lack of a toolName + tools with no latency coverage.
|
|
564
|
+
const toolStats = aggregateToolInventoryWithStats(traces);
|
|
565
|
+
if (toolStats.entries.length > 0) ctx.toolInventory = toolStats.entries;
|
|
566
|
+
if (toolStats.skippedCount > 0) ctx.skippedCount = toolStats.skippedCount;
|
|
567
|
+
if (toolStats.toolsWithoutLatency > 0)
|
|
568
|
+
ctx.toolsWithoutLatency = toolStats.toolsWithoutLatency;
|
|
569
|
+
|
|
570
|
+
const inp = firstUserInput(traces);
|
|
571
|
+
if (inp) ctx.inputSample = inputSample(inp);
|
|
572
|
+
|
|
573
|
+
return ctx;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
// ── PRD-SD-01: skill-typed self-entity context builder ───────────────────────
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* PRD-SD-01 (PR-022 / PR-025): Build a skill-typed EntityContext for self-diagnosis runs.
|
|
580
|
+
* The skill diagnoses ITSELF — entityType is 'skill', codeAccess is true (we have the
|
|
581
|
+
* source in the worktree), and applyTarget points at the skill source tree.
|
|
582
|
+
*
|
|
583
|
+
* Deterministic: all fields are derived from the provided metadata, no LLM, no clock.
|
|
584
|
+
* Called by self-diagnostics/dispatch.ts which passes it to the enricher via the
|
|
585
|
+
* descriptor so the enricher can inject it via --entity-context.
|
|
586
|
+
*
|
|
587
|
+
* Q12 (self-diag re-run cadence): on-demand only — this function is pure and
|
|
588
|
+
* stateless; the caller (dispatch.ts) gates behind self_diagnostics.enabled.
|
|
589
|
+
*/
|
|
590
|
+
export function buildSkillSelfEntityContext(opts: {
|
|
591
|
+
/** Skill name — defaults to 'mutagent-diagnostics'. */
|
|
592
|
+
skillName?: string;
|
|
593
|
+
/** Skill version from package.json — optional. */
|
|
594
|
+
version?: string;
|
|
595
|
+
/** Host runtime where the skill is executing (for provenance). */
|
|
596
|
+
source?: string;
|
|
597
|
+
/** Session-transcript-derived tool inventory (when available). */
|
|
598
|
+
toolInventory?: ToolInventoryEntry[];
|
|
599
|
+
/** Sanitized system-prompt sample derived from session transcript. */
|
|
600
|
+
systemPromptText?: string;
|
|
601
|
+
}): EntityContext {
|
|
602
|
+
const name = opts.skillName ?? "mutagent-diagnostics";
|
|
603
|
+
const source = opts.source ?? "claude-code-self-diag";
|
|
604
|
+
|
|
605
|
+
const ctx: EntityContext = {
|
|
606
|
+
name,
|
|
607
|
+
entityType: "skill",
|
|
608
|
+
codeAccess: true,
|
|
609
|
+
source,
|
|
610
|
+
/**
|
|
611
|
+
* PRD-SD-01: applyTarget for skill-typed subjects explicitly states that
|
|
612
|
+
* in REPORT-ONLY runs the skill source is READ-ONLY (no source modification).
|
|
613
|
+
* Apply-workers may modify skill assets (config.yaml, .claude/skills/) but
|
|
614
|
+
* NEVER the source scripts. This mirrors the self-diag security note in
|
|
615
|
+
* references/internal/self-diagnostics.md.
|
|
616
|
+
*/
|
|
617
|
+
applyTarget:
|
|
618
|
+
"~/.claude/skills/mutagent-diagnostics/* (skill source — READ-ONLY in report-only runs)",
|
|
619
|
+
};
|
|
620
|
+
|
|
621
|
+
if (opts.version) {
|
|
622
|
+
// Encode version in the name for disambiguation across deploys.
|
|
623
|
+
ctx.name = `${name}@${opts.version}`;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
if (opts.systemPromptText) {
|
|
627
|
+
ctx.systemPrompt = sized(sanitize(opts.systemPromptText));
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
if (opts.toolInventory && opts.toolInventory.length > 0) {
|
|
631
|
+
ctx.toolInventory = opts.toolInventory;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
return ctx;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
// ── W11-07: Agent identity resolution ────────────────────────────────────────
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* W11-07: Look up a named entity in the config's agents[] identity map and
|
|
641
|
+
* return its cross-platform identity pointers, or undefined when not declared.
|
|
642
|
+
*
|
|
643
|
+
* Deterministic + pure: only performs a case-insensitive name lookup.
|
|
644
|
+
* Called at Step 3.7 AFTER the normalizer has produced its EntityContext,
|
|
645
|
+
* to annotate the context with identity pointers from config.
|
|
646
|
+
*
|
|
647
|
+
* @param entityName - The code-level entity name (from parse-brief.entity or
|
|
648
|
+
* EntityContext.name). Compared case-insensitively.
|
|
649
|
+
* @param agents - The config.agents[] array (from DiagnosticsConfig).
|
|
650
|
+
* Pass undefined or empty array when absent (no-op).
|
|
651
|
+
* @returns EntityIdentityPointers for the matched agent, or undefined.
|
|
652
|
+
*/
|
|
653
|
+
export function resolveEntityIdentity(
|
|
654
|
+
entityName: string | undefined,
|
|
655
|
+
agents: AgentIdentity[] | undefined
|
|
656
|
+
): EntityIdentityPointers | undefined {
|
|
657
|
+
if (!entityName || !agents || agents.length === 0) return undefined;
|
|
658
|
+
|
|
659
|
+
const lower = entityName.toLowerCase();
|
|
660
|
+
const match = agents.find((a) => a.name.toLowerCase() === lower);
|
|
661
|
+
if (!match) return undefined;
|
|
662
|
+
|
|
663
|
+
const pointers: EntityIdentityPointers = {};
|
|
664
|
+
|
|
665
|
+
if (match.langfuse) {
|
|
666
|
+
pointers.langfuse = {};
|
|
667
|
+
if (match.langfuse.traceName !== undefined)
|
|
668
|
+
pointers.langfuse.traceName = match.langfuse.traceName;
|
|
669
|
+
if (match.langfuse.tags !== undefined)
|
|
670
|
+
pointers.langfuse.tags = match.langfuse.tags;
|
|
671
|
+
if (match.langfuse.agentIdField !== undefined)
|
|
672
|
+
pointers.langfuse.agentIdField = match.langfuse.agentIdField;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
if (match.otel) {
|
|
676
|
+
pointers.otel = {};
|
|
677
|
+
if (match.otel.serviceName !== undefined)
|
|
678
|
+
pointers.otel.serviceName = match.otel.serviceName;
|
|
679
|
+
if (match.otel.resourceAttrs !== undefined)
|
|
680
|
+
pointers.otel.resourceAttrs = match.otel.resourceAttrs;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
// Only return if at least one platform has data.
|
|
684
|
+
if (!pointers.langfuse && !pointers.otel) return undefined;
|
|
685
|
+
return pointers;
|
|
686
|
+
}
|