oh-my-knowledge 0.31.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -842
- package/README.zh.md +43 -854
- package/dist/analysis/coverage-analyzer.d.ts.map +1 -0
- package/dist/analysis/coverage-analyzer.js.map +1 -0
- package/dist/analysis/failure-clusterer.d.ts.map +1 -0
- package/dist/analysis/failure-clusterer.js.map +1 -0
- package/dist/analysis/gap-analyzer.d.ts +121 -0
- package/dist/analysis/gap-analyzer.d.ts.map +1 -0
- package/dist/analysis/gap-analyzer.js +471 -0
- package/dist/analysis/gap-analyzer.js.map +1 -0
- package/dist/analysis/hedging-classifier.d.ts.map +1 -0
- package/dist/analysis/hedging-classifier.js.map +1 -0
- package/dist/analysis/report-diagnostics.d.ts +34 -0
- package/dist/analysis/report-diagnostics.d.ts.map +1 -0
- package/dist/analysis/report-diagnostics.js +753 -0
- package/dist/analysis/report-diagnostics.js.map +1 -0
- package/dist/analysis/sample-diagnostics.d.ts.map +1 -0
- package/dist/analysis/sample-diagnostics.js.map +1 -0
- package/dist/analysis/saturation.d.ts.map +1 -0
- package/dist/analysis/saturation.js.map +1 -0
- package/dist/authoring/evolver.d.ts.map +1 -0
- package/dist/authoring/evolver.js.map +1 -0
- package/dist/authoring/generator.d.ts.map +1 -0
- package/dist/authoring/generator.js +720 -0
- package/dist/authoring/generator.js.map +1 -0
- package/dist/authoring/sample-fixer.d.ts.map +1 -0
- package/dist/authoring/sample-fixer.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +26 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +302 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/eval/gold/compare.d.ts.map +1 -0
- package/dist/cli/commands/eval/gold/compare.js.map +1 -0
- package/dist/cli/commands/eval/gold/index.d.ts.map +1 -0
- package/dist/cli/commands/eval/gold/index.js.map +1 -0
- package/dist/cli/commands/eval/gold/init.d.ts.map +1 -0
- package/dist/cli/commands/eval/gold/init.js.map +1 -0
- package/dist/cli/commands/eval/gold/validate.d.ts.map +1 -0
- package/dist/cli/commands/eval/gold/validate.js.map +1 -0
- package/dist/cli/commands/eval/index.d.ts.map +1 -0
- package/dist/cli/commands/eval/index.js +465 -0
- package/dist/cli/commands/eval/index.js.map +1 -0
- package/dist/cli/commands/evolve.d.ts.map +1 -0
- package/dist/cli/commands/evolve.js +283 -0
- package/dist/cli/commands/evolve.js.map +1 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/observe/inbox.d.ts.map +1 -0
- package/dist/cli/commands/observe/inbox.js +260 -0
- package/dist/cli/commands/observe/inbox.js.map +1 -0
- package/dist/cli/commands/observe/index.d.ts.map +1 -0
- package/dist/cli/commands/observe/index.js.map +1 -0
- package/dist/cli/commands/observe/ingest.d.ts.map +1 -0
- package/dist/cli/commands/observe/ingest.js +71 -0
- package/dist/cli/commands/observe/ingest.js.map +1 -0
- package/dist/cli/commands/observe/show.d.ts.map +1 -0
- package/dist/cli/commands/observe/show.js.map +1 -0
- package/dist/cli/commands/sample.d.ts.map +1 -0
- package/dist/cli/commands/sample.js +487 -0
- package/dist/cli/commands/sample.js.map +1 -0
- package/dist/cli/commands/studio.d.ts.map +1 -0
- package/dist/cli/commands/studio.js +158 -0
- package/dist/cli/commands/studio.js.map +1 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/lib/cli-exit.d.ts.map +1 -0
- package/dist/cli/lib/cli-exit.js.map +1 -0
- package/dist/cli/lib/cmd-flags.d.ts +224 -0
- package/dist/cli/lib/cmd-flags.d.ts.map +1 -0
- package/dist/cli/lib/cmd-flags.js.map +1 -0
- package/dist/cli/lib/i18n-dict/common.d.ts +4 -0
- package/dist/cli/lib/i18n-dict/common.d.ts.map +1 -0
- package/dist/cli/lib/i18n-dict/common.js +67 -0
- package/dist/cli/lib/i18n-dict/common.js.map +1 -0
- package/dist/cli/lib/i18n-dict/evolve.d.ts +4 -0
- package/dist/cli/lib/i18n-dict/evolve.d.ts.map +1 -0
- package/dist/cli/lib/i18n-dict/evolve.js +43 -0
- package/dist/cli/lib/i18n-dict/evolve.js.map +1 -0
- package/dist/cli/lib/i18n-dict/gen.d.ts +4 -0
- package/dist/cli/lib/i18n-dict/gen.d.ts.map +1 -0
- package/dist/cli/lib/i18n-dict/gen.js +63 -0
- package/dist/cli/lib/i18n-dict/gen.js.map +1 -0
- package/dist/cli/lib/i18n-dict/help.d.ts +4 -0
- package/dist/cli/lib/i18n-dict/help.d.ts.map +1 -0
- package/dist/cli/lib/i18n-dict/help.js +281 -0
- package/dist/cli/lib/i18n-dict/help.js.map +1 -0
- package/dist/cli/lib/i18n-dict/init.d.ts +4 -0
- package/dist/cli/lib/i18n-dict/init.d.ts.map +1 -0
- package/dist/cli/lib/i18n-dict/init.js +27 -0
- package/dist/cli/lib/i18n-dict/init.js.map +1 -0
- package/dist/cli/lib/i18n-dict/run.d.ts +4 -0
- package/dist/cli/lib/i18n-dict/run.d.ts.map +1 -0
- package/dist/cli/lib/i18n-dict/run.js +143 -0
- package/dist/cli/lib/i18n-dict/run.js.map +1 -0
- package/dist/cli/lib/i18n-dict/types.d.ts +5 -0
- package/dist/cli/lib/i18n-dict/types.d.ts.map +1 -0
- package/dist/cli/lib/i18n-dict/types.js +2 -0
- package/dist/cli/lib/i18n-dict/types.js.map +1 -0
- package/dist/cli/lib/i18n-dict.d.ts +63 -0
- package/dist/cli/lib/i18n-dict.d.ts.map +1 -0
- package/dist/cli/lib/i18n-dict.js +67 -0
- package/dist/cli/lib/i18n-dict.js.map +1 -0
- package/dist/cli/lib/i18n.d.ts.map +1 -0
- package/dist/cli/lib/i18n.js.map +1 -0
- package/dist/cli/lib/parse-run-config/judge-models.d.ts +24 -0
- package/dist/cli/lib/parse-run-config/judge-models.d.ts.map +1 -0
- package/dist/cli/lib/parse-run-config/judge-models.js +55 -0
- package/dist/cli/lib/parse-run-config/judge-models.js.map +1 -0
- package/dist/cli/lib/parse-run-config/samples-discovery.d.ts +19 -0
- package/dist/cli/lib/parse-run-config/samples-discovery.d.ts.map +1 -0
- package/dist/cli/lib/parse-run-config/samples-discovery.js +53 -0
- package/dist/cli/lib/parse-run-config/samples-discovery.js.map +1 -0
- package/dist/cli/lib/parse-run-config/variant-resolution.d.ts +18 -0
- package/dist/cli/lib/parse-run-config/variant-resolution.d.ts.map +1 -0
- package/dist/cli/lib/parse-run-config/variant-resolution.js +59 -0
- package/dist/cli/lib/parse-run-config/variant-resolution.js.map +1 -0
- package/dist/cli/lib/parse-run-config.d.ts +93 -0
- package/dist/cli/lib/parse-run-config.d.ts.map +1 -0
- package/dist/cli/lib/parse-run-config.js +157 -0
- package/dist/cli/lib/parse-run-config.js.map +1 -0
- package/dist/cli/lib/progress.d.ts.map +1 -0
- package/dist/cli/lib/progress.js.map +1 -0
- package/dist/cli/lib/resolve-skill-input.d.ts +8 -0
- package/dist/cli/lib/resolve-skill-input.d.ts.map +1 -0
- package/dist/cli/lib/resolve-skill-input.js +38 -0
- package/dist/cli/lib/resolve-skill-input.js.map +1 -0
- package/dist/cli/lib/run-tally.d.ts.map +1 -0
- package/dist/cli/lib/run-tally.js.map +1 -0
- package/dist/cli/lib/shared.d.ts.map +1 -0
- package/dist/cli/lib/shared.js.map +1 -0
- package/dist/cli/lib/update-check.d.ts +9 -0
- package/dist/cli/lib/update-check.d.ts.map +1 -0
- package/dist/cli/lib/update-check.js +113 -0
- package/dist/cli/lib/update-check.js.map +1 -0
- package/dist/cli/oclif/base-command.d.ts.map +1 -0
- package/dist/cli/oclif/base-command.js.map +1 -0
- package/dist/cli/oclif/help.d.ts.map +1 -0
- package/dist/cli/oclif/help.js.map +1 -0
- package/dist/cli/oclif/i18n.d.ts.map +1 -0
- package/dist/cli/oclif/i18n.js.map +1 -0
- package/dist/cli/oclif/parsers.d.ts.map +1 -0
- package/dist/cli/oclif/parsers.js.map +1 -0
- package/dist/cli/oclif/projection.d.ts.map +1 -0
- package/dist/cli/oclif/projection.js.map +1 -0
- package/dist/cli/oclif/run.d.ts.map +1 -0
- package/dist/cli/oclif/run.js +11 -0
- package/dist/cli/oclif/run.js.map +1 -0
- package/dist/diagnosis/observe-mapper.d.ts.map +1 -0
- package/dist/diagnosis/observe-mapper.js.map +1 -0
- package/dist/diagnosis/observe-producer.d.ts.map +1 -0
- package/dist/diagnosis/observe-producer.js +199 -0
- package/dist/diagnosis/observe-producer.js.map +1 -0
- package/dist/diagnosis/studio-projection.d.ts +7 -0
- package/dist/diagnosis/studio-projection.d.ts.map +1 -0
- package/dist/diagnosis/studio-projection.js.map +1 -0
- package/dist/diagnosis/types.d.ts +4 -0
- package/dist/diagnosis/types.d.ts.map +1 -0
- package/dist/diagnosis/types.js +20 -0
- package/dist/diagnosis/types.js.map +1 -0
- package/dist/doctor/fixer.d.ts.map +1 -0
- package/dist/doctor/fixer.js.map +1 -0
- package/dist/doctor/health/builtin-dimensions.d.ts.map +1 -0
- package/dist/doctor/health/builtin-dimensions.js.map +1 -0
- package/dist/doctor/health/composer.d.ts.map +1 -0
- package/dist/doctor/health/composer.js +296 -0
- package/dist/doctor/health/composer.js.map +1 -0
- package/dist/doctor/health/dimension-registry.d.ts.map +1 -0
- package/dist/doctor/health/dimension-registry.js.map +1 -0
- package/dist/doctor/health/dimension-spec.d.ts +47 -0
- package/dist/doctor/health/dimension-spec.d.ts.map +1 -0
- package/dist/doctor/health/dimension-spec.js.map +1 -0
- package/dist/doctor/health/parser.d.ts.map +1 -0
- package/dist/doctor/health/parser.js.map +1 -0
- package/dist/doctor/health/prompt-builder.d.ts.map +1 -0
- package/dist/doctor/health/prompt-builder.js.map +1 -0
- package/dist/doctor/health/register.d.ts.map +1 -0
- package/dist/doctor/health/register.js.map +1 -0
- package/dist/doctor/index.d.ts.map +1 -0
- package/dist/doctor/index.js.map +1 -0
- package/dist/doctor/messages.d.ts +21 -0
- package/dist/doctor/messages.d.ts.map +1 -0
- package/dist/doctor/messages.js +217 -0
- package/dist/doctor/messages.js.map +1 -0
- package/dist/doctor/preflight.d.ts.map +1 -0
- package/dist/doctor/preflight.js.map +1 -0
- package/dist/doctor/renderer.d.ts +17 -0
- package/dist/doctor/renderer.d.ts.map +1 -0
- package/dist/doctor/renderer.js +122 -0
- package/dist/doctor/renderer.js.map +1 -0
- package/dist/doctor/rules.d.ts.map +1 -0
- package/dist/doctor/rules.js +289 -0
- package/dist/doctor/rules.js.map +1 -0
- package/dist/eval-core/bootstrap.d.ts.map +1 -0
- package/dist/eval-core/bootstrap.js.map +1 -0
- package/dist/eval-core/cache.d.ts.map +1 -0
- package/dist/eval-core/cache.js.map +1 -0
- package/dist/eval-core/comparability.d.ts.map +1 -0
- package/dist/eval-core/comparability.js.map +1 -0
- package/dist/eval-core/dependency-checker.d.ts +37 -0
- package/dist/eval-core/dependency-checker.d.ts.map +1 -0
- package/dist/eval-core/dependency-checker.js.map +1 -0
- package/dist/eval-core/evaluation-execution.d.ts.map +1 -0
- package/dist/eval-core/evaluation-execution.js.map +1 -0
- package/dist/eval-core/evaluation-job.d.ts.map +1 -0
- package/dist/eval-core/evaluation-job.js.map +1 -0
- package/dist/eval-core/evaluation-reporting.d.ts.map +1 -0
- package/dist/eval-core/evaluation-reporting.js.map +1 -0
- package/dist/eval-core/execution-strategy.d.ts.map +1 -0
- package/dist/eval-core/execution-strategy.js +165 -0
- package/dist/eval-core/execution-strategy.js.map +1 -0
- package/dist/eval-core/fact-checker.d.ts.map +1 -0
- package/dist/eval-core/fact-checker.js.map +1 -0
- package/dist/eval-core/layer-gates.d.ts.map +1 -0
- package/dist/eval-core/layer-gates.js.map +1 -0
- package/dist/eval-core/mocks-runtime.d.ts.map +1 -0
- package/dist/eval-core/mocks-runtime.js +559 -0
- package/dist/eval-core/mocks-runtime.js.map +1 -0
- package/dist/eval-core/schema.d.ts.map +1 -0
- package/dist/eval-core/schema.js.map +1 -0
- package/dist/eval-core/statistics.d.ts.map +1 -0
- package/dist/eval-core/statistics.js.map +1 -0
- package/dist/eval-core/task-planner.d.ts.map +1 -0
- package/dist/eval-core/task-planner.js.map +1 -0
- package/dist/eval-core/verdict.d.ts.map +1 -0
- package/dist/eval-core/verdict.js.map +1 -0
- package/dist/eval-workflows/batch-evaluation-workflow.d.ts.map +1 -0
- package/dist/eval-workflows/batch-evaluation-workflow.js.map +1 -0
- package/dist/eval-workflows/evaluation-pipeline/preflight-warnings.d.ts +22 -0
- package/dist/eval-workflows/evaluation-pipeline/preflight-warnings.d.ts.map +1 -0
- package/dist/eval-workflows/evaluation-pipeline/preflight-warnings.js +67 -0
- package/dist/eval-workflows/evaluation-pipeline/preflight-warnings.js.map +1 -0
- package/dist/eval-workflows/evaluation-pipeline/report-finalize.d.ts +32 -0
- package/dist/eval-workflows/evaluation-pipeline/report-finalize.d.ts.map +1 -0
- package/dist/eval-workflows/evaluation-pipeline/report-finalize.js +57 -0
- package/dist/eval-workflows/evaluation-pipeline/report-finalize.js.map +1 -0
- package/dist/eval-workflows/evaluation-pipeline/run-state.d.ts +60 -0
- package/dist/eval-workflows/evaluation-pipeline/run-state.d.ts.map +1 -0
- package/dist/eval-workflows/evaluation-pipeline/run-state.js +88 -0
- package/dist/eval-workflows/evaluation-pipeline/run-state.js.map +1 -0
- package/dist/eval-workflows/evaluation-pipeline/test-set-hash.d.ts +21 -0
- package/dist/eval-workflows/evaluation-pipeline/test-set-hash.d.ts.map +1 -0
- package/dist/eval-workflows/evaluation-pipeline/test-set-hash.js +46 -0
- package/dist/eval-workflows/evaluation-pipeline/test-set-hash.js.map +1 -0
- package/dist/eval-workflows/evaluation-pipeline.d.ts +97 -0
- package/dist/eval-workflows/evaluation-pipeline.d.ts.map +1 -0
- package/dist/eval-workflows/evaluation-pipeline.js +179 -0
- package/dist/eval-workflows/evaluation-pipeline.js.map +1 -0
- package/dist/eval-workflows/evaluation-preparation.d.ts.map +1 -0
- package/dist/eval-workflows/evaluation-preparation.js.map +1 -0
- package/dist/eval-workflows/messages.d.ts +4 -0
- package/dist/eval-workflows/messages.d.ts.map +1 -0
- package/dist/eval-workflows/messages.js +30 -0
- package/dist/eval-workflows/messages.js.map +1 -0
- package/dist/eval-workflows/run-evaluation.d.ts.map +1 -0
- package/dist/eval-workflows/run-evaluation.js +528 -0
- package/dist/eval-workflows/run-evaluation.js.map +1 -0
- package/dist/executors/anthropic-api.d.ts.map +1 -0
- package/dist/executors/anthropic-api.js.map +1 -0
- package/dist/executors/claude-cli.d.ts.map +1 -0
- package/dist/executors/claude-cli.js.map +1 -0
- package/dist/executors/claude-sdk-trace.d.ts.map +1 -0
- package/dist/executors/claude-sdk-trace.js.map +1 -0
- package/dist/executors/claude-sdk.d.ts.map +1 -0
- package/dist/executors/claude-sdk.js.map +1 -0
- package/dist/executors/codex-cli-trace.d.ts.map +1 -0
- package/dist/executors/codex-cli-trace.js.map +1 -0
- package/dist/executors/codex-cli.d.ts.map +1 -0
- package/dist/executors/codex-cli.js.map +1 -0
- package/dist/executors/codex-sdk.d.ts.map +1 -0
- package/dist/executors/codex-sdk.js.map +1 -0
- package/dist/executors/gemini.d.ts.map +1 -0
- package/dist/executors/gemini.js.map +1 -0
- package/dist/executors/index.d.ts.map +1 -0
- package/dist/executors/index.js.map +1 -0
- package/dist/executors/openai-api.d.ts.map +1 -0
- package/dist/executors/openai-api.js.map +1 -0
- package/dist/executors/runtime-fingerprint.d.ts.map +1 -0
- package/dist/executors/runtime-fingerprint.js.map +1 -0
- package/dist/executors/script.d.ts.map +1 -0
- package/dist/executors/script.js.map +1 -0
- package/dist/executors/shared.d.ts +194 -0
- package/dist/executors/shared.d.ts.map +1 -0
- package/dist/executors/shared.js +253 -0
- package/dist/executors/shared.js.map +1 -0
- package/dist/grading/assertions.d.ts.map +1 -0
- package/dist/grading/assertions.js.map +1 -0
- package/dist/grading/debias-validate.d.ts.map +1 -0
- package/dist/grading/debias-validate.js.map +1 -0
- package/dist/grading/diagnostic.d.ts.map +1 -0
- package/dist/grading/diagnostic.js.map +1 -0
- package/dist/grading/gold-cli.d.ts.map +1 -0
- package/dist/grading/gold-cli.js.map +1 -0
- package/dist/grading/gold-dataset.d.ts.map +1 -0
- package/dist/grading/gold-dataset.js.map +1 -0
- package/dist/grading/human-gold.d.ts.map +1 -0
- package/dist/grading/human-gold.js.map +1 -0
- package/dist/grading/index.d.ts.map +1 -0
- package/dist/grading/index.js.map +1 -0
- package/dist/grading/judge.d.ts.map +1 -0
- package/dist/grading/judge.js.map +1 -0
- package/dist/grading/layered-scores.d.ts.map +1 -0
- package/dist/grading/layered-scores.js.map +1 -0
- package/dist/inputs/eval-config.d.ts.map +1 -0
- package/dist/inputs/eval-config.js.map +1 -0
- package/dist/inputs/load-samples.d.ts.map +1 -0
- package/dist/inputs/load-samples.js.map +1 -0
- package/dist/inputs/mcp-resolver.d.ts.map +1 -0
- package/dist/inputs/mcp-resolver.js.map +1 -0
- package/dist/inputs/skill-loader.d.ts.map +1 -0
- package/dist/inputs/skill-loader.js +261 -0
- package/dist/inputs/skill-loader.js.map +1 -0
- package/dist/inputs/url-fetcher.d.ts.map +1 -0
- package/dist/inputs/url-fetcher.js.map +1 -0
- package/dist/observability/experience-frontmatter.d.ts +37 -0
- package/dist/observability/experience-frontmatter.d.ts.map +1 -0
- package/dist/observability/experience-frontmatter.js +100 -0
- package/dist/observability/experience-frontmatter.js.map +1 -0
- package/dist/observability/experience.d.ts +23 -0
- package/dist/observability/experience.d.ts.map +1 -0
- package/dist/observability/experience.js +3438 -0
- package/dist/observability/experience.js.map +1 -0
- package/dist/observability/feedback-matchers.d.ts +37 -0
- package/dist/observability/feedback-matchers.d.ts.map +1 -0
- package/dist/observability/feedback-matchers.js +232 -0
- package/dist/observability/feedback-matchers.js.map +1 -0
- package/dist/observability/feedback-projection.d.ts +21 -0
- package/dist/observability/feedback-projection.d.ts.map +1 -0
- package/dist/observability/feedback-projection.js +20 -0
- package/dist/observability/feedback-projection.js.map +1 -0
- package/dist/observability/inbox-view-model.d.ts +43 -0
- package/dist/observability/inbox-view-model.d.ts.map +1 -0
- package/dist/observability/inbox-view-model.js +180 -0
- package/dist/observability/inbox-view-model.js.map +1 -0
- package/dist/observability/inbox.d.ts +28 -0
- package/dist/observability/inbox.d.ts.map +1 -0
- package/dist/observability/inbox.js +765 -0
- package/dist/observability/inbox.js.map +1 -0
- package/dist/observability/problem-patterns.d.ts +12 -0
- package/dist/observability/problem-patterns.d.ts.map +1 -0
- package/dist/observability/problem-patterns.js +244 -0
- package/dist/observability/problem-patterns.js.map +1 -0
- package/dist/observability/prompts/llm-enhanced-review.prompt.md +224 -0
- package/dist/observability/resolved-review.d.ts +37 -0
- package/dist/observability/resolved-review.d.ts.map +1 -0
- package/dist/observability/resolved-review.js +552 -0
- package/dist/observability/resolved-review.js.map +1 -0
- package/dist/observability/review-state.d.ts +20 -0
- package/dist/observability/review-state.d.ts.map +1 -0
- package/dist/observability/review-state.js.map +1 -0
- package/dist/observability/skill-chain-advisories.d.ts +16 -0
- package/dist/observability/skill-chain-advisories.d.ts.map +1 -0
- package/dist/observability/skill-chain-advisories.js.map +1 -0
- package/dist/observability/skill-chain.d.ts +7 -0
- package/dist/observability/skill-chain.d.ts.map +1 -0
- package/dist/observability/skill-chain.js +474 -0
- package/dist/observability/skill-chain.js.map +1 -0
- package/dist/observability/skill-health-analyzer.d.ts.map +1 -0
- package/dist/observability/skill-health-analyzer.js.map +1 -0
- package/dist/observability/soft-standards/constants.d.ts +5 -0
- package/dist/observability/soft-standards/constants.d.ts.map +1 -0
- package/dist/observability/soft-standards/constants.js +10 -0
- package/dist/observability/soft-standards/constants.js.map +1 -0
- package/dist/observability/soft-standards/index.d.ts +16 -0
- package/dist/observability/soft-standards/index.d.ts.map +1 -0
- package/dist/observability/soft-standards/index.js +15 -0
- package/dist/observability/soft-standards/index.js.map +1 -0
- package/dist/observability/soft-standards/llm-extractor.d.ts +6 -0
- package/dist/observability/soft-standards/llm-extractor.d.ts.map +1 -0
- package/dist/observability/soft-standards/llm-extractor.js +692 -0
- package/dist/observability/soft-standards/llm-extractor.js.map +1 -0
- package/dist/observability/soft-standards/runtime-evaluator.d.ts +12 -0
- package/dist/observability/soft-standards/runtime-evaluator.d.ts.map +1 -0
- package/dist/observability/soft-standards/runtime-evaluator.js +385 -0
- package/dist/observability/soft-standards/runtime-evaluator.js.map +1 -0
- package/dist/observability/soft-standards/skill-standards-store.d.ts +11 -0
- package/dist/observability/soft-standards/skill-standards-store.d.ts.map +1 -0
- package/dist/observability/soft-standards/skill-standards-store.js +158 -0
- package/dist/observability/soft-standards/skill-standards-store.js.map +1 -0
- package/dist/observability/soft-standards/types.d.ts +212 -0
- package/dist/observability/soft-standards/types.d.ts.map +1 -0
- package/dist/observability/soft-standards/types.js +2 -0
- package/dist/observability/soft-standards/types.js.map +1 -0
- package/dist/observability/text-signals.d.ts +14 -0
- package/dist/observability/text-signals.d.ts.map +1 -0
- package/dist/observability/text-signals.js +116 -0
- package/dist/observability/text-signals.js.map +1 -0
- package/dist/observability/trace-adapter.d.ts.map +1 -0
- package/dist/observability/trace-adapter.js.map +1 -0
- package/dist/observability/trace-attribution.d.ts +56 -0
- package/dist/observability/trace-attribution.d.ts.map +1 -0
- package/dist/observability/trace-attribution.js +200 -0
- package/dist/observability/trace-attribution.js.map +1 -0
- package/dist/observability/trace-segmenter.d.ts +52 -0
- package/dist/observability/trace-segmenter.d.ts.map +1 -0
- package/dist/observability/trace-segmenter.js +322 -0
- package/dist/observability/trace-segmenter.js.map +1 -0
- package/dist/observability/trace-source.d.ts +92 -0
- package/dist/observability/trace-source.d.ts.map +1 -0
- package/dist/observability/trace-source.js +502 -0
- package/dist/observability/trace-source.js.map +1 -0
- package/dist/renderer/html-renderer.d.ts.map +1 -0
- package/dist/renderer/html-renderer.js.map +1 -0
- package/dist/renderer/layout.d.ts.map +1 -0
- package/dist/renderer/layout.js.map +1 -0
- package/dist/renderer/observation-inbox/helpers.d.ts +14 -0
- package/dist/renderer/observation-inbox/helpers.d.ts.map +1 -0
- package/dist/renderer/observation-inbox/helpers.js +75 -0
- package/dist/renderer/observation-inbox/helpers.js.map +1 -0
- package/dist/renderer/observation-inbox/styles.d.ts +2 -0
- package/dist/renderer/observation-inbox/styles.d.ts.map +1 -0
- package/dist/renderer/observation-inbox/styles.js +5184 -0
- package/dist/renderer/observation-inbox/styles.js.map +1 -0
- package/dist/renderer/observation-inbox-renderer.d.ts +5 -0
- package/dist/renderer/observation-inbox-renderer.d.ts.map +1 -0
- package/dist/renderer/observation-inbox-renderer.js +7182 -0
- package/dist/renderer/observation-inbox-renderer.js.map +1 -0
- package/dist/renderer/skill-detail-renderer.d.ts +13 -0
- package/dist/renderer/skill-detail-renderer.d.ts.map +1 -0
- package/dist/renderer/skill-detail-renderer.js.map +1 -0
- package/dist/renderer/skill-health-renderer.d.ts.map +1 -0
- package/dist/renderer/skill-health-renderer.js.map +1 -0
- package/dist/renderer/skill-list-renderer.d.ts +3 -0
- package/dist/renderer/skill-list-renderer.d.ts.map +1 -0
- package/dist/renderer/skill-list-renderer.js.map +1 -0
- package/dist/renderer/summary.d.ts +68 -0
- package/dist/renderer/summary.d.ts.map +1 -0
- package/dist/renderer/summary.js +1896 -0
- package/dist/renderer/summary.js.map +1 -0
- package/dist/renderer/table.d.ts.map +1 -0
- package/dist/renderer/table.js.map +1 -0
- package/dist/renderer/test-view.d.ts.map +1 -0
- package/dist/renderer/test-view.js.map +1 -0
- package/dist/renderer/trends.d.ts.map +1 -0
- package/dist/renderer/trends.js.map +1 -0
- package/dist/server/job-store.d.ts.map +1 -0
- package/dist/server/job-store.js.map +1 -0
- package/dist/server/report-server.d.ts.map +1 -0
- package/dist/server/report-server.js +892 -0
- package/dist/server/report-server.js.map +1 -0
- package/dist/server/report-store.d.ts.map +1 -0
- package/dist/server/report-store.js.map +1 -0
- package/dist/server/skill-index.d.ts +14 -0
- package/dist/server/skill-index.d.ts.map +1 -0
- package/dist/server/skill-index.js +381 -0
- package/dist/server/skill-index.js.map +1 -0
- package/dist/server/skill-insights.d.ts +32 -0
- package/dist/server/skill-insights.d.ts.map +1 -0
- package/dist/server/skill-insights.js.map +1 -0
- package/dist/shared/hard-rules.d.ts.map +1 -0
- package/dist/shared/hard-rules.js.map +1 -0
- package/dist/shared/llm-prompts/index.d.ts +14 -0
- package/dist/shared/llm-prompts/index.d.ts.map +1 -0
- package/dist/shared/llm-prompts/index.js +22 -0
- package/dist/shared/llm-prompts/index.js.map +1 -0
- package/dist/shared/llm-prompts/skill-health.d.ts.map +1 -0
- package/dist/shared/llm-prompts/skill-health.js.map +1 -0
- package/dist/shared/time.d.ts.map +1 -0
- package/dist/shared/time.js.map +1 -0
- package/dist/shared/tool-search.d.ts.map +1 -0
- package/dist/shared/tool-search.js.map +1 -0
- package/dist/types/dependencies.d.ts +23 -0
- package/dist/types/dependencies.d.ts.map +1 -0
- package/dist/types/dependencies.js +2 -0
- package/dist/types/dependencies.js.map +1 -0
- package/dist/types/diagnosis.d.ts +88 -0
- package/dist/types/diagnosis.d.ts.map +1 -0
- package/dist/types/diagnosis.js +2 -0
- package/dist/types/diagnosis.js.map +1 -0
- package/dist/types/doctor.d.ts +157 -0
- package/dist/types/doctor.d.ts.map +1 -0
- package/dist/types/doctor.js.map +1 -0
- package/dist/types/eval.d.ts +377 -0
- package/dist/types/eval.d.ts.map +1 -0
- package/dist/types/eval.js.map +1 -0
- package/dist/types/executor.d.ts.map +1 -0
- package/dist/types/executor.js.map +1 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +12 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/judge.d.ts.map +1 -0
- package/dist/types/judge.js.map +1 -0
- package/dist/types/observability.d.ts +865 -0
- package/dist/types/observability.d.ts.map +1 -0
- package/dist/types/observability.js +14 -0
- package/dist/types/observability.js.map +1 -0
- package/dist/types/report.d.ts +560 -0
- package/dist/types/report.d.ts.map +1 -0
- package/dist/types/report.js.map +1 -0
- package/dist/types/shared.d.ts.map +1 -0
- package/dist/types/shared.js.map +1 -0
- package/dist/types/skill-index.d.ts +142 -0
- package/dist/types/skill-index.d.ts.map +1 -0
- package/dist/types/skill-index.js +2 -0
- package/dist/types/skill-index.js.map +1 -0
- package/dist/types/storage.d.ts.map +1 -0
- package/dist/types/storage.js.map +1 -0
- package/dist/util/safe-slice.d.ts +23 -0
- package/dist/util/safe-slice.d.ts.map +1 -0
- package/dist/util/safe-slice.js +33 -0
- package/dist/util/safe-slice.js.map +1 -0
- package/package.json +20 -13
- package/dist/src/analysis/coverage-analyzer.d.ts.map +0 -1
- package/dist/src/analysis/coverage-analyzer.js.map +0 -1
- package/dist/src/analysis/failure-clusterer.d.ts.map +0 -1
- package/dist/src/analysis/failure-clusterer.js.map +0 -1
- package/dist/src/analysis/gap-analyzer.d.ts +0 -121
- package/dist/src/analysis/gap-analyzer.d.ts.map +0 -1
- package/dist/src/analysis/gap-analyzer.js +0 -471
- package/dist/src/analysis/gap-analyzer.js.map +0 -1
- package/dist/src/analysis/hedging-classifier.d.ts.map +0 -1
- package/dist/src/analysis/hedging-classifier.js.map +0 -1
- package/dist/src/analysis/report-diagnostics.d.ts +0 -34
- package/dist/src/analysis/report-diagnostics.d.ts.map +0 -1
- package/dist/src/analysis/report-diagnostics.js +0 -753
- package/dist/src/analysis/report-diagnostics.js.map +0 -1
- package/dist/src/analysis/sample-diagnostics.d.ts.map +0 -1
- package/dist/src/analysis/sample-diagnostics.js.map +0 -1
- package/dist/src/analysis/saturation.d.ts.map +0 -1
- package/dist/src/analysis/saturation.js.map +0 -1
- package/dist/src/authoring/evolver.d.ts.map +0 -1
- package/dist/src/authoring/evolver.js.map +0 -1
- package/dist/src/authoring/generator.d.ts.map +0 -1
- package/dist/src/authoring/generator.js +0 -720
- package/dist/src/authoring/generator.js.map +0 -1
- package/dist/src/authoring/sample-fixer.d.ts.map +0 -1
- package/dist/src/authoring/sample-fixer.js.map +0 -1
- package/dist/src/cli/commands/doctor.d.ts +0 -26
- package/dist/src/cli/commands/doctor.d.ts.map +0 -1
- package/dist/src/cli/commands/doctor.js +0 -283
- package/dist/src/cli/commands/doctor.js.map +0 -1
- package/dist/src/cli/commands/eval/gold/compare.d.ts.map +0 -1
- package/dist/src/cli/commands/eval/gold/compare.js.map +0 -1
- package/dist/src/cli/commands/eval/gold/index.d.ts.map +0 -1
- package/dist/src/cli/commands/eval/gold/index.js.map +0 -1
- package/dist/src/cli/commands/eval/gold/init.d.ts.map +0 -1
- package/dist/src/cli/commands/eval/gold/init.js.map +0 -1
- package/dist/src/cli/commands/eval/gold/validate.d.ts.map +0 -1
- package/dist/src/cli/commands/eval/gold/validate.js.map +0 -1
- package/dist/src/cli/commands/eval/index.d.ts.map +0 -1
- package/dist/src/cli/commands/eval/index.js +0 -465
- package/dist/src/cli/commands/eval/index.js.map +0 -1
- package/dist/src/cli/commands/evolve.d.ts.map +0 -1
- package/dist/src/cli/commands/evolve.js +0 -276
- package/dist/src/cli/commands/evolve.js.map +0 -1
- package/dist/src/cli/commands/init.d.ts.map +0 -1
- package/dist/src/cli/commands/init.js.map +0 -1
- package/dist/src/cli/commands/observe/inbox.d.ts.map +0 -1
- package/dist/src/cli/commands/observe/inbox.js +0 -258
- package/dist/src/cli/commands/observe/inbox.js.map +0 -1
- package/dist/src/cli/commands/observe/index.d.ts.map +0 -1
- package/dist/src/cli/commands/observe/index.js.map +0 -1
- package/dist/src/cli/commands/observe/ingest.d.ts.map +0 -1
- package/dist/src/cli/commands/observe/ingest.js +0 -69
- package/dist/src/cli/commands/observe/ingest.js.map +0 -1
- package/dist/src/cli/commands/observe/show.d.ts.map +0 -1
- package/dist/src/cli/commands/observe/show.js.map +0 -1
- package/dist/src/cli/commands/sample.d.ts.map +0 -1
- package/dist/src/cli/commands/sample.js +0 -488
- package/dist/src/cli/commands/sample.js.map +0 -1
- package/dist/src/cli/commands/skill-extract.d.ts +0 -20
- package/dist/src/cli/commands/skill-extract.d.ts.map +0 -1
- package/dist/src/cli/commands/skill-extract.js +0 -84
- package/dist/src/cli/commands/skill-extract.js.map +0 -1
- package/dist/src/cli/commands/studio.d.ts.map +0 -1
- package/dist/src/cli/commands/studio.js +0 -158
- package/dist/src/cli/commands/studio.js.map +0 -1
- package/dist/src/cli/index.d.ts.map +0 -1
- package/dist/src/cli/index.js.map +0 -1
- package/dist/src/cli/lib/cli-exit.d.ts.map +0 -1
- package/dist/src/cli/lib/cli-exit.js.map +0 -1
- package/dist/src/cli/lib/cmd-flags.d.ts +0 -236
- package/dist/src/cli/lib/cmd-flags.d.ts.map +0 -1
- package/dist/src/cli/lib/cmd-flags.js.map +0 -1
- package/dist/src/cli/lib/i18n-dict.d.ts +0 -54
- package/dist/src/cli/lib/i18n-dict.d.ts.map +0 -1
- package/dist/src/cli/lib/i18n-dict.js +0 -900
- package/dist/src/cli/lib/i18n-dict.js.map +0 -1
- package/dist/src/cli/lib/i18n.d.ts.map +0 -1
- package/dist/src/cli/lib/i18n.js.map +0 -1
- package/dist/src/cli/lib/parse-run-config.d.ts +0 -89
- package/dist/src/cli/lib/parse-run-config.d.ts.map +0 -1
- package/dist/src/cli/lib/parse-run-config.js +0 -252
- package/dist/src/cli/lib/parse-run-config.js.map +0 -1
- package/dist/src/cli/lib/progress.d.ts.map +0 -1
- package/dist/src/cli/lib/progress.js.map +0 -1
- package/dist/src/cli/lib/run-tally.d.ts.map +0 -1
- package/dist/src/cli/lib/run-tally.js.map +0 -1
- package/dist/src/cli/lib/shared.d.ts.map +0 -1
- package/dist/src/cli/lib/shared.js.map +0 -1
- package/dist/src/cli/lib/update-check.d.ts +0 -3
- package/dist/src/cli/lib/update-check.d.ts.map +0 -1
- package/dist/src/cli/lib/update-check.js +0 -37
- package/dist/src/cli/lib/update-check.js.map +0 -1
- package/dist/src/cli/oclif/base-command.d.ts.map +0 -1
- package/dist/src/cli/oclif/base-command.js.map +0 -1
- package/dist/src/cli/oclif/help.d.ts.map +0 -1
- package/dist/src/cli/oclif/help.js.map +0 -1
- package/dist/src/cli/oclif/i18n.d.ts.map +0 -1
- package/dist/src/cli/oclif/i18n.js.map +0 -1
- package/dist/src/cli/oclif/parsers.d.ts.map +0 -1
- package/dist/src/cli/oclif/parsers.js.map +0 -1
- package/dist/src/cli/oclif/projection.d.ts.map +0 -1
- package/dist/src/cli/oclif/projection.js.map +0 -1
- package/dist/src/cli/oclif/run.d.ts.map +0 -1
- package/dist/src/cli/oclif/run.js +0 -11
- package/dist/src/cli/oclif/run.js.map +0 -1
- package/dist/src/diagnosis/observe-mapper.d.ts.map +0 -1
- package/dist/src/diagnosis/observe-mapper.js.map +0 -1
- package/dist/src/diagnosis/observe-producer.d.ts.map +0 -1
- package/dist/src/diagnosis/observe-producer.js +0 -197
- package/dist/src/diagnosis/observe-producer.js.map +0 -1
- package/dist/src/diagnosis/studio-projection.d.ts +0 -14
- package/dist/src/diagnosis/studio-projection.d.ts.map +0 -1
- package/dist/src/diagnosis/studio-projection.js.map +0 -1
- package/dist/src/diagnosis/types.d.ts +0 -79
- package/dist/src/diagnosis/types.d.ts.map +0 -1
- package/dist/src/diagnosis/types.js +0 -20
- package/dist/src/diagnosis/types.js.map +0 -1
- package/dist/src/doctor/fixer.d.ts.map +0 -1
- package/dist/src/doctor/fixer.js.map +0 -1
- package/dist/src/doctor/health/builtin-dimensions.d.ts.map +0 -1
- package/dist/src/doctor/health/builtin-dimensions.js.map +0 -1
- package/dist/src/doctor/health/composer.d.ts.map +0 -1
- package/dist/src/doctor/health/composer.js +0 -296
- package/dist/src/doctor/health/composer.js.map +0 -1
- package/dist/src/doctor/health/dimension-registry.d.ts.map +0 -1
- package/dist/src/doctor/health/dimension-registry.js.map +0 -1
- package/dist/src/doctor/health/dimension-spec.d.ts +0 -47
- package/dist/src/doctor/health/dimension-spec.d.ts.map +0 -1
- package/dist/src/doctor/health/dimension-spec.js.map +0 -1
- package/dist/src/doctor/health/parser.d.ts.map +0 -1
- package/dist/src/doctor/health/parser.js.map +0 -1
- package/dist/src/doctor/health/prompt-builder.d.ts.map +0 -1
- package/dist/src/doctor/health/prompt-builder.js.map +0 -1
- package/dist/src/doctor/health/register.d.ts.map +0 -1
- package/dist/src/doctor/health/register.js.map +0 -1
- package/dist/src/doctor/html-renderer.d.ts +0 -20
- package/dist/src/doctor/html-renderer.d.ts.map +0 -1
- package/dist/src/doctor/html-renderer.js +0 -376
- package/dist/src/doctor/html-renderer.js.map +0 -1
- package/dist/src/doctor/index.d.ts.map +0 -1
- package/dist/src/doctor/index.js.map +0 -1
- package/dist/src/doctor/preflight.d.ts.map +0 -1
- package/dist/src/doctor/preflight.js.map +0 -1
- package/dist/src/doctor/renderer.d.ts +0 -17
- package/dist/src/doctor/renderer.d.ts.map +0 -1
- package/dist/src/doctor/renderer.js +0 -123
- package/dist/src/doctor/renderer.js.map +0 -1
- package/dist/src/doctor/rules.d.ts.map +0 -1
- package/dist/src/doctor/rules.js +0 -289
- package/dist/src/doctor/rules.js.map +0 -1
- package/dist/src/eval-core/bootstrap.d.ts.map +0 -1
- package/dist/src/eval-core/bootstrap.js.map +0 -1
- package/dist/src/eval-core/cache.d.ts.map +0 -1
- package/dist/src/eval-core/cache.js.map +0 -1
- package/dist/src/eval-core/comparability.d.ts.map +0 -1
- package/dist/src/eval-core/comparability.js.map +0 -1
- package/dist/src/eval-core/dependency-checker.d.ts +0 -58
- package/dist/src/eval-core/dependency-checker.d.ts.map +0 -1
- package/dist/src/eval-core/dependency-checker.js.map +0 -1
- package/dist/src/eval-core/evaluation-execution.d.ts.map +0 -1
- package/dist/src/eval-core/evaluation-execution.js.map +0 -1
- package/dist/src/eval-core/evaluation-job.d.ts.map +0 -1
- package/dist/src/eval-core/evaluation-job.js.map +0 -1
- package/dist/src/eval-core/evaluation-reporting.d.ts.map +0 -1
- package/dist/src/eval-core/evaluation-reporting.js.map +0 -1
- package/dist/src/eval-core/execution-strategy.d.ts.map +0 -1
- package/dist/src/eval-core/execution-strategy.js +0 -165
- package/dist/src/eval-core/execution-strategy.js.map +0 -1
- package/dist/src/eval-core/fact-checker.d.ts.map +0 -1
- package/dist/src/eval-core/fact-checker.js.map +0 -1
- package/dist/src/eval-core/layer-gates.d.ts.map +0 -1
- package/dist/src/eval-core/layer-gates.js.map +0 -1
- package/dist/src/eval-core/mocks-runtime.d.ts.map +0 -1
- package/dist/src/eval-core/mocks-runtime.js +0 -559
- package/dist/src/eval-core/mocks-runtime.js.map +0 -1
- package/dist/src/eval-core/schema.d.ts.map +0 -1
- package/dist/src/eval-core/schema.js.map +0 -1
- package/dist/src/eval-core/statistics.d.ts.map +0 -1
- package/dist/src/eval-core/statistics.js.map +0 -1
- package/dist/src/eval-core/task-planner.d.ts.map +0 -1
- package/dist/src/eval-core/task-planner.js.map +0 -1
- package/dist/src/eval-core/verdict.d.ts.map +0 -1
- package/dist/src/eval-core/verdict.js.map +0 -1
- package/dist/src/eval-workflows/batch-evaluation-workflow.d.ts.map +0 -1
- package/dist/src/eval-workflows/batch-evaluation-workflow.js.map +0 -1
- package/dist/src/eval-workflows/evaluation-pipeline.d.ts +0 -109
- package/dist/src/eval-workflows/evaluation-pipeline.d.ts.map +0 -1
- package/dist/src/eval-workflows/evaluation-pipeline.js +0 -373
- package/dist/src/eval-workflows/evaluation-pipeline.js.map +0 -1
- package/dist/src/eval-workflows/evaluation-preparation.d.ts.map +0 -1
- package/dist/src/eval-workflows/evaluation-preparation.js.map +0 -1
- package/dist/src/eval-workflows/run-evaluation.d.ts.map +0 -1
- package/dist/src/eval-workflows/run-evaluation.js +0 -528
- package/dist/src/eval-workflows/run-evaluation.js.map +0 -1
- package/dist/src/executors/anthropic-api.d.ts.map +0 -1
- package/dist/src/executors/anthropic-api.js.map +0 -1
- package/dist/src/executors/claude-cli.d.ts.map +0 -1
- package/dist/src/executors/claude-cli.js.map +0 -1
- package/dist/src/executors/claude-sdk-trace.d.ts.map +0 -1
- package/dist/src/executors/claude-sdk-trace.js.map +0 -1
- package/dist/src/executors/claude-sdk.d.ts.map +0 -1
- package/dist/src/executors/claude-sdk.js.map +0 -1
- package/dist/src/executors/codex-cli-trace.d.ts.map +0 -1
- package/dist/src/executors/codex-cli-trace.js.map +0 -1
- package/dist/src/executors/codex-cli.d.ts.map +0 -1
- package/dist/src/executors/codex-cli.js.map +0 -1
- package/dist/src/executors/codex-sdk.d.ts.map +0 -1
- package/dist/src/executors/codex-sdk.js.map +0 -1
- package/dist/src/executors/gemini.d.ts.map +0 -1
- package/dist/src/executors/gemini.js.map +0 -1
- package/dist/src/executors/index.d.ts.map +0 -1
- package/dist/src/executors/index.js.map +0 -1
- package/dist/src/executors/openai-api.d.ts.map +0 -1
- package/dist/src/executors/openai-api.js.map +0 -1
- package/dist/src/executors/runtime-fingerprint.d.ts.map +0 -1
- package/dist/src/executors/runtime-fingerprint.js.map +0 -1
- package/dist/src/executors/script.d.ts.map +0 -1
- package/dist/src/executors/script.js.map +0 -1
- package/dist/src/executors/shared.d.ts +0 -194
- package/dist/src/executors/shared.d.ts.map +0 -1
- package/dist/src/executors/shared.js +0 -256
- package/dist/src/executors/shared.js.map +0 -1
- package/dist/src/grading/assertions.d.ts.map +0 -1
- package/dist/src/grading/assertions.js.map +0 -1
- package/dist/src/grading/debias-validate.d.ts.map +0 -1
- package/dist/src/grading/debias-validate.js.map +0 -1
- package/dist/src/grading/diagnostic.d.ts.map +0 -1
- package/dist/src/grading/diagnostic.js.map +0 -1
- package/dist/src/grading/gold-cli.d.ts.map +0 -1
- package/dist/src/grading/gold-cli.js.map +0 -1
- package/dist/src/grading/gold-dataset.d.ts.map +0 -1
- package/dist/src/grading/gold-dataset.js.map +0 -1
- package/dist/src/grading/human-gold.d.ts.map +0 -1
- package/dist/src/grading/human-gold.js.map +0 -1
- package/dist/src/grading/index.d.ts.map +0 -1
- package/dist/src/grading/index.js.map +0 -1
- package/dist/src/grading/judge.d.ts.map +0 -1
- package/dist/src/grading/judge.js.map +0 -1
- package/dist/src/grading/layered-scores.d.ts.map +0 -1
- package/dist/src/grading/layered-scores.js.map +0 -1
- package/dist/src/inputs/eval-config.d.ts.map +0 -1
- package/dist/src/inputs/eval-config.js.map +0 -1
- package/dist/src/inputs/load-samples.d.ts.map +0 -1
- package/dist/src/inputs/load-samples.js.map +0 -1
- package/dist/src/inputs/mcp-resolver.d.ts.map +0 -1
- package/dist/src/inputs/mcp-resolver.js.map +0 -1
- package/dist/src/inputs/skill-loader.d.ts.map +0 -1
- package/dist/src/inputs/skill-loader.js +0 -253
- package/dist/src/inputs/skill-loader.js.map +0 -1
- package/dist/src/inputs/url-fetcher.d.ts.map +0 -1
- package/dist/src/inputs/url-fetcher.js.map +0 -1
- package/dist/src/observability/experience.d.ts +0 -441
- package/dist/src/observability/experience.d.ts.map +0 -1
- package/dist/src/observability/experience.js +0 -2400
- package/dist/src/observability/experience.js.map +0 -1
- package/dist/src/observability/inbox-view-model.d.ts +0 -30
- package/dist/src/observability/inbox-view-model.d.ts.map +0 -1
- package/dist/src/observability/inbox-view-model.js +0 -144
- package/dist/src/observability/inbox-view-model.js.map +0 -1
- package/dist/src/observability/inbox.d.ts +0 -127
- package/dist/src/observability/inbox.d.ts.map +0 -1
- package/dist/src/observability/inbox.js +0 -755
- package/dist/src/observability/inbox.js.map +0 -1
- package/dist/src/observability/problem-patterns.d.ts +0 -52
- package/dist/src/observability/problem-patterns.d.ts.map +0 -1
- package/dist/src/observability/problem-patterns.js +0 -205
- package/dist/src/observability/problem-patterns.js.map +0 -1
- package/dist/src/observability/resolved-review.d.ts +0 -25
- package/dist/src/observability/resolved-review.d.ts.map +0 -1
- package/dist/src/observability/resolved-review.js +0 -231
- package/dist/src/observability/resolved-review.js.map +0 -1
- package/dist/src/observability/review-state.d.ts +0 -61
- package/dist/src/observability/review-state.d.ts.map +0 -1
- package/dist/src/observability/review-state.js.map +0 -1
- package/dist/src/observability/skill-chain-advisories.d.ts +0 -25
- package/dist/src/observability/skill-chain-advisories.d.ts.map +0 -1
- package/dist/src/observability/skill-chain-advisories.js.map +0 -1
- package/dist/src/observability/skill-chain.d.ts +0 -62
- package/dist/src/observability/skill-chain.d.ts.map +0 -1
- package/dist/src/observability/skill-chain.js +0 -270
- package/dist/src/observability/skill-chain.js.map +0 -1
- package/dist/src/observability/skill-health-analyzer.d.ts.map +0 -1
- package/dist/src/observability/skill-health-analyzer.js.map +0 -1
- package/dist/src/observability/soft-standards.d.ts +0 -130
- package/dist/src/observability/soft-standards.d.ts.map +0 -1
- package/dist/src/observability/soft-standards.js +0 -426
- package/dist/src/observability/soft-standards.js.map +0 -1
- package/dist/src/observability/text-signals.d.ts +0 -14
- package/dist/src/observability/text-signals.d.ts.map +0 -1
- package/dist/src/observability/text-signals.js +0 -106
- package/dist/src/observability/text-signals.js.map +0 -1
- package/dist/src/observability/trace-adapter.d.ts.map +0 -1
- package/dist/src/observability/trace-adapter.js.map +0 -1
- package/dist/src/observability/trace-attribution.d.ts +0 -56
- package/dist/src/observability/trace-attribution.d.ts.map +0 -1
- package/dist/src/observability/trace-attribution.js +0 -200
- package/dist/src/observability/trace-attribution.js.map +0 -1
- package/dist/src/observability/trace-segmenter.d.ts +0 -52
- package/dist/src/observability/trace-segmenter.d.ts.map +0 -1
- package/dist/src/observability/trace-segmenter.js +0 -322
- package/dist/src/observability/trace-segmenter.js.map +0 -1
- package/dist/src/observability/trace-source.d.ts +0 -99
- package/dist/src/observability/trace-source.d.ts.map +0 -1
- package/dist/src/observability/trace-source.js +0 -502
- package/dist/src/observability/trace-source.js.map +0 -1
- package/dist/src/renderer/html-renderer.d.ts.map +0 -1
- package/dist/src/renderer/html-renderer.js.map +0 -1
- package/dist/src/renderer/layout.d.ts.map +0 -1
- package/dist/src/renderer/layout.js.map +0 -1
- package/dist/src/renderer/observation-inbox-renderer.d.ts +0 -4
- package/dist/src/renderer/observation-inbox-renderer.d.ts.map +0 -1
- package/dist/src/renderer/observation-inbox-renderer.js +0 -10366
- package/dist/src/renderer/observation-inbox-renderer.js.map +0 -1
- package/dist/src/renderer/skill-detail-renderer.d.ts +0 -15
- package/dist/src/renderer/skill-detail-renderer.d.ts.map +0 -1
- package/dist/src/renderer/skill-detail-renderer.js.map +0 -1
- package/dist/src/renderer/skill-health-renderer.d.ts.map +0 -1
- package/dist/src/renderer/skill-health-renderer.js.map +0 -1
- package/dist/src/renderer/skill-list-renderer.d.ts +0 -4
- package/dist/src/renderer/skill-list-renderer.d.ts.map +0 -1
- package/dist/src/renderer/skill-list-renderer.js.map +0 -1
- package/dist/src/renderer/summary.d.ts +0 -68
- package/dist/src/renderer/summary.d.ts.map +0 -1
- package/dist/src/renderer/summary.js +0 -1896
- package/dist/src/renderer/summary.js.map +0 -1
- package/dist/src/renderer/table.d.ts.map +0 -1
- package/dist/src/renderer/table.js.map +0 -1
- package/dist/src/renderer/test-view.d.ts.map +0 -1
- package/dist/src/renderer/test-view.js.map +0 -1
- package/dist/src/renderer/trends.d.ts.map +0 -1
- package/dist/src/renderer/trends.js.map +0 -1
- package/dist/src/server/job-store.d.ts.map +0 -1
- package/dist/src/server/job-store.js.map +0 -1
- package/dist/src/server/report-server.d.ts.map +0 -1
- package/dist/src/server/report-server.js +0 -894
- package/dist/src/server/report-server.js.map +0 -1
- package/dist/src/server/report-store.d.ts.map +0 -1
- package/dist/src/server/report-store.js.map +0 -1
- package/dist/src/server/skill-index.d.ts +0 -81
- package/dist/src/server/skill-index.d.ts.map +0 -1
- package/dist/src/server/skill-index.js +0 -377
- package/dist/src/server/skill-index.js.map +0 -1
- package/dist/src/server/skill-insights.d.ts +0 -101
- package/dist/src/server/skill-insights.d.ts.map +0 -1
- package/dist/src/server/skill-insights.js.map +0 -1
- package/dist/src/shared/hard-rules.d.ts.map +0 -1
- package/dist/src/shared/hard-rules.js.map +0 -1
- package/dist/src/shared/llm-prompts/index.d.ts +0 -14
- package/dist/src/shared/llm-prompts/index.d.ts.map +0 -1
- package/dist/src/shared/llm-prompts/index.js +0 -35
- package/dist/src/shared/llm-prompts/index.js.map +0 -1
- package/dist/src/shared/llm-prompts/skill-health.d.ts.map +0 -1
- package/dist/src/shared/llm-prompts/skill-health.js.map +0 -1
- package/dist/src/shared/time.d.ts.map +0 -1
- package/dist/src/shared/time.js.map +0 -1
- package/dist/src/shared/tool-search.d.ts.map +0 -1
- package/dist/src/shared/tool-search.js.map +0 -1
- package/dist/src/types/doctor.d.ts +0 -157
- package/dist/src/types/doctor.d.ts.map +0 -1
- package/dist/src/types/doctor.js.map +0 -1
- package/dist/src/types/eval.d.ts +0 -377
- package/dist/src/types/eval.d.ts.map +0 -1
- package/dist/src/types/eval.js.map +0 -1
- package/dist/src/types/executor.d.ts.map +0 -1
- package/dist/src/types/executor.js.map +0 -1
- package/dist/src/types/index.d.ts +0 -8
- package/dist/src/types/index.d.ts.map +0 -1
- package/dist/src/types/index.js +0 -8
- package/dist/src/types/index.js.map +0 -1
- package/dist/src/types/judge.d.ts.map +0 -1
- package/dist/src/types/judge.js.map +0 -1
- package/dist/src/types/report.d.ts +0 -557
- package/dist/src/types/report.d.ts.map +0 -1
- package/dist/src/types/report.js.map +0 -1
- package/dist/src/types/shared.d.ts.map +0 -1
- package/dist/src/types/shared.js.map +0 -1
- package/dist/src/types/storage.d.ts.map +0 -1
- package/dist/src/types/storage.js.map +0 -1
- package/dist/src/util/safe-slice.d.ts +0 -23
- package/dist/src/util/safe-slice.d.ts.map +0 -1
- package/dist/src/util/safe-slice.js +0 -33
- package/dist/src/util/safe-slice.js.map +0 -1
- package/docs/prompts/llm-enhanced-review.prompt.md +0 -111
- /package/dist/{src/analysis → analysis}/coverage-analyzer.d.ts +0 -0
- /package/dist/{src/analysis → analysis}/coverage-analyzer.js +0 -0
- /package/dist/{src/analysis → analysis}/failure-clusterer.d.ts +0 -0
- /package/dist/{src/analysis → analysis}/failure-clusterer.js +0 -0
- /package/dist/{src/analysis → analysis}/hedging-classifier.d.ts +0 -0
- /package/dist/{src/analysis → analysis}/hedging-classifier.js +0 -0
- /package/dist/{src/analysis → analysis}/sample-diagnostics.d.ts +0 -0
- /package/dist/{src/analysis → analysis}/sample-diagnostics.js +0 -0
- /package/dist/{src/analysis → analysis}/saturation.d.ts +0 -0
- /package/dist/{src/analysis → analysis}/saturation.js +0 -0
- /package/dist/{src/authoring → authoring}/evolver.d.ts +0 -0
- /package/dist/{src/authoring → authoring}/evolver.js +0 -0
- /package/dist/{src/authoring → authoring}/generator.d.ts +0 -0
- /package/dist/{src/authoring → authoring}/sample-fixer.d.ts +0 -0
- /package/dist/{src/authoring → authoring}/sample-fixer.js +0 -0
- /package/dist/{src/cli → cli}/commands/eval/gold/compare.d.ts +0 -0
- /package/dist/{src/cli → cli}/commands/eval/gold/compare.js +0 -0
- /package/dist/{src/cli → cli}/commands/eval/gold/index.d.ts +0 -0
- /package/dist/{src/cli → cli}/commands/eval/gold/index.js +0 -0
- /package/dist/{src/cli → cli}/commands/eval/gold/init.d.ts +0 -0
- /package/dist/{src/cli → cli}/commands/eval/gold/init.js +0 -0
- /package/dist/{src/cli → cli}/commands/eval/gold/validate.d.ts +0 -0
- /package/dist/{src/cli → cli}/commands/eval/gold/validate.js +0 -0
- /package/dist/{src/cli → cli}/commands/eval/index.d.ts +0 -0
- /package/dist/{src/cli → cli}/commands/evolve.d.ts +0 -0
- /package/dist/{src/cli → cli}/commands/init.d.ts +0 -0
- /package/dist/{src/cli → cli}/commands/init.js +0 -0
- /package/dist/{src/cli → cli}/commands/observe/inbox.d.ts +0 -0
- /package/dist/{src/cli → cli}/commands/observe/index.d.ts +0 -0
- /package/dist/{src/cli → cli}/commands/observe/index.js +0 -0
- /package/dist/{src/cli → cli}/commands/observe/ingest.d.ts +0 -0
- /package/dist/{src/cli → cli}/commands/observe/show.d.ts +0 -0
- /package/dist/{src/cli → cli}/commands/observe/show.js +0 -0
- /package/dist/{src/cli → cli}/commands/sample.d.ts +0 -0
- /package/dist/{src/cli → cli}/commands/studio.d.ts +0 -0
- /package/dist/{src/cli → cli}/index.d.ts +0 -0
- /package/dist/{src/cli → cli}/index.js +0 -0
- /package/dist/{src/cli → cli}/lib/cli-exit.d.ts +0 -0
- /package/dist/{src/cli → cli}/lib/cli-exit.js +0 -0
- /package/dist/{src/cli → cli}/lib/cmd-flags.js +0 -0
- /package/dist/{src/cli → cli}/lib/i18n.d.ts +0 -0
- /package/dist/{src/cli → cli}/lib/i18n.js +0 -0
- /package/dist/{src/cli → cli}/lib/progress.d.ts +0 -0
- /package/dist/{src/cli → cli}/lib/progress.js +0 -0
- /package/dist/{src/cli → cli}/lib/run-tally.d.ts +0 -0
- /package/dist/{src/cli → cli}/lib/run-tally.js +0 -0
- /package/dist/{src/cli → cli}/lib/shared.d.ts +0 -0
- /package/dist/{src/cli → cli}/lib/shared.js +0 -0
- /package/dist/{src/cli → cli}/oclif/base-command.d.ts +0 -0
- /package/dist/{src/cli → cli}/oclif/base-command.js +0 -0
- /package/dist/{src/cli → cli}/oclif/help.d.ts +0 -0
- /package/dist/{src/cli → cli}/oclif/help.js +0 -0
- /package/dist/{src/cli → cli}/oclif/i18n.d.ts +0 -0
- /package/dist/{src/cli → cli}/oclif/i18n.js +0 -0
- /package/dist/{src/cli → cli}/oclif/parsers.d.ts +0 -0
- /package/dist/{src/cli → cli}/oclif/parsers.js +0 -0
- /package/dist/{src/cli → cli}/oclif/projection.d.ts +0 -0
- /package/dist/{src/cli → cli}/oclif/projection.js +0 -0
- /package/dist/{src/cli → cli}/oclif/run.d.ts +0 -0
- /package/dist/{src/diagnosis → diagnosis}/observe-mapper.d.ts +0 -0
- /package/dist/{src/diagnosis → diagnosis}/observe-mapper.js +0 -0
- /package/dist/{src/diagnosis → diagnosis}/observe-producer.d.ts +0 -0
- /package/dist/{src/diagnosis → diagnosis}/studio-projection.js +0 -0
- /package/dist/{src/doctor → doctor}/fixer.d.ts +0 -0
- /package/dist/{src/doctor → doctor}/fixer.js +0 -0
- /package/dist/{src/doctor → doctor}/health/builtin-dimensions.d.ts +0 -0
- /package/dist/{src/doctor → doctor}/health/builtin-dimensions.js +0 -0
- /package/dist/{src/doctor → doctor}/health/composer.d.ts +0 -0
- /package/dist/{src/doctor → doctor}/health/dimension-registry.d.ts +0 -0
- /package/dist/{src/doctor → doctor}/health/dimension-registry.js +0 -0
- /package/dist/{src/doctor → doctor}/health/dimension-spec.js +0 -0
- /package/dist/{src/doctor → doctor}/health/parser.d.ts +0 -0
- /package/dist/{src/doctor → doctor}/health/parser.js +0 -0
- /package/dist/{src/doctor → doctor}/health/prompt-builder.d.ts +0 -0
- /package/dist/{src/doctor → doctor}/health/prompt-builder.js +0 -0
- /package/dist/{src/doctor → doctor}/health/register.d.ts +0 -0
- /package/dist/{src/doctor → doctor}/health/register.js +0 -0
- /package/dist/{src/doctor → doctor}/index.d.ts +0 -0
- /package/dist/{src/doctor → doctor}/index.js +0 -0
- /package/dist/{src/doctor → doctor}/preflight.d.ts +0 -0
- /package/dist/{src/doctor → doctor}/preflight.js +0 -0
- /package/dist/{src/doctor → doctor}/rules.d.ts +0 -0
- /package/dist/{src/eval-core → eval-core}/bootstrap.d.ts +0 -0
- /package/dist/{src/eval-core → eval-core}/bootstrap.js +0 -0
- /package/dist/{src/eval-core → eval-core}/cache.d.ts +0 -0
- /package/dist/{src/eval-core → eval-core}/cache.js +0 -0
- /package/dist/{src/eval-core → eval-core}/comparability.d.ts +0 -0
- /package/dist/{src/eval-core → eval-core}/comparability.js +0 -0
- /package/dist/{src/eval-core → eval-core}/dependency-checker.js +0 -0
- /package/dist/{src/eval-core → eval-core}/evaluation-execution.d.ts +0 -0
- /package/dist/{src/eval-core → eval-core}/evaluation-execution.js +0 -0
- /package/dist/{src/eval-core → eval-core}/evaluation-job.d.ts +0 -0
- /package/dist/{src/eval-core → eval-core}/evaluation-job.js +0 -0
- /package/dist/{src/eval-core → eval-core}/evaluation-reporting.d.ts +0 -0
- /package/dist/{src/eval-core → eval-core}/evaluation-reporting.js +0 -0
- /package/dist/{src/eval-core → eval-core}/execution-strategy.d.ts +0 -0
- /package/dist/{src/eval-core → eval-core}/fact-checker.d.ts +0 -0
- /package/dist/{src/eval-core → eval-core}/fact-checker.js +0 -0
- /package/dist/{src/eval-core → eval-core}/layer-gates.d.ts +0 -0
- /package/dist/{src/eval-core → eval-core}/layer-gates.js +0 -0
- /package/dist/{src/eval-core → eval-core}/mock-hook.cjs +0 -0
- /package/dist/{src/eval-core → eval-core}/mocks-runtime.d.ts +0 -0
- /package/dist/{src/eval-core → eval-core}/schema.d.ts +0 -0
- /package/dist/{src/eval-core → eval-core}/schema.js +0 -0
- /package/dist/{src/eval-core → eval-core}/statistics.d.ts +0 -0
- /package/dist/{src/eval-core → eval-core}/statistics.js +0 -0
- /package/dist/{src/eval-core → eval-core}/task-planner.d.ts +0 -0
- /package/dist/{src/eval-core → eval-core}/task-planner.js +0 -0
- /package/dist/{src/eval-core → eval-core}/verdict.d.ts +0 -0
- /package/dist/{src/eval-core → eval-core}/verdict.js +0 -0
- /package/dist/{src/eval-workflows → eval-workflows}/batch-evaluation-workflow.d.ts +0 -0
- /package/dist/{src/eval-workflows → eval-workflows}/batch-evaluation-workflow.js +0 -0
- /package/dist/{src/eval-workflows → eval-workflows}/evaluation-preparation.d.ts +0 -0
- /package/dist/{src/eval-workflows → eval-workflows}/evaluation-preparation.js +0 -0
- /package/dist/{src/eval-workflows → eval-workflows}/run-evaluation.d.ts +0 -0
- /package/dist/{src/executors → executors}/anthropic-api.d.ts +0 -0
- /package/dist/{src/executors → executors}/anthropic-api.js +0 -0
- /package/dist/{src/executors → executors}/claude-cli.d.ts +0 -0
- /package/dist/{src/executors → executors}/claude-cli.js +0 -0
- /package/dist/{src/executors → executors}/claude-sdk-trace.d.ts +0 -0
- /package/dist/{src/executors → executors}/claude-sdk-trace.js +0 -0
- /package/dist/{src/executors → executors}/claude-sdk.d.ts +0 -0
- /package/dist/{src/executors → executors}/claude-sdk.js +0 -0
- /package/dist/{src/executors → executors}/codex-cli-trace.d.ts +0 -0
- /package/dist/{src/executors → executors}/codex-cli-trace.js +0 -0
- /package/dist/{src/executors → executors}/codex-cli.d.ts +0 -0
- /package/dist/{src/executors → executors}/codex-cli.js +0 -0
- /package/dist/{src/executors → executors}/codex-sdk.d.ts +0 -0
- /package/dist/{src/executors → executors}/codex-sdk.js +0 -0
- /package/dist/{src/executors → executors}/gemini.d.ts +0 -0
- /package/dist/{src/executors → executors}/gemini.js +0 -0
- /package/dist/{src/executors → executors}/index.d.ts +0 -0
- /package/dist/{src/executors → executors}/index.js +0 -0
- /package/dist/{src/executors → executors}/openai-api.d.ts +0 -0
- /package/dist/{src/executors → executors}/openai-api.js +0 -0
- /package/dist/{src/executors → executors}/runtime-fingerprint.d.ts +0 -0
- /package/dist/{src/executors → executors}/runtime-fingerprint.js +0 -0
- /package/dist/{src/executors → executors}/script.d.ts +0 -0
- /package/dist/{src/executors → executors}/script.js +0 -0
- /package/dist/{src/grading → grading}/assertions.d.ts +0 -0
- /package/dist/{src/grading → grading}/assertions.js +0 -0
- /package/dist/{src/grading → grading}/debias-validate.d.ts +0 -0
- /package/dist/{src/grading → grading}/debias-validate.js +0 -0
- /package/dist/{src/grading → grading}/diagnostic.d.ts +0 -0
- /package/dist/{src/grading → grading}/diagnostic.js +0 -0
- /package/dist/{src/grading → grading}/gold-cli.d.ts +0 -0
- /package/dist/{src/grading → grading}/gold-cli.js +0 -0
- /package/dist/{src/grading → grading}/gold-dataset.d.ts +0 -0
- /package/dist/{src/grading → grading}/gold-dataset.js +0 -0
- /package/dist/{src/grading → grading}/human-gold.d.ts +0 -0
- /package/dist/{src/grading → grading}/human-gold.js +0 -0
- /package/dist/{src/grading → grading}/index.d.ts +0 -0
- /package/dist/{src/grading → grading}/index.js +0 -0
- /package/dist/{src/grading → grading}/judge.d.ts +0 -0
- /package/dist/{src/grading → grading}/judge.js +0 -0
- /package/dist/{src/grading → grading}/layered-scores.d.ts +0 -0
- /package/dist/{src/grading → grading}/layered-scores.js +0 -0
- /package/dist/{src/inputs → inputs}/eval-config.d.ts +0 -0
- /package/dist/{src/inputs → inputs}/eval-config.js +0 -0
- /package/dist/{src/inputs → inputs}/load-samples.d.ts +0 -0
- /package/dist/{src/inputs → inputs}/load-samples.js +0 -0
- /package/dist/{src/inputs → inputs}/mcp-resolver.d.ts +0 -0
- /package/dist/{src/inputs → inputs}/mcp-resolver.js +0 -0
- /package/dist/{src/inputs → inputs}/skill-loader.d.ts +0 -0
- /package/dist/{src/inputs → inputs}/url-fetcher.d.ts +0 -0
- /package/dist/{src/inputs → inputs}/url-fetcher.js +0 -0
- /package/dist/{src/observability → observability}/review-state.js +0 -0
- /package/dist/{src/observability → observability}/skill-chain-advisories.js +0 -0
- /package/dist/{src/observability → observability}/skill-health-analyzer.d.ts +0 -0
- /package/dist/{src/observability → observability}/skill-health-analyzer.js +0 -0
- /package/dist/{src/observability → observability}/trace-adapter.d.ts +0 -0
- /package/dist/{src/observability → observability}/trace-adapter.js +0 -0
- /package/dist/{src/renderer → renderer}/html-renderer.d.ts +0 -0
- /package/dist/{src/renderer → renderer}/html-renderer.js +0 -0
- /package/dist/{src/renderer → renderer}/layout.d.ts +0 -0
- /package/dist/{src/renderer → renderer}/layout.js +0 -0
- /package/dist/{src/renderer → renderer}/skill-detail-renderer.js +0 -0
- /package/dist/{src/renderer → renderer}/skill-health-renderer.d.ts +0 -0
- /package/dist/{src/renderer → renderer}/skill-health-renderer.js +0 -0
- /package/dist/{src/renderer → renderer}/skill-list-renderer.js +0 -0
- /package/dist/{src/renderer → renderer}/table.d.ts +0 -0
- /package/dist/{src/renderer → renderer}/table.js +0 -0
- /package/dist/{src/renderer → renderer}/test-view.d.ts +0 -0
- /package/dist/{src/renderer → renderer}/test-view.js +0 -0
- /package/dist/{src/renderer → renderer}/trends.d.ts +0 -0
- /package/dist/{src/renderer → renderer}/trends.js +0 -0
- /package/dist/{src/server → server}/job-store.d.ts +0 -0
- /package/dist/{src/server → server}/job-store.js +0 -0
- /package/dist/{src/server → server}/report-server.d.ts +0 -0
- /package/dist/{src/server → server}/report-store.d.ts +0 -0
- /package/dist/{src/server → server}/report-store.js +0 -0
- /package/dist/{src/server → server}/skill-insights.js +0 -0
- /package/dist/{src/shared → shared}/hard-rules.d.ts +0 -0
- /package/dist/{src/shared → shared}/hard-rules.js +0 -0
- /package/dist/{src/shared → shared}/llm-prompts/skill-health.d.ts +0 -0
- /package/dist/{src/shared → shared}/llm-prompts/skill-health.js +0 -0
- /package/dist/{src/shared → shared}/time.d.ts +0 -0
- /package/dist/{src/shared → shared}/time.js +0 -0
- /package/dist/{src/shared → shared}/tool-search.d.ts +0 -0
- /package/dist/{src/shared → shared}/tool-search.js +0 -0
- /package/dist/{src/types → types}/doctor.js +0 -0
- /package/dist/{src/types → types}/eval.js +0 -0
- /package/dist/{src/types → types}/executor.d.ts +0 -0
- /package/dist/{src/types → types}/executor.js +0 -0
- /package/dist/{src/types → types}/judge.d.ts +0 -0
- /package/dist/{src/types → types}/judge.js +0 -0
- /package/dist/{src/types → types}/report.js +0 -0
- /package/dist/{src/types → types}/shared.d.ts +0 -0
- /package/dist/{src/types → types}/shared.js +0 -0
- /package/dist/{src/types → types}/storage.d.ts +0 -0
- /package/dist/{src/types → types}/storage.js +0 -0
|
@@ -1,2400 +0,0 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto';
|
|
2
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
3
|
-
import { homedir } from 'node:os';
|
|
4
|
-
import { join } from 'node:path';
|
|
5
|
-
import { buildExperienceProblemPatterns, mergeExperienceProblemPatterns, } from './problem-patterns.js';
|
|
6
|
-
import { observationMetricAnnotationVerdict, observationReviewStateKey } from './review-state.js';
|
|
7
|
-
import { extractCommandEnvelopeText, stripCommandEnvelopeText } from './trace-attribution.js';
|
|
8
|
-
import { hasAssistantDeliverableArtifactText, hasAssistantDeliverySignalText, hasUserHardRuleText, isAssistantProgressUpdateText, isAssistantProtocolReplyText, isRuntimeProtocolPromptText, isSyntheticUserMessageText, isToolResultFailureText, isUserInteractionMetricText } from './text-signals.js';
|
|
9
|
-
import { durationMsBetween } from '../shared/time.js';
|
|
10
|
-
import { parseSkillFrontmatter, validateSkillHardRules, validateSkillWorkflows } from '../shared/hard-rules.js';
|
|
11
|
-
export function aggregateExperienceChecklistItemStatus(statuses) {
|
|
12
|
-
if (statuses.includes('degraded'))
|
|
13
|
-
return 'degraded';
|
|
14
|
-
if (statuses.includes('failed'))
|
|
15
|
-
return 'failed';
|
|
16
|
-
if (statuses.includes('unknown'))
|
|
17
|
-
return 'unknown';
|
|
18
|
-
if (statuses.includes('not_declared'))
|
|
19
|
-
return 'not_declared';
|
|
20
|
-
if (statuses.includes('passed'))
|
|
21
|
-
return 'passed';
|
|
22
|
-
return 'not_applicable';
|
|
23
|
-
}
|
|
24
|
-
const TEXT_BOUNDARY_CHARS = new Set([
|
|
25
|
-
' ', '\n', '\r', '\t',
|
|
26
|
-
',', ',', ';', ';', '、', '.', '。', '!', '!', '?', '?', ':', ':',
|
|
27
|
-
'"', "'", '“', '”', '‘', '’', '(', ')', '[', ']', '{', '}', '<', '>', '《', '》',
|
|
28
|
-
]);
|
|
29
|
-
const BOUNDED_USER_CORRECTION_TERMS = ['不对', '不是', '错了'];
|
|
30
|
-
const PHRASE_USER_CORRECTION_TERMS = [
|
|
31
|
-
'不是这个',
|
|
32
|
-
'不要这样',
|
|
33
|
-
'理解错',
|
|
34
|
-
'看错',
|
|
35
|
-
'你应该',
|
|
36
|
-
'应该是',
|
|
37
|
-
'直接用',
|
|
38
|
-
'直接按',
|
|
39
|
-
'改成',
|
|
40
|
-
'重来',
|
|
41
|
-
];
|
|
42
|
-
const USER_GOAL_SHIFT_TERMS = [
|
|
43
|
-
'换个方向',
|
|
44
|
-
'重新来',
|
|
45
|
-
'重来',
|
|
46
|
-
'先不',
|
|
47
|
-
'不用这个',
|
|
48
|
-
'先不用',
|
|
49
|
-
'暂时不用',
|
|
50
|
-
'不看这个',
|
|
51
|
-
'换一个',
|
|
52
|
-
'换下一个',
|
|
53
|
-
'另一个问题',
|
|
54
|
-
'另外一个问题',
|
|
55
|
-
'先看别的',
|
|
56
|
-
'先处理别的',
|
|
57
|
-
];
|
|
58
|
-
const NEGATIVE_FEEDBACK_TERMS = [
|
|
59
|
-
'没有用',
|
|
60
|
-
'没用',
|
|
61
|
-
'不行',
|
|
62
|
-
'太慢',
|
|
63
|
-
'看不懂',
|
|
64
|
-
'不需要',
|
|
65
|
-
'别再',
|
|
66
|
-
'怎么又',
|
|
67
|
-
'赶紧',
|
|
68
|
-
'有问题',
|
|
69
|
-
'不符合',
|
|
70
|
-
'做错了',
|
|
71
|
-
'做错',
|
|
72
|
-
'完全错',
|
|
73
|
-
'错得离谱',
|
|
74
|
-
'很垃圾',
|
|
75
|
-
'太垃圾',
|
|
76
|
-
'乱来',
|
|
77
|
-
'瞎搞',
|
|
78
|
-
'白干',
|
|
79
|
-
'浪费时间',
|
|
80
|
-
'没有价值',
|
|
81
|
-
'没价值',
|
|
82
|
-
'没意义',
|
|
83
|
-
'不好用',
|
|
84
|
-
'用不了',
|
|
85
|
-
'没有帮助',
|
|
86
|
-
'没帮助',
|
|
87
|
-
'毫无帮助',
|
|
88
|
-
'太菜',
|
|
89
|
-
'很菜',
|
|
90
|
-
'真菜',
|
|
91
|
-
'菜了',
|
|
92
|
-
'菜啊',
|
|
93
|
-
];
|
|
94
|
-
const BOUNDED_NEGATIVE_FEEDBACK_TERMS = ['失败', '垃圾', '菜'];
|
|
95
|
-
const ADDITIONAL_NEGATIVE_FEEDBACK_TERMS = [
|
|
96
|
-
'不对',
|
|
97
|
-
'错了',
|
|
98
|
-
'有误',
|
|
99
|
-
'不可以',
|
|
100
|
-
'不是这个',
|
|
101
|
-
'不是我要的',
|
|
102
|
-
'跑偏',
|
|
103
|
-
'绕路',
|
|
104
|
-
'你没懂',
|
|
105
|
-
'没懂',
|
|
106
|
-
'重做',
|
|
107
|
-
'重新做',
|
|
108
|
-
'重来',
|
|
109
|
-
'不符合预期',
|
|
110
|
-
];
|
|
111
|
-
const POSITIVE_FEEDBACK_TERMS = [
|
|
112
|
-
'非常好',
|
|
113
|
-
'很好',
|
|
114
|
-
'做得好',
|
|
115
|
-
'做的好',
|
|
116
|
-
'做得不错',
|
|
117
|
-
'做的不错',
|
|
118
|
-
'不错',
|
|
119
|
-
'很棒',
|
|
120
|
-
'优秀',
|
|
121
|
-
'厉害',
|
|
122
|
-
'很厉害',
|
|
123
|
-
'值得鼓励',
|
|
124
|
-
'很有用',
|
|
125
|
-
'非常有用',
|
|
126
|
-
'很有价值',
|
|
127
|
-
'非常有价值',
|
|
128
|
-
'很有帮助',
|
|
129
|
-
'非常有帮助',
|
|
130
|
-
'good job',
|
|
131
|
-
'great job',
|
|
132
|
-
'well done',
|
|
133
|
-
'nice work',
|
|
134
|
-
'excellent',
|
|
135
|
-
'awesome',
|
|
136
|
-
];
|
|
137
|
-
const USER_INTERRUPTION_RE = /\[Request interrupted by user(?: for tool use)?\]|interrupted by user|用户中断|停止任务|停一下|先别|别动|等一下|等下|等等|取消(?:任务|执行)?|先暂停|暂停一下/i;
|
|
138
|
-
const TIMELINE_PREVIEW_EVENT_LIMIT = 240;
|
|
139
|
-
const ZERO_INDICATORS = {
|
|
140
|
-
userMessageCount: 0,
|
|
141
|
-
userFollowUpCount: 0,
|
|
142
|
-
userCorrectionCount: 0,
|
|
143
|
-
userInterruptionCount: 0,
|
|
144
|
-
sessionInterruptedCount: 0,
|
|
145
|
-
negativeFeedbackCount: 0,
|
|
146
|
-
positiveFeedbackCount: 0,
|
|
147
|
-
userGoalShiftCount: 0,
|
|
148
|
-
hardRuleTextHitCount: 0,
|
|
149
|
-
assistantDeliverySignalCount: 0,
|
|
150
|
-
deliverableArtifactSignalCount: 0,
|
|
151
|
-
selfCorrectionCount: 0,
|
|
152
|
-
repeatedExecutionCount: 0,
|
|
153
|
-
toolCallCount: 0,
|
|
154
|
-
toolFailureCount: 0,
|
|
155
|
-
highObservationCount: 0,
|
|
156
|
-
mediumObservationCount: 0,
|
|
157
|
-
hedgingCount: 0,
|
|
158
|
-
explicitMarkerCount: 0,
|
|
159
|
-
};
|
|
160
|
-
export function buildObservationExperienceReport(input) {
|
|
161
|
-
const sessionsBySourceTrace = new Map(input.sessions.map((session) => [session.sourcePath, session]));
|
|
162
|
-
const sessionGroupsById = groupSessionsByLogicalId(input.sessions);
|
|
163
|
-
const sessionGroupsByKey = groupSessionsByExperienceKey(input.sessions);
|
|
164
|
-
const goalSlices = [];
|
|
165
|
-
const invocations = [];
|
|
166
|
-
for (const segment of input.segments) {
|
|
167
|
-
if (segment.skillName === 'general')
|
|
168
|
-
continue;
|
|
169
|
-
const session = sessionsBySourceTrace.get(segment.sourceTrace ?? '') ?? sessionGroupsById.get(segment.sessionId)?.[0];
|
|
170
|
-
const sourceTrace = segment.sourceTrace ?? session?.sourcePath ?? '';
|
|
171
|
-
const sessionGroupKey = session ? experienceSessionGroupKey(session) : `trace:${sourceTrace || segment.sessionId}`;
|
|
172
|
-
const relatedItems = relatedObservationItems(segment, input.items);
|
|
173
|
-
const bounds = session ? segmentRecordBounds(session, segment) : { start: 0, end: 0 };
|
|
174
|
-
const timeline = session ? buildTimeline(session, bounds.start, bounds.end) : [];
|
|
175
|
-
const metricScopeId = hashParts('session', segment.skillName, sessionGroupKey);
|
|
176
|
-
const userRefs = timeline.filter((event) => event.kind === 'user_message');
|
|
177
|
-
const indicators = indicatorsForSegment(segment, relatedItems, timeline, metricScopeId, input.reviewState);
|
|
178
|
-
const observationRefs = relatedItems.map(observationEvidenceRef);
|
|
179
|
-
const evidenceChain = evidenceChainForTimeline(timeline, observationRefs);
|
|
180
|
-
const ruleFindings = ruleFindingsForEvidence(indicators, timeline, observationRefs, evidenceChain, metricScopeId, input.reviewState);
|
|
181
|
-
const assistiveInference = assistiveInferenceForEvidence(indicators, evidenceChain, ruleFindings);
|
|
182
|
-
const problemPatterns = buildExperienceProblemPatterns({
|
|
183
|
-
skillName: segment.skillName,
|
|
184
|
-
sessionId: segment.sessionId,
|
|
185
|
-
timeline,
|
|
186
|
-
metricScopeId,
|
|
187
|
-
reviewState: input.reviewState,
|
|
188
|
-
});
|
|
189
|
-
const hasGoalShift = userRefs.some((ref) => hasUserGoalShiftSignal(ref.snippet ?? ''));
|
|
190
|
-
// 包含 sourceTrace 防止 main + subagent 因 segmentIndex 各自从 0 计数而撞 hash
|
|
191
|
-
// (segmenter 给 segment.sessionId = sessionGroupId,main 和 subagent 共享)
|
|
192
|
-
const goalSliceId = hashParts('goal', segment.sessionId, sourceTrace, segment.skillName, String(segment.segmentIndex));
|
|
193
|
-
const invocationId = hashParts('invocation', segment.sessionId, sourceTrace, segment.skillName, String(segment.segmentIndex));
|
|
194
|
-
goalSlices.push({
|
|
195
|
-
id: goalSliceId,
|
|
196
|
-
skillName: segment.skillName,
|
|
197
|
-
sessionId: segment.sessionId,
|
|
198
|
-
sourceTrace,
|
|
199
|
-
cwd: segment.cwd,
|
|
200
|
-
startTimestamp: segment.startTimestamp,
|
|
201
|
-
endTimestamp: segment.endTimestamp,
|
|
202
|
-
sliceReasonCode: hasGoalShift ? 'explicit_user_goal_shift' : 'skill_segment_boundary',
|
|
203
|
-
sliceConfidence: hasGoalShift ? 'medium' : 'high',
|
|
204
|
-
inferredUserGoal: inferUserGoal(userRefs),
|
|
205
|
-
userMessageRefs: userRefs.slice(0, 8).map(evidenceRefFromTimeline),
|
|
206
|
-
});
|
|
207
|
-
invocations.push({
|
|
208
|
-
id: invocationId,
|
|
209
|
-
skillName: segment.skillName,
|
|
210
|
-
sessionId: segment.sessionId,
|
|
211
|
-
sessionGroupKey,
|
|
212
|
-
sourceTrace,
|
|
213
|
-
sourceKind: segment.sourceKind ?? sourceKindForPath(sourceTrace),
|
|
214
|
-
entrypoint: session ? session.entrypoint ?? inferEntrypointFromRecords(session) : undefined,
|
|
215
|
-
sourceMetadata: session?.sourceMetadata,
|
|
216
|
-
cwd: segment.cwd,
|
|
217
|
-
segmentIndex: segment.segmentIndex,
|
|
218
|
-
goalSliceId,
|
|
219
|
-
startTimestamp: segment.startTimestamp,
|
|
220
|
-
endTimestamp: segment.endTimestamp,
|
|
221
|
-
attribution: {
|
|
222
|
-
source: segment.attribution?.source ?? 'unknown',
|
|
223
|
-
confidence: segment.attribution?.confidence ?? 0.3,
|
|
224
|
-
rawSkillRef: segment.attribution?.rawSkillRef,
|
|
225
|
-
pluginName: segment.attribution?.pluginName,
|
|
226
|
-
commandName: segment.attribution?.commandName,
|
|
227
|
-
},
|
|
228
|
-
metrics: segment.metrics,
|
|
229
|
-
toolCounts: countTools(segment),
|
|
230
|
-
indicators,
|
|
231
|
-
evidenceChain,
|
|
232
|
-
ruleFindings,
|
|
233
|
-
assistiveInference,
|
|
234
|
-
problemPatterns,
|
|
235
|
-
relatedObservationIds: relatedItems.map((item) => item.id),
|
|
236
|
-
evidenceRefs: [
|
|
237
|
-
...observationRefs,
|
|
238
|
-
...userRefs.slice(0, 5).map(evidenceRefFromTimeline),
|
|
239
|
-
],
|
|
240
|
-
timeline,
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
const sessions = summarizeExperienceSessions(invocations, sessionGroupsByKey, input.generatedAt, input.reviewState);
|
|
244
|
-
const skills = summarizeExperienceSkills(sessions, invocations);
|
|
245
|
-
return {
|
|
246
|
-
kind: 'observe-experience',
|
|
247
|
-
schemaVersion: 1,
|
|
248
|
-
scope: 'evidence-only',
|
|
249
|
-
generatedAt: input.generatedAt,
|
|
250
|
-
meta: {
|
|
251
|
-
sessionCount: sessions.length,
|
|
252
|
-
skillCount: skills.length,
|
|
253
|
-
invocationCount: invocations.length,
|
|
254
|
-
goalSliceCount: goalSlices.length,
|
|
255
|
-
noteCodes: ['no_llm_judge', 'no_auto_verdict', 'default_goal_slice_is_allowed', 'deterministic_assistive_inference'],
|
|
256
|
-
},
|
|
257
|
-
goalSlices,
|
|
258
|
-
invocations,
|
|
259
|
-
sessions,
|
|
260
|
-
skills,
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
function relatedObservationItems(segment, items) {
|
|
264
|
-
return items.filter((item) => item.skillName === segment.skillName
|
|
265
|
-
&& (item.sessionId === segment.sessionId || item.recentSessionIds.includes(segment.sessionId))
|
|
266
|
-
&& timestampsOverlap(item.firstSeen, item.lastSeen, segment.startTimestamp, segment.endTimestamp));
|
|
267
|
-
}
|
|
268
|
-
function logicalSessionId(session) {
|
|
269
|
-
return session.sessionGroupId ?? session.sessionId;
|
|
270
|
-
}
|
|
271
|
-
function experienceSessionGroupKey(session) {
|
|
272
|
-
const logicalId = logicalSessionId(session);
|
|
273
|
-
if (session.traceRole && session.traceRole !== 'standalone' && session.sessionGroupPath) {
|
|
274
|
-
return `group:${session.sessionGroupPath}\u0000${logicalId}`;
|
|
275
|
-
}
|
|
276
|
-
return `trace:${session.sourcePath}`;
|
|
277
|
-
}
|
|
278
|
-
function groupSessionsByLogicalId(sessions) {
|
|
279
|
-
const groups = new Map();
|
|
280
|
-
for (const session of sessions) {
|
|
281
|
-
const key = logicalSessionId(session);
|
|
282
|
-
const group = groups.get(key) ?? [];
|
|
283
|
-
group.push(session);
|
|
284
|
-
groups.set(key, group);
|
|
285
|
-
}
|
|
286
|
-
for (const [key, group] of groups.entries()) {
|
|
287
|
-
groups.set(key, group.sort(compareSessionsForTimeline));
|
|
288
|
-
}
|
|
289
|
-
return groups;
|
|
290
|
-
}
|
|
291
|
-
function groupSessionsByExperienceKey(sessions) {
|
|
292
|
-
const groups = new Map();
|
|
293
|
-
for (const session of sessions) {
|
|
294
|
-
const key = experienceSessionGroupKey(session);
|
|
295
|
-
const group = groups.get(key) ?? [];
|
|
296
|
-
group.push(session);
|
|
297
|
-
groups.set(key, group);
|
|
298
|
-
}
|
|
299
|
-
for (const [key, group] of groups.entries()) {
|
|
300
|
-
groups.set(key, group.sort(compareSessionsForTimeline));
|
|
301
|
-
}
|
|
302
|
-
return groups;
|
|
303
|
-
}
|
|
304
|
-
function compareSessionsForTimeline(a, b) {
|
|
305
|
-
const roleRank = (session) => session.traceRole === 'main' ? 0 : session.traceRole === 'standalone' ? 1 : 2;
|
|
306
|
-
const rank = roleRank(a) - roleRank(b);
|
|
307
|
-
if (rank !== 0)
|
|
308
|
-
return rank;
|
|
309
|
-
const time = (a.startTimestamp ?? '').localeCompare(b.startTimestamp ?? '');
|
|
310
|
-
if (time !== 0)
|
|
311
|
-
return time;
|
|
312
|
-
return a.sourcePath.localeCompare(b.sourcePath);
|
|
313
|
-
}
|
|
314
|
-
function timestampsOverlap(aStart, aEnd, bStart, bEnd) {
|
|
315
|
-
if (!aStart || !aEnd || !bStart || !bEnd)
|
|
316
|
-
return true;
|
|
317
|
-
return aStart <= bEnd && bStart <= aEnd;
|
|
318
|
-
}
|
|
319
|
-
function segmentRecordBounds(session, segment) {
|
|
320
|
-
if (typeof segment.startRecordIndex === 'number' && typeof segment.endRecordIndex === 'number') {
|
|
321
|
-
const rawStart = clampRecordIndex(session, segment.startRecordIndex);
|
|
322
|
-
const rawEnd = clampRecordIndex(session, Math.max(segment.startRecordIndex, segment.endRecordIndex));
|
|
323
|
-
const humanStart = Math.min(rawStart, previousHumanUserRecordIndex(session, rawStart) ?? rawStart);
|
|
324
|
-
return {
|
|
325
|
-
start: includeLeadingRuntimeContext(session, humanStart),
|
|
326
|
-
end: includeTrailingDeliveryContext(session, Math.min(session.records.length, rawEnd + 1)),
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
const indexes = segment.toolCalls
|
|
330
|
-
.map((toolCall) => toolCall.messageIndex)
|
|
331
|
-
.filter((index) => typeof index === 'number' && index >= 0);
|
|
332
|
-
if (indexes.length > 0) {
|
|
333
|
-
const start = Math.max(0, Math.min(...indexes) - 3);
|
|
334
|
-
return {
|
|
335
|
-
start: Math.min(start, previousHumanUserRecordIndex(session, start) ?? start),
|
|
336
|
-
end: includeTrailingDeliveryContext(session, Math.min(session.records.length, Math.max(...indexes) + 5)),
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
const timestampIndexes = [];
|
|
340
|
-
session.records.forEach((record, index) => {
|
|
341
|
-
const ts = timestampOf(record);
|
|
342
|
-
if (ts && ts >= segment.startTimestamp && ts <= segment.endTimestamp)
|
|
343
|
-
timestampIndexes.push(index);
|
|
344
|
-
});
|
|
345
|
-
if (timestampIndexes.length === 0)
|
|
346
|
-
return { start: 0, end: Math.min(session.records.length, 12) };
|
|
347
|
-
const start = Math.max(0, Math.min(...timestampIndexes) - 2);
|
|
348
|
-
return {
|
|
349
|
-
start: Math.min(start, previousHumanUserRecordIndex(session, start) ?? start),
|
|
350
|
-
end: includeTrailingDeliveryContext(session, Math.min(session.records.length, Math.max(...timestampIndexes) + 3)),
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
function clampRecordIndex(session, index) {
|
|
354
|
-
return Math.max(0, Math.min(session.records.length - 1, index));
|
|
355
|
-
}
|
|
356
|
-
function includeLeadingRuntimeContext(session, start) {
|
|
357
|
-
let nextStart = start;
|
|
358
|
-
for (let index = start - 1; index >= 0; index -= 1) {
|
|
359
|
-
const events = timelineEventsFromRecord(session, session.records[index], index);
|
|
360
|
-
if (events.length === 0)
|
|
361
|
-
continue;
|
|
362
|
-
if (events.some((event) => event.kind === 'runtime_context')) {
|
|
363
|
-
nextStart = index;
|
|
364
|
-
continue;
|
|
365
|
-
}
|
|
366
|
-
break;
|
|
367
|
-
}
|
|
368
|
-
return nextStart;
|
|
369
|
-
}
|
|
370
|
-
function includeTrailingDeliveryContext(session, end) {
|
|
371
|
-
const safeEnd = Math.min(session.records.length, Math.max(0, end));
|
|
372
|
-
const lookaheadEnd = Math.min(session.records.length, safeEnd + 8);
|
|
373
|
-
for (let index = safeEnd; index < lookaheadEnd; index += 1) {
|
|
374
|
-
const events = timelineEventsFromRecord(session, session.records[index], index);
|
|
375
|
-
if (events.some((event) => event.kind === 'user_message'))
|
|
376
|
-
break;
|
|
377
|
-
if (events.some(isAssistantDeliveryEvent))
|
|
378
|
-
return index + 1;
|
|
379
|
-
}
|
|
380
|
-
return safeEnd;
|
|
381
|
-
}
|
|
382
|
-
function previousHumanUserRecordIndex(session, start) {
|
|
383
|
-
for (let index = Math.min(start, session.records.length - 1); index >= 0; index -= 1) {
|
|
384
|
-
const events = timelineEventsFromRecord(session, session.records[index], index);
|
|
385
|
-
if (events.some((event) => event.kind === 'user_message'))
|
|
386
|
-
return index;
|
|
387
|
-
}
|
|
388
|
-
return undefined;
|
|
389
|
-
}
|
|
390
|
-
function isAssistantDeliveryEvent(event) {
|
|
391
|
-
if (event.kind !== 'assistant_message')
|
|
392
|
-
return false;
|
|
393
|
-
const text = event.fullText ?? event.snippet ?? '';
|
|
394
|
-
return hasAssistantDeliverySignalText(text);
|
|
395
|
-
}
|
|
396
|
-
function isAssistantDeliverableArtifactEvent(event) {
|
|
397
|
-
if (event.kind !== 'assistant_message')
|
|
398
|
-
return false;
|
|
399
|
-
const text = event.fullText ?? event.snippet ?? '';
|
|
400
|
-
return hasAssistantDeliverableArtifactText(text);
|
|
401
|
-
}
|
|
402
|
-
function isAssistantProgressUpdateEvent(event) {
|
|
403
|
-
if (event.kind !== 'assistant_message')
|
|
404
|
-
return false;
|
|
405
|
-
const text = event.fullText ?? event.snippet ?? '';
|
|
406
|
-
return isAssistantProgressUpdateText(text);
|
|
407
|
-
}
|
|
408
|
-
function hasSelfCorrectionSignal(event) {
|
|
409
|
-
if (event.kind !== 'assistant_message')
|
|
410
|
-
return false;
|
|
411
|
-
const text = event.fullText ?? event.snippet ?? '';
|
|
412
|
-
return /刚才.*(?:不对|错了|有误)|发现.*(?:不对|错了|问题|遗漏)|重新(?:检查|分析|执行|生成|整理|补(?:充)?(?:结论|答案|回答))|改用|换成|修正|我再(?:检查|重新|看)|跑偏|偏(?:题|了|向)|没(?:有)?(?:完整|完全)?(?:回答|覆盖)|漏(?:了|掉)|不完整|我刚追问了一版|按原问题(?:重新)?(?:补|回|答)|\b(?:recheck|retry|rerun|mistake|wrong)\b/i.test(text);
|
|
413
|
-
}
|
|
414
|
-
function hasRepeatedExecutionSignal(event) {
|
|
415
|
-
if (event.kind !== 'assistant_message' && event.kind !== 'tool_use')
|
|
416
|
-
return false;
|
|
417
|
-
const text = `${event.label ?? ''} ${event.toolName ?? ''} ${event.fullText ?? event.snippet ?? ''}`;
|
|
418
|
-
return /重复(?:执行|尝试|读取|搜索|调用)|再次(?:执行|读取|搜索|调用)|重新(?:执行|读取|搜索|调用|跑|运行)|再(?:执行|读取|搜索|调用|跑)一遍|重试|\b(?:retry|rerun)\b/i.test(text);
|
|
419
|
-
}
|
|
420
|
-
function buildTimeline(session, start, end) {
|
|
421
|
-
return buildTimelineWindow(session, start, end).slice(0, TIMELINE_PREVIEW_EVENT_LIMIT);
|
|
422
|
-
}
|
|
423
|
-
function buildTimelineWindow(session, start, end) {
|
|
424
|
-
const events = [];
|
|
425
|
-
const safeEnd = Math.min(session.records.length, Math.max(start, end));
|
|
426
|
-
for (let index = start; index < safeEnd; index += 1) {
|
|
427
|
-
events.push(...timelineEventsFromRecord(session, session.records[index], index));
|
|
428
|
-
}
|
|
429
|
-
return events
|
|
430
|
-
.sort((a, b) => a.order - b.order);
|
|
431
|
-
}
|
|
432
|
-
function timelineEventsFromRecord(session, record, messageIndex) {
|
|
433
|
-
if (!record || typeof record !== 'object')
|
|
434
|
-
return [];
|
|
435
|
-
const rec = record;
|
|
436
|
-
const uuid = typeof rec.uuid === 'string' ? rec.uuid : undefined;
|
|
437
|
-
const timestamp = timestampOf(record);
|
|
438
|
-
const base = {
|
|
439
|
-
sourceTrace: session.sourcePath,
|
|
440
|
-
sessionId: logicalSessionId(session),
|
|
441
|
-
traceRole: session.traceRole,
|
|
442
|
-
traceLabel: session.traceLabel,
|
|
443
|
-
messageIndex,
|
|
444
|
-
messageUuid: uuid,
|
|
445
|
-
timestamp,
|
|
446
|
-
};
|
|
447
|
-
if (rec.type === 'user') {
|
|
448
|
-
const user = rec;
|
|
449
|
-
return userEvents(user, base, messageIndex);
|
|
450
|
-
}
|
|
451
|
-
if (rec.type === 'assistant') {
|
|
452
|
-
const assistant = rec;
|
|
453
|
-
return assistantEvents(assistant, base, messageIndex);
|
|
454
|
-
}
|
|
455
|
-
return sessionEventFromRecord(rec, base, messageIndex);
|
|
456
|
-
}
|
|
457
|
-
function sessionEventFromRecord(record, base, messageIndex) {
|
|
458
|
-
const type = typeof record.type === 'string' ? record.type : '';
|
|
459
|
-
const rawText = safeRecordText(record);
|
|
460
|
-
if (!isSessionBoundaryType(type) && !hasAssistantTurnFailedText(rawText))
|
|
461
|
-
return [];
|
|
462
|
-
return [timelineEvent({
|
|
463
|
-
...base,
|
|
464
|
-
kind: 'runtime_context',
|
|
465
|
-
role: 'other',
|
|
466
|
-
order: messageIndex * 10,
|
|
467
|
-
snippet: snippet(rawText || type, 700),
|
|
468
|
-
fullText: fullText(rawText || type),
|
|
469
|
-
label: type || 'session event',
|
|
470
|
-
})];
|
|
471
|
-
}
|
|
472
|
-
function isSessionBoundaryType(type) {
|
|
473
|
-
return /^session[._-](?:started|ended)$/i.test(type);
|
|
474
|
-
}
|
|
475
|
-
function safeRecordText(record) {
|
|
476
|
-
try {
|
|
477
|
-
return JSON.stringify(record);
|
|
478
|
-
}
|
|
479
|
-
catch {
|
|
480
|
-
return String(record ?? '');
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
function hasAssistantTurnFailedText(value) {
|
|
484
|
-
return /\[assistant turn failed\]|assistant turn failed|assistant_turn_failed|turn failed/i.test(value);
|
|
485
|
-
}
|
|
486
|
-
function userEvents(record, base, messageIndex) {
|
|
487
|
-
const content = record.message.content;
|
|
488
|
-
const events = [];
|
|
489
|
-
if (typeof content === 'string') {
|
|
490
|
-
events.push(...userTextEventsFromText(record, content, base, messageIndex, 0));
|
|
491
|
-
return events;
|
|
492
|
-
}
|
|
493
|
-
let textIndex = 0;
|
|
494
|
-
let resultIndex = 0;
|
|
495
|
-
for (const part of content) {
|
|
496
|
-
if (part.type === 'text') {
|
|
497
|
-
const nextEvents = userTextEventsFromText(record, part.text, base, messageIndex, textIndex);
|
|
498
|
-
events.push(...nextEvents);
|
|
499
|
-
if (nextEvents.length > 0)
|
|
500
|
-
textIndex += nextEvents.length;
|
|
501
|
-
}
|
|
502
|
-
else if (part.type === 'tool_result') {
|
|
503
|
-
const full = fullText(part.content);
|
|
504
|
-
const text = snippet(part.content, 900);
|
|
505
|
-
const failed = part.is_error === true || isToolResultFailureText(part.content);
|
|
506
|
-
events.push(timelineEvent({
|
|
507
|
-
...base,
|
|
508
|
-
kind: 'tool_result',
|
|
509
|
-
role: 'tool',
|
|
510
|
-
order: messageIndex * 10 + 5 + resultIndex,
|
|
511
|
-
toolUseId: part.tool_use_id,
|
|
512
|
-
isError: failed,
|
|
513
|
-
snippet: text,
|
|
514
|
-
fullText: full,
|
|
515
|
-
label: failed ? 'tool result error' : 'tool result',
|
|
516
|
-
}));
|
|
517
|
-
resultIndex += 1;
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
return events;
|
|
521
|
-
}
|
|
522
|
-
function userTextEventsFromText(record, rawText, base, messageIndex, offset) {
|
|
523
|
-
const events = [];
|
|
524
|
-
const commandEnvelope = extractCommandEnvelopeText(rawText);
|
|
525
|
-
if (commandEnvelope) {
|
|
526
|
-
events.push(timelineEvent({
|
|
527
|
-
...base,
|
|
528
|
-
kind: 'runtime_context',
|
|
529
|
-
role: 'tool',
|
|
530
|
-
order: messageIndex * 10 + offset,
|
|
531
|
-
snippet: snippet(commandEnvelope, 700),
|
|
532
|
-
fullText: fullText(commandEnvelope),
|
|
533
|
-
label: 'command envelope',
|
|
534
|
-
}));
|
|
535
|
-
}
|
|
536
|
-
const humanText = commandEnvelope ? stripCommandEnvelopeText(rawText) : rawText;
|
|
537
|
-
const full = fullText(humanText);
|
|
538
|
-
const text = snippet(humanText, 700);
|
|
539
|
-
if (text) {
|
|
540
|
-
const kind = userTextEventKind(record, text);
|
|
541
|
-
events.push(timelineEvent({
|
|
542
|
-
...base,
|
|
543
|
-
kind,
|
|
544
|
-
role: kind === 'user_message' ? 'user' : kind === 'synthetic_user_event' ? 'other' : 'tool',
|
|
545
|
-
order: messageIndex * 10 + offset + (commandEnvelope ? 1 : 0),
|
|
546
|
-
snippet: text,
|
|
547
|
-
fullText: full,
|
|
548
|
-
label: userTextEventLabel(kind),
|
|
549
|
-
}));
|
|
550
|
-
}
|
|
551
|
-
return events;
|
|
552
|
-
}
|
|
553
|
-
function assistantEvents(record, base, messageIndex) {
|
|
554
|
-
const events = [];
|
|
555
|
-
const textParts = [];
|
|
556
|
-
let index = 0;
|
|
557
|
-
for (const part of record.message.content) {
|
|
558
|
-
if (part.type === 'text' && part.text)
|
|
559
|
-
textParts.push(part.text);
|
|
560
|
-
if (part.type === 'tool_use' && part.id && part.name) {
|
|
561
|
-
const inputText = JSON.stringify(part.input ?? {});
|
|
562
|
-
events.push(timelineEvent({
|
|
563
|
-
...base,
|
|
564
|
-
kind: 'tool_use',
|
|
565
|
-
role: 'assistant',
|
|
566
|
-
order: messageIndex * 10 + 5 + index,
|
|
567
|
-
toolUseId: part.id,
|
|
568
|
-
toolName: part.name,
|
|
569
|
-
snippet: snippet(inputText, 900),
|
|
570
|
-
fullText: fullText(inputText),
|
|
571
|
-
label: `tool_use ${part.name}`,
|
|
572
|
-
}));
|
|
573
|
-
index += 1;
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
const rawText = textParts.join('\n');
|
|
577
|
-
const text = snippet(rawText, 700);
|
|
578
|
-
if (text) {
|
|
579
|
-
const protocolReply = isAssistantProtocolReplyText(rawText);
|
|
580
|
-
events.unshift(timelineEvent({
|
|
581
|
-
...base,
|
|
582
|
-
kind: protocolReply ? 'runtime_context' : 'assistant_message',
|
|
583
|
-
role: 'assistant',
|
|
584
|
-
order: messageIndex * 10,
|
|
585
|
-
snippet: text,
|
|
586
|
-
fullText: fullText(rawText),
|
|
587
|
-
label: protocolReply ? 'assistant protocol reply' : 'assistant message',
|
|
588
|
-
}));
|
|
589
|
-
}
|
|
590
|
-
return events;
|
|
591
|
-
}
|
|
592
|
-
function timelineEvent(input) {
|
|
593
|
-
return {
|
|
594
|
-
...input,
|
|
595
|
-
id: hashParts(input.sourceTrace, input.sessionId, String(input.messageIndex ?? ''), input.kind, input.toolUseId ?? '', input.snippet ?? ''),
|
|
596
|
-
};
|
|
597
|
-
}
|
|
598
|
-
function userTextEventKind(record, text) {
|
|
599
|
-
if (isSkillContextRecord(record, text))
|
|
600
|
-
return 'skill_context';
|
|
601
|
-
if (isRuntimeContextRecord(record, text))
|
|
602
|
-
return 'runtime_context';
|
|
603
|
-
if (isSyntheticUserMessageText(text))
|
|
604
|
-
return 'synthetic_user_event';
|
|
605
|
-
return 'user_message';
|
|
606
|
-
}
|
|
607
|
-
function userTextEventLabel(kind) {
|
|
608
|
-
if (kind === 'skill_context')
|
|
609
|
-
return 'skill context';
|
|
610
|
-
if (kind === 'runtime_context')
|
|
611
|
-
return 'runtime context';
|
|
612
|
-
if (kind === 'synthetic_user_event')
|
|
613
|
-
return 'synthetic user event';
|
|
614
|
-
return 'user message';
|
|
615
|
-
}
|
|
616
|
-
function observationEvidenceRef(item) {
|
|
617
|
-
return {
|
|
618
|
-
id: hashParts('observation', item.id),
|
|
619
|
-
kind: 'observation',
|
|
620
|
-
sourceTrace: item.sourceTrace,
|
|
621
|
-
sessionId: item.sessionId,
|
|
622
|
-
messageIndex: item.evidence.messageIndex,
|
|
623
|
-
messageUuid: item.evidence.messageUuid,
|
|
624
|
-
toolUseId: item.evidence.toolUseId,
|
|
625
|
-
timestamp: item.evidence.segmentTimestamp,
|
|
626
|
-
role: 'other',
|
|
627
|
-
label: `${item.signalType}/${item.signalSubtype}`,
|
|
628
|
-
snippet: snippet(item.evidence.query || item.evidence.path || item.evidence.assistantSnippet || item.evidence.outputSnippet || item.evidence.markerToken, 700),
|
|
629
|
-
};
|
|
630
|
-
}
|
|
631
|
-
function evidenceRefFromTimeline(event) {
|
|
632
|
-
return {
|
|
633
|
-
id: event.id,
|
|
634
|
-
kind: event.kind,
|
|
635
|
-
sourceTrace: event.sourceTrace,
|
|
636
|
-
sessionId: event.sessionId,
|
|
637
|
-
traceRole: event.traceRole,
|
|
638
|
-
traceLabel: event.traceLabel,
|
|
639
|
-
messageIndex: event.messageIndex,
|
|
640
|
-
messageUuid: event.messageUuid,
|
|
641
|
-
toolUseId: event.toolUseId,
|
|
642
|
-
timestamp: event.timestamp,
|
|
643
|
-
role: event.role,
|
|
644
|
-
label: event.label,
|
|
645
|
-
snippet: event.snippet,
|
|
646
|
-
};
|
|
647
|
-
}
|
|
648
|
-
function evidenceChainForTimeline(timeline, observationRefs) {
|
|
649
|
-
const events = uniqueTimelineEvents(timeline).sort(compareTimelineEvents);
|
|
650
|
-
const userEvents = events.filter((event) => event.kind === 'user_message' && !isSyntheticUserMessageText(event.snippet ?? ''));
|
|
651
|
-
const runtimeEvents = events.filter((event) => event.kind === 'runtime_context');
|
|
652
|
-
const skillEvents = events.filter((event) => event.kind === 'skill_context');
|
|
653
|
-
const assistantEvents = events.filter((event) => event.kind === 'assistant_message');
|
|
654
|
-
const toolUseEvents = events.filter((event) => event.kind === 'tool_use');
|
|
655
|
-
const toolResultEvents = events.filter((event) => event.kind === 'tool_result');
|
|
656
|
-
const toolFailureEvents = toolResultEvents.filter(isToolFailureEvent);
|
|
657
|
-
return {
|
|
658
|
-
userMessageCount: userEvents.length,
|
|
659
|
-
runtimeContextCount: runtimeEvents.length,
|
|
660
|
-
skillContextCount: skillEvents.length,
|
|
661
|
-
assistantMessageCount: assistantEvents.length,
|
|
662
|
-
toolUseCount: toolUseEvents.length,
|
|
663
|
-
toolResultCount: toolResultEvents.length,
|
|
664
|
-
toolFailureResultCount: toolFailureEvents.length,
|
|
665
|
-
observationCount: observationRefs.length,
|
|
666
|
-
firstUserMessage: userEvents[0] ? evidenceRefFromTimeline(userEvents[0]) : undefined,
|
|
667
|
-
firstRuntimeContext: runtimeEvents[0] ? evidenceRefFromTimeline(runtimeEvents[0]) : undefined,
|
|
668
|
-
firstSkillContext: skillEvents[0] ? evidenceRefFromTimeline(skillEvents[0]) : undefined,
|
|
669
|
-
firstToolUse: toolUseEvents[0] ? evidenceRefFromTimeline(toolUseEvents[0]) : undefined,
|
|
670
|
-
firstToolFailure: toolFailureEvents[0] ? evidenceRefFromTimeline(toolFailureEvents[0]) : undefined,
|
|
671
|
-
lastAssistantMessage: assistantEvents.at(-1) ? evidenceRefFromTimeline(assistantEvents.at(-1)) : undefined,
|
|
672
|
-
};
|
|
673
|
-
}
|
|
674
|
-
function ruleFindingsForEvidence(indicators, timeline, observationRefs, evidenceChain, metricScopeId, reviewState) {
|
|
675
|
-
const events = uniqueTimelineEvents(timeline);
|
|
676
|
-
const userEvents = events.filter((event) => event.kind === 'user_message');
|
|
677
|
-
const metricUserEvents = userEvents.filter((event) => isUserInteractionMetricText(event.snippet ?? ''));
|
|
678
|
-
const refs = (matches) => matches.slice(0, 5).map(evidenceRefFromTimeline);
|
|
679
|
-
const findings = [];
|
|
680
|
-
const push = (code, level, count, evidenceRefs = []) => {
|
|
681
|
-
if (count <= 0)
|
|
682
|
-
return;
|
|
683
|
-
findings.push({ code, level, count, evidenceRefs: uniqueEvidenceRefs(evidenceRefs).slice(0, 5) });
|
|
684
|
-
};
|
|
685
|
-
push('high_observation_seen', 'attention', indicators.highObservationCount, observationRefs);
|
|
686
|
-
push('user_correction_seen', 'attention', indicators.userCorrectionCount, refs(metricUserEvents.filter((event) => metricIsActive(event, 'user_correction', hasUserCorrectionSignal(event.snippet ?? ''), reviewState, metricScopeId))));
|
|
687
|
-
push('user_interruption_seen', 'attention', indicators.userInterruptionCount, refs(metricUserEvents.filter((event) => metricIsActive(event, 'user_interruption', USER_INTERRUPTION_RE.test(event.snippet ?? ''), reviewState, metricScopeId))));
|
|
688
|
-
push('session_interrupted_seen', 'attention', indicators.sessionInterruptedCount, refs(sessionInterruptedEvents(events)));
|
|
689
|
-
push('negative_feedback_seen', 'attention', indicators.negativeFeedbackCount, refs(metricUserEvents.filter((event) => metricIsActive(event, 'negative_feedback', hasNegativeFeedbackSignal(event.snippet ?? ''), reviewState))));
|
|
690
|
-
push('tool_failure_seen', 'sample', indicators.toolFailureCount, refs(events.filter(isToolFailureEvent)));
|
|
691
|
-
push('medium_observation_seen', 'sample', indicators.mediumObservationCount, observationRefs);
|
|
692
|
-
push('hedging_seen', 'sample', indicators.hedgingCount, observationRefs);
|
|
693
|
-
push('explicit_marker_seen', 'sample', indicators.explicitMarkerCount, observationRefs);
|
|
694
|
-
push('hard_rule_seen', 'sample', indicators.hardRuleTextHitCount, refs(metricUserEvents.filter((event) => metricIsActive(event, 'hard_rule', hasUserHardRuleText(event.snippet ?? ''), reviewState, metricScopeId))));
|
|
695
|
-
push('positive_feedback_seen', 'normal', indicators.positiveFeedbackCount, refs(metricUserEvents.filter((event) => metricIsActive(event, 'positive_feedback', hasPositiveFeedbackSignal(event.snippet ?? ''), reviewState))));
|
|
696
|
-
push('user_goal_shift_seen', 'normal', indicators.userGoalShiftCount, refs(metricUserEvents.filter((event) => metricIsActive(event, 'user_goal_shift', hasUserGoalShiftSignal(event.snippet ?? ''), reviewState, metricScopeId))));
|
|
697
|
-
push('runtime_context_excluded', 'normal', evidenceChain.runtimeContextCount, evidenceChain.firstRuntimeContext ? [evidenceChain.firstRuntimeContext] : []);
|
|
698
|
-
push('skill_context_excluded', 'normal', evidenceChain.skillContextCount, evidenceChain.firstSkillContext ? [evidenceChain.firstSkillContext] : []);
|
|
699
|
-
if (findings.filter((finding) => finding.level !== 'normal').length === 0) {
|
|
700
|
-
findings.push({ code: 'no_priority_signal', level: 'normal', count: 1, evidenceRefs: [] });
|
|
701
|
-
}
|
|
702
|
-
return findings;
|
|
703
|
-
}
|
|
704
|
-
function assistiveInferenceForEvidence(indicators, evidenceChain, ruleFindings) {
|
|
705
|
-
const attentionFindings = ruleFindings.filter((finding) => finding.level === 'attention');
|
|
706
|
-
const sampleFindings = ruleFindings.filter((finding) => finding.level === 'sample');
|
|
707
|
-
const normalFindings = ruleFindings.filter((finding) => finding.level === 'normal');
|
|
708
|
-
const basisRuleCodes = unique([
|
|
709
|
-
...attentionFindings.map((finding) => finding.code),
|
|
710
|
-
...sampleFindings.map((finding) => finding.code),
|
|
711
|
-
...normalFindings
|
|
712
|
-
.filter((finding) => finding.code === 'positive_feedback_seen' || finding.code === 'hard_rule_seen' || finding.code === 'user_goal_shift_seen' || finding.code === 'no_priority_signal')
|
|
713
|
-
.map((finding) => finding.code),
|
|
714
|
-
]);
|
|
715
|
-
const cautionCodes = ['no_llm_judge', 'rule_only'];
|
|
716
|
-
if (evidenceChain.runtimeContextCount > 0)
|
|
717
|
-
cautionCodes.push('runtime_context_excluded');
|
|
718
|
-
if (evidenceChain.skillContextCount > 0)
|
|
719
|
-
cautionCodes.push('skill_context_excluded');
|
|
720
|
-
if (evidenceChain.userMessageCount === 0)
|
|
721
|
-
cautionCodes.push('no_human_user_message');
|
|
722
|
-
if (evidenceChain.toolUseCount + evidenceChain.toolResultCount + evidenceChain.assistantMessageCount > 24)
|
|
723
|
-
cautionCodes.push('limited_timeline_window');
|
|
724
|
-
let code;
|
|
725
|
-
if (attentionFindings.length > 0) {
|
|
726
|
-
code = 'review_recommended';
|
|
727
|
-
}
|
|
728
|
-
else if (sampleFindings.length > 0) {
|
|
729
|
-
code = 'sample_recommended';
|
|
730
|
-
}
|
|
731
|
-
else if (indicators.positiveFeedbackCount > 0) {
|
|
732
|
-
code = 'positive_signal_observed';
|
|
733
|
-
}
|
|
734
|
-
else if (indicators.userGoalShiftCount > 0) {
|
|
735
|
-
code = 'user_switched_topic_neutral';
|
|
736
|
-
}
|
|
737
|
-
else if (evidenceChain.userMessageCount === 0 && evidenceChain.toolUseCount === 0 && evidenceChain.observationCount === 0) {
|
|
738
|
-
code = 'insufficient_human_context';
|
|
739
|
-
}
|
|
740
|
-
else if (evidenceChain.userMessageCount === 0 && indicators.hardRuleTextHitCount === 0) {
|
|
741
|
-
code = 'insufficient_human_context';
|
|
742
|
-
}
|
|
743
|
-
else {
|
|
744
|
-
code = 'no_obvious_issue_from_rules';
|
|
745
|
-
}
|
|
746
|
-
const confidence = attentionFindings.length > 0 || indicators.positiveFeedbackCount > 0
|
|
747
|
-
? 'high'
|
|
748
|
-
: sampleFindings.length > 0 || indicators.userGoalShiftCount > 0 || evidenceChain.userMessageCount > 0 || evidenceChain.toolUseCount > 0
|
|
749
|
-
? 'medium'
|
|
750
|
-
: 'low';
|
|
751
|
-
const evidenceRefs = uniqueEvidenceRefs([
|
|
752
|
-
...attentionFindings.flatMap((finding) => finding.evidenceRefs),
|
|
753
|
-
...sampleFindings.flatMap((finding) => finding.evidenceRefs),
|
|
754
|
-
...(evidenceChain.firstUserMessage ? [evidenceChain.firstUserMessage] : []),
|
|
755
|
-
...(evidenceChain.firstToolUse ? [evidenceChain.firstToolUse] : []),
|
|
756
|
-
...(evidenceChain.firstToolFailure ? [evidenceChain.firstToolFailure] : []),
|
|
757
|
-
]).slice(0, 8);
|
|
758
|
-
return {
|
|
759
|
-
mode: 'deterministic_rules_only',
|
|
760
|
-
code,
|
|
761
|
-
confidence,
|
|
762
|
-
basisRuleCodes,
|
|
763
|
-
cautionCodes: unique(cautionCodes),
|
|
764
|
-
evidenceRefs,
|
|
765
|
-
};
|
|
766
|
-
}
|
|
767
|
-
function indicatorsForSegment(segment, relatedItems, timeline, metricScopeId, reviewState) {
|
|
768
|
-
const userRefs = timeline.filter((event) => event.kind === 'user_message');
|
|
769
|
-
const humanUserRefs = userRefs.filter((ref) => Boolean(ref.snippet) && !isSyntheticUserMessageText(ref.snippet ?? ''));
|
|
770
|
-
const interactionUserRefs = humanUserRefs.filter((ref) => isUserInteractionMetricText(ref.snippet ?? ''));
|
|
771
|
-
return {
|
|
772
|
-
userMessageCount: humanUserRefs.length,
|
|
773
|
-
userFollowUpCount: interactionUserRefs.reduce((sum, ref, index) => sum + (metricIsActive(ref, 'user_follow_up', index > 0 && !hasUserGoalShiftSignal(ref.snippet ?? ''), reviewState, metricScopeId) ? 1 : 0), 0),
|
|
774
|
-
userCorrectionCount: interactionUserRefs.reduce((sum, ref) => sum + metricCount(ref, 'user_correction', findUserCorrectionMatches(ref.snippet ?? '').length, reviewState, metricScopeId), 0),
|
|
775
|
-
userInterruptionCount: interactionUserRefs.reduce((sum, ref) => sum + (metricIsActive(ref, 'user_interruption', USER_INTERRUPTION_RE.test(ref.snippet ?? ''), reviewState, metricScopeId) ? 1 : 0), 0),
|
|
776
|
-
sessionInterruptedCount: sessionInterruptedEvents(timeline).length,
|
|
777
|
-
negativeFeedbackCount: interactionUserRefs.reduce((sum, ref) => sum + metricCount(ref, 'negative_feedback', findNegativeFeedbackMatches(ref.snippet ?? '').length, reviewState), 0),
|
|
778
|
-
positiveFeedbackCount: interactionUserRefs.reduce((sum, ref) => sum + metricCount(ref, 'positive_feedback', findPositiveFeedbackMatches(ref.snippet ?? '').length, reviewState), 0),
|
|
779
|
-
userGoalShiftCount: interactionUserRefs.reduce((sum, ref) => sum + metricCount(ref, 'user_goal_shift', findUserGoalShiftMatches(ref.snippet ?? '').length, reviewState, metricScopeId), 0),
|
|
780
|
-
hardRuleTextHitCount: interactionUserRefs.reduce((sum, ref) => sum + (metricIsActive(ref, 'hard_rule', hasUserHardRuleText(ref.snippet ?? ''), reviewState, metricScopeId) ? 1 : 0), 0),
|
|
781
|
-
assistantDeliverySignalCount: timeline.filter(isAssistantDeliveryEvent).length,
|
|
782
|
-
deliverableArtifactSignalCount: timeline.reduce((sum, ref) => sum + (metricIsActive(ref, 'deliverable_artifact', isAssistantDeliverableArtifactEvent(ref), reviewState) ? 1 : 0), 0),
|
|
783
|
-
selfCorrectionCount: timeline.reduce((sum, ref) => sum + (metricIsActive(ref, 'self_correction', hasSelfCorrectionSignal(ref), reviewState) ? 1 : 0), 0),
|
|
784
|
-
repeatedExecutionCount: timeline.reduce((sum, ref) => sum + (metricIsActive(ref, 'repeated_execution', hasRepeatedExecutionSignal(ref), reviewState) ? 1 : 0), 0),
|
|
785
|
-
toolCallCount: segment.metrics.numToolCalls,
|
|
786
|
-
toolFailureCount: Math.max(segment.metrics.numToolFailures, timeline.filter(isToolFailureEvent).length),
|
|
787
|
-
highObservationCount: relatedItems.filter((item) => item.severity === 'high').length,
|
|
788
|
-
mediumObservationCount: relatedItems.filter((item) => item.severity === 'medium').length,
|
|
789
|
-
hedgingCount: relatedItems.filter((item) => item.signalType === 'hedging').reduce((sum, item) => sum + item.occurrences, 0),
|
|
790
|
-
explicitMarkerCount: relatedItems.filter((item) => item.signalType === 'explicit_marker').reduce((sum, item) => sum + item.occurrences, 0),
|
|
791
|
-
};
|
|
792
|
-
}
|
|
793
|
-
function isToolFailureEvent(event) {
|
|
794
|
-
return event.kind === 'tool_result' && (event.isError === true || isToolResultFailureText(event.fullText ?? event.snippet ?? ''));
|
|
795
|
-
}
|
|
796
|
-
function sessionInterruptedEvents(timeline) {
|
|
797
|
-
const events = uniqueTimelineEvents(timeline).sort(compareTimelineEvents);
|
|
798
|
-
const interrupted = [];
|
|
799
|
-
for (let index = 0; index < events.length; index += 1) {
|
|
800
|
-
const event = events[index];
|
|
801
|
-
const text = `${event.label ?? ''}\n${event.snippet ?? ''}\n${event.fullText ?? ''}`;
|
|
802
|
-
if (hasAssistantTurnFailedText(text)) {
|
|
803
|
-
interrupted.push(event);
|
|
804
|
-
continue;
|
|
805
|
-
}
|
|
806
|
-
if (/^session[._-]ended$/i.test(event.label ?? '')) {
|
|
807
|
-
const next = events.slice(index + 1).find((candidate) => /^session[._-]started$/i.test(candidate.label ?? ''));
|
|
808
|
-
if (next)
|
|
809
|
-
interrupted.push(event);
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
return uniqueTimelineEvents(interrupted);
|
|
813
|
-
}
|
|
814
|
-
function metricIsActive(ref, metricKey, ruleDetected, reviewState, metricScopeId) {
|
|
815
|
-
const verdict = observationMetricAnnotationVerdict(reviewState, { ...ref, metricScopeId }, metricKey);
|
|
816
|
-
if (verdict === 'confirmed')
|
|
817
|
-
return true;
|
|
818
|
-
if (verdict === 'rejected')
|
|
819
|
-
return false;
|
|
820
|
-
return ruleDetected;
|
|
821
|
-
}
|
|
822
|
-
function metricCount(ref, metricKey, ruleCount, reviewState, metricScopeId) {
|
|
823
|
-
const verdict = observationMetricAnnotationVerdict(reviewState, { ...ref, metricScopeId }, metricKey);
|
|
824
|
-
if (verdict === 'confirmed')
|
|
825
|
-
return Math.max(1, ruleCount);
|
|
826
|
-
if (verdict === 'rejected')
|
|
827
|
-
return 0;
|
|
828
|
-
return ruleCount;
|
|
829
|
-
}
|
|
830
|
-
function summarizeExperienceSessions(invocations, sessionGroupsByKey, generatedAt, reviewState) {
|
|
831
|
-
const byKey = new Map();
|
|
832
|
-
for (const invocation of invocations) {
|
|
833
|
-
const key = `${invocation.skillName}\u0000${invocation.sessionGroupKey}`;
|
|
834
|
-
const group = byKey.get(key) ?? [];
|
|
835
|
-
group.push(invocation);
|
|
836
|
-
byKey.set(key, group);
|
|
837
|
-
}
|
|
838
|
-
return Array.from(byKey.values()).map((group) => {
|
|
839
|
-
const first = group[0];
|
|
840
|
-
const indicators = sumIndicators(group.map((invocation) => invocation.indicators));
|
|
841
|
-
const relatedObservationIds = unique(group.flatMap((invocation) => invocation.relatedObservationIds));
|
|
842
|
-
const reviewBasisCodes = basisCodesForIndicators(indicators);
|
|
843
|
-
const reviewPriorityScore = scoreForIndicators(indicators);
|
|
844
|
-
const timeline = uniqueTimelineEvents(group.flatMap((invocation) => invocation.timeline)).sort(compareTimelineEvents);
|
|
845
|
-
const sessionGroup = sessionGroupsByKey.get(first.sessionGroupKey) ?? [];
|
|
846
|
-
const sourceSessionStartTimestamp = minString(sessionGroup.map((session) => session.startTimestamp));
|
|
847
|
-
const sourceSessionEndTimestamp = maxString(sessionGroup.map((session) => session.endTimestamp));
|
|
848
|
-
const timelineTree = sessionGroup.length > 0 ? buildSessionTimelineTree(first.sessionId, sessionGroup) : undefined;
|
|
849
|
-
const fullSessionTimeline = timelineTree
|
|
850
|
-
? uniqueTimelineEvents([
|
|
851
|
-
...timelineTree.main,
|
|
852
|
-
...timelineTree.branches.flatMap((branch) => branch.events),
|
|
853
|
-
]).sort(compareTimelineEvents)
|
|
854
|
-
: timeline;
|
|
855
|
-
const fullSessionEventCount = fullSessionTimeline.length;
|
|
856
|
-
const previewEvents = timeline.slice(0, TIMELINE_PREVIEW_EVENT_LIMIT);
|
|
857
|
-
const previewIndexes = previewEvents
|
|
858
|
-
.map((event) => event.messageIndex)
|
|
859
|
-
.filter((index) => typeof index === 'number');
|
|
860
|
-
const groupStartRecordIndex = minDefined(group.map((invocation) => minDefined(invocation.timeline.map((event) => event.messageIndex))));
|
|
861
|
-
const groupEndRecordIndex = maxDefined(group.map((invocation) => maxDefined(invocation.timeline.map((event) => event.messageIndex))));
|
|
862
|
-
const previewStartRecordIndex = minDefined(previewIndexes);
|
|
863
|
-
const previewEndRecordIndex = maxDefined(previewIndexes);
|
|
864
|
-
const fullSessionIndexes = fullSessionTimeline
|
|
865
|
-
.map((event) => event.messageIndex)
|
|
866
|
-
.filter((index) => typeof index === 'number');
|
|
867
|
-
const sessionStartRecordIndex = minDefined(fullSessionIndexes) ?? 0;
|
|
868
|
-
const sessionEndRecordIndex = maxDefined(fullSessionIndexes) ?? Math.max(0, (sessionGroup[0]?.records.length ?? 1) - 1);
|
|
869
|
-
const omittedBeforeCount = previewStartRecordIndex === undefined
|
|
870
|
-
? 0
|
|
871
|
-
: fullSessionTimeline.filter((event) => typeof event.messageIndex === 'number' && event.messageIndex < previewStartRecordIndex).length;
|
|
872
|
-
const omittedAfterCount = previewEndRecordIndex === undefined
|
|
873
|
-
? 0
|
|
874
|
-
: fullSessionTimeline.filter((event) => typeof event.messageIndex === 'number' && event.messageIndex > previewEndRecordIndex).length;
|
|
875
|
-
const observationRefs = uniqueEvidenceRefs(group.flatMap((invocation) => invocation.evidenceRefs.filter((ref) => ref.kind === 'observation')));
|
|
876
|
-
const evidenceChain = evidenceChainForTimeline(timeline, observationRefs);
|
|
877
|
-
const metricScopeId = hashParts('session', first.skillName, first.sessionGroupKey);
|
|
878
|
-
const ruleFindings = ruleFindingsForEvidence(indicators, timeline, observationRefs, evidenceChain, metricScopeId);
|
|
879
|
-
const assistiveInference = assistiveInferenceForEvidence(indicators, evidenceChain, ruleFindings);
|
|
880
|
-
const problemPatterns = mergeExperienceProblemPatterns(group.flatMap((invocation) => invocation.problemPatterns));
|
|
881
|
-
const storyInvocations = invocations.filter((invocation) => invocation.sessionGroupKey === first.sessionGroupKey);
|
|
882
|
-
const baseSession = {
|
|
883
|
-
id: metricScopeId,
|
|
884
|
-
skillName: first.skillName,
|
|
885
|
-
sessionId: first.sessionId,
|
|
886
|
-
sourceTrace: first.sourceTrace,
|
|
887
|
-
sourceKind: first.sourceKind,
|
|
888
|
-
entrypoint: first.entrypoint,
|
|
889
|
-
sourceMetadata: mergeSourceMetadata(group.map((invocation) => invocation.sourceMetadata)),
|
|
890
|
-
cwd: first.cwd,
|
|
891
|
-
sourceSessionStartTimestamp,
|
|
892
|
-
sourceSessionEndTimestamp,
|
|
893
|
-
sourceSessionDurationMs: durationMsBetween(sourceSessionStartTimestamp, sourceSessionEndTimestamp),
|
|
894
|
-
startTimestamp: group.reduce((min, invocation) => invocation.startTimestamp < min ? invocation.startTimestamp : min, first.startTimestamp),
|
|
895
|
-
endTimestamp: group.reduce((max, invocation) => invocation.endTimestamp > max ? invocation.endTimestamp : max, first.endTimestamp),
|
|
896
|
-
invocationIds: group.map((invocation) => invocation.id),
|
|
897
|
-
goalSliceIds: unique(group.map((invocation) => invocation.goalSliceId)),
|
|
898
|
-
reviewPriority: priorityForScore(reviewPriorityScore),
|
|
899
|
-
reviewPriorityScore,
|
|
900
|
-
reviewBasisCodes,
|
|
901
|
-
indicators,
|
|
902
|
-
evidenceChain,
|
|
903
|
-
ruleFindings,
|
|
904
|
-
assistiveInference,
|
|
905
|
-
problemPatterns,
|
|
906
|
-
relatedObservationIds,
|
|
907
|
-
timelinePreview: previewEvents,
|
|
908
|
-
fullSessionTimeline,
|
|
909
|
-
timelineTree,
|
|
910
|
-
timelineScope: {
|
|
911
|
-
mode: 'skill_segment_window',
|
|
912
|
-
segmentStartRecordIndex: groupStartRecordIndex,
|
|
913
|
-
segmentEndRecordIndex: groupEndRecordIndex,
|
|
914
|
-
previewStartRecordIndex,
|
|
915
|
-
previewEndRecordIndex,
|
|
916
|
-
sessionStartRecordIndex,
|
|
917
|
-
sessionEndRecordIndex,
|
|
918
|
-
previewEventCount: previewEvents.length,
|
|
919
|
-
fullSessionEventCount,
|
|
920
|
-
truncated: timeline.length > previewEvents.length || omittedBeforeCount > 0 || omittedAfterCount > 0,
|
|
921
|
-
omittedBeforeCount,
|
|
922
|
-
omittedAfterCount,
|
|
923
|
-
},
|
|
924
|
-
attributionSources: unique(group.map((invocation) => invocation.attribution.source).filter(Boolean)).sort(),
|
|
925
|
-
pluginNames: unique(group.map((invocation) => invocation.attribution.pluginName).filter((value) => Boolean(value))).sort(),
|
|
926
|
-
rawSkillRefs: unique(group.map((invocation) => invocation.attribution.rawSkillRef).filter((value) => Boolean(value))).sort(),
|
|
927
|
-
commandNames: unique(group.map((invocation) => invocation.attribution.commandName).filter((value) => Boolean(value))).sort(),
|
|
928
|
-
};
|
|
929
|
-
const sessionStory = buildSessionStory(baseSession, storyInvocations);
|
|
930
|
-
const sessionWithStory = {
|
|
931
|
-
...baseSession,
|
|
932
|
-
sessionStory,
|
|
933
|
-
};
|
|
934
|
-
const reviewerReport = buildReviewerReport(sessionWithStory, group, generatedAt, reviewState, storyInvocations, sessionStory);
|
|
935
|
-
return {
|
|
936
|
-
...sessionWithStory,
|
|
937
|
-
reviewPriority: priorityForReviewerFindings(sessionWithStory, reviewerReport.findings),
|
|
938
|
-
reviewerReport,
|
|
939
|
-
};
|
|
940
|
-
}).sort((a, b) => {
|
|
941
|
-
const priorityDiff = experiencePriorityRank(b.reviewPriority) - experiencePriorityRank(a.reviewPriority);
|
|
942
|
-
if (priorityDiff !== 0)
|
|
943
|
-
return priorityDiff;
|
|
944
|
-
if (b.reviewPriorityScore !== a.reviewPriorityScore)
|
|
945
|
-
return b.reviewPriorityScore - a.reviewPriorityScore;
|
|
946
|
-
return b.endTimestamp.localeCompare(a.endTimestamp);
|
|
947
|
-
});
|
|
948
|
-
}
|
|
949
|
-
function experiencePriorityRank(priority) {
|
|
950
|
-
if (priority === 'review_first')
|
|
951
|
-
return 2;
|
|
952
|
-
if (priority === 'sample_review')
|
|
953
|
-
return 1;
|
|
954
|
-
return 0;
|
|
955
|
-
}
|
|
956
|
-
const REVIEWER_REPORT_RULE_VERSION = 'reviewer-report.v1';
|
|
957
|
-
function buildReviewerReport(session, invocations, generatedAt, reviewState, storyInvocations = invocations, sessionStory = buildSessionStory(session, storyInvocations)) {
|
|
958
|
-
const indicators = session.indicators;
|
|
959
|
-
const scopeReasons = reviewerScopeReasonCodes(session);
|
|
960
|
-
const scopeKind = scopeReasons.length === 0 ? 'single_skill_single_goal' : 'degraded_complex';
|
|
961
|
-
const findings = reviewerFindingsForSession(session, reviewState);
|
|
962
|
-
const attentionCount = findings.filter((finding) => finding.level === 'attention').length;
|
|
963
|
-
const possibleFalsePositiveCount = findings.filter((finding) => finding.level === 'possible_false_positive').length;
|
|
964
|
-
const tokenUsage = sumTokenUsage(invocations);
|
|
965
|
-
const title = reviewerTitle(session, attentionCount, possibleFalsePositiveCount);
|
|
966
|
-
const expectedToolCheck = expectedToolCheckForSession(session);
|
|
967
|
-
const traceLinks = uniqueEvidenceRefs([
|
|
968
|
-
...(session.evidenceChain.firstUserMessage ? [session.evidenceChain.firstUserMessage] : []),
|
|
969
|
-
...(session.evidenceChain.firstToolUse ? [session.evidenceChain.firstToolUse] : []),
|
|
970
|
-
...(session.evidenceChain.firstToolFailure ? [session.evidenceChain.firstToolFailure] : []),
|
|
971
|
-
...(session.evidenceChain.lastAssistantMessage ? [session.evidenceChain.lastAssistantMessage] : []),
|
|
972
|
-
...findings.flatMap((finding) => finding.evidenceRefs),
|
|
973
|
-
]).slice(0, 10);
|
|
974
|
-
return {
|
|
975
|
-
schemaVersion: 1,
|
|
976
|
-
mode: 'deterministic_session_story',
|
|
977
|
-
generatedAt,
|
|
978
|
-
title,
|
|
979
|
-
summary: reviewerSummary(session, scopeKind, attentionCount, possibleFalsePositiveCount),
|
|
980
|
-
scope: {
|
|
981
|
-
kind: scopeKind,
|
|
982
|
-
reasonCodes: scopeReasons,
|
|
983
|
-
},
|
|
984
|
-
chainSteps: [
|
|
985
|
-
reviewerStep(1, '用户期待', userGoalStepText(session), session.evidenceChain.firstUserMessage ? 'ok' : 'unknown', session.evidenceChain.firstUserMessage ? [session.evidenceChain.firstUserMessage] : []),
|
|
986
|
-
reviewerStep(2, '选择能力', skillSelectionStepText(session), 'ok', [session.evidenceChain.firstSkillContext, session.evidenceChain.firstToolUse].filter((ref) => Boolean(ref))),
|
|
987
|
-
reviewerStep(3, '执行流程', executionStepText(session, expectedToolCheck), executionStepStatus(session, expectedToolCheck), session.evidenceChain.firstToolUse ? [session.evidenceChain.firstToolUse] : []),
|
|
988
|
-
reviewerStep(4, '结果 / 产物', deliveryStepText(session), indicators.assistantDeliverySignalCount > 0 ? 'ok' : 'unknown', session.evidenceChain.lastAssistantMessage ? [session.evidenceChain.lastAssistantMessage] : []),
|
|
989
|
-
reviewerStep(5, '用户反馈', userFeedbackStepText(session), userFeedbackStepStatus(session), userFeedbackEvidenceRefs(session)),
|
|
990
|
-
],
|
|
991
|
-
findings,
|
|
992
|
-
oneLookMetrics: {
|
|
993
|
-
toolCallCount: indicators.toolCallCount,
|
|
994
|
-
toolFailureCount: indicators.toolFailureCount,
|
|
995
|
-
userMessageCount: indicators.userMessageCount,
|
|
996
|
-
userFollowUpCount: indicators.userFollowUpCount,
|
|
997
|
-
assistantDeliverySignalCount: indicators.assistantDeliverySignalCount,
|
|
998
|
-
deliverableArtifactSignalCount: indicators.deliverableArtifactSignalCount,
|
|
999
|
-
assistantProgressUpdateCount: assistantProgressUpdateEvents(session).length,
|
|
1000
|
-
selfCorrectionCount: indicators.selfCorrectionCount,
|
|
1001
|
-
repeatedExecutionCount: indicators.repeatedExecutionCount,
|
|
1002
|
-
finalDeliverySignalCount: assistantFinalDeliveryEvents(session).length,
|
|
1003
|
-
traceEventCount: session.fullSessionTimeline.length || session.timelinePreview.length,
|
|
1004
|
-
tokenUsage: {
|
|
1005
|
-
...tokenUsage,
|
|
1006
|
-
attribution: 'skill_segment',
|
|
1007
|
-
},
|
|
1008
|
-
},
|
|
1009
|
-
sessionStory,
|
|
1010
|
-
authorSuggestions: reviewerAuthorSuggestions(session, findings),
|
|
1011
|
-
traceLinks,
|
|
1012
|
-
};
|
|
1013
|
-
}
|
|
1014
|
-
function buildSessionStory(session, invocations) {
|
|
1015
|
-
const nodes = [];
|
|
1016
|
-
const push = (kind, label, status, text, evidenceRefs = []) => {
|
|
1017
|
-
nodes.push({
|
|
1018
|
-
id: hashParts('session-story-node', session.id, kind, String(nodes.length), text),
|
|
1019
|
-
order: nodes.length + 1,
|
|
1020
|
-
kind,
|
|
1021
|
-
label,
|
|
1022
|
-
status,
|
|
1023
|
-
text,
|
|
1024
|
-
evidenceRefs: uniqueEvidenceRefs(evidenceRefs).slice(0, 5),
|
|
1025
|
-
});
|
|
1026
|
-
return nodes[nodes.length - 1];
|
|
1027
|
-
};
|
|
1028
|
-
const goalSlices = sessionStoryGoalSlices(session, invocations);
|
|
1029
|
-
const subagentDispatches = sessionStorySubagentDispatches(session);
|
|
1030
|
-
const skillLinks = sessionStorySkillLinks(session, invocations);
|
|
1031
|
-
const progressUpdates = assistantProgressUpdateEvents(session);
|
|
1032
|
-
const finalDeliveries = assistantFinalDeliveryEvents(session);
|
|
1033
|
-
const userGoalNode = push('user_goal', '用户提出目标', session.evidenceChain.firstUserMessage ? 'ok' : 'unknown', goalSlices.length > 1
|
|
1034
|
-
? `识别到 ${goalSlices.length} 个目标段:${goalSlices.map((goal) => goal.inferredUserGoal ?? '未提取到明确目标').slice(0, 3).join(';')}${goalSlices.length > 3 ? ';...' : ''}`
|
|
1035
|
-
: session.evidenceChain.firstUserMessage?.snippet
|
|
1036
|
-
? `用户目标:${session.evidenceChain.firstUserMessage.snippet}`
|
|
1037
|
-
: '没有看到明确人工用户目标;当前只能按运行证据还原链路。', session.evidenceChain.firstUserMessage ? [session.evidenceChain.firstUserMessage] : []);
|
|
1038
|
-
const roleSummary = skillLinks.map((link) => `${link.skillName}:${skillRoleLabel(link.role)}`).join(';');
|
|
1039
|
-
const invocationText = skillLinks.length > 1
|
|
1040
|
-
? `本次链路识别到 ${skillLinks.length} 个能力:${roleSummary}。`
|
|
1041
|
-
: skillLinks[0]
|
|
1042
|
-
? `本次使用能力:${skillLinks[0].skillName},角色判断:${skillRoleLabel(skillLinks[0].role)}。`
|
|
1043
|
-
: `本次使用能力:${session.skillName}。`;
|
|
1044
|
-
const invocationNode = push('skill_invocation', '能力介入', 'ok', invocationText, uniqueEvidenceRefs([session.evidenceChain.firstSkillContext, session.evidenceChain.firstToolUse].filter((ref) => Boolean(ref))));
|
|
1045
|
-
let subagentNode;
|
|
1046
|
-
if (subagentDispatches.length > 0) {
|
|
1047
|
-
subagentNode = push('subagent_branch', '分支 / 子任务', 'unknown', `检测到 ${subagentDispatches.length} 条分支或子任务执行线;主线和分支已单独列出,仍需要结合原文确认真实委派关系。`, subagentDispatches.flatMap((dispatch) => dispatch.evidenceRefs.slice(0, 1)));
|
|
1048
|
-
}
|
|
1049
|
-
const executionNode = push('tool_execution', '执行过程', session.indicators.toolFailureCount > 0 ? 'attention' : session.indicators.toolCallCount > 0 ? 'ok' : 'unknown', session.indicators.toolCallCount > 0
|
|
1050
|
-
? `执行中看到 ${session.indicators.toolCallCount} 次工具调用${session.indicators.toolFailureCount > 0 ? `,其中失败 ${session.indicators.toolFailureCount} 次` : ''}。`
|
|
1051
|
-
: '没有看到明确工具调用;只能根据消息上下文复盘。', uniqueEvidenceRefs([
|
|
1052
|
-
session.evidenceChain.firstToolUse,
|
|
1053
|
-
session.evidenceChain.firstToolFailure,
|
|
1054
|
-
].filter((ref) => Boolean(ref))));
|
|
1055
|
-
const deliveryNode = push('delivery', '交付产物', finalDeliveries.length > 0 ? 'ok' : 'attention', deliveryStepText(session), uniqueEvidenceRefs([
|
|
1056
|
-
...finalDeliveries.slice(-2).map(evidenceRefFromTimeline),
|
|
1057
|
-
...progressUpdates.slice(-2).map(evidenceRefFromTimeline),
|
|
1058
|
-
session.evidenceChain.lastAssistantMessage,
|
|
1059
|
-
].filter((ref) => Boolean(ref))));
|
|
1060
|
-
const feedbackNode = push('user_feedback', '用户反馈', userFeedbackStepStatus(session), userFeedbackStepText(session), userFeedbackEvidenceRefs(session));
|
|
1061
|
-
if (session.indicators.userGoalShiftCount > 0) {
|
|
1062
|
-
push('goal_shift', '目标切换', 'unknown', `用户中途切换了 ${session.indicators.userGoalShiftCount} 次目标,后续诉求可能不属于当前 skill。`, userFeedbackEvidenceRefs(session));
|
|
1063
|
-
}
|
|
1064
|
-
const goalChecklistItems = checklistItemsForAnswer(session, 'goal_satisfaction');
|
|
1065
|
-
const declaredBehaviorChecklistItems = checklistItemsForAnswer(session, 'declared_behavior_fit');
|
|
1066
|
-
const userFeelingChecklistItems = checklistItemsForAnswer(session, 'user_feeling');
|
|
1067
|
-
const answers = [
|
|
1068
|
-
sessionStoryAnswer('goal_satisfaction', '用户目标有没有被满足', goalChecklistItems, [
|
|
1069
|
-
session.evidenceChain.firstUserMessage,
|
|
1070
|
-
session.evidenceChain.lastAssistantMessage,
|
|
1071
|
-
...userFeedbackEvidenceRefs(session),
|
|
1072
|
-
]),
|
|
1073
|
-
sessionStoryAnswer('declared_behavior_fit', '行为是否符合能力用途', declaredBehaviorChecklistItems, [
|
|
1074
|
-
session.evidenceChain.firstSkillContext,
|
|
1075
|
-
session.evidenceChain.firstToolUse,
|
|
1076
|
-
session.evidenceChain.firstToolFailure,
|
|
1077
|
-
]),
|
|
1078
|
-
sessionStoryAnswer('user_feeling', '用户是否觉得有用或绕路', userFeelingChecklistItems, userFeedbackEvidenceRefs(session)),
|
|
1079
|
-
];
|
|
1080
|
-
const summary = answers.some((answer) => answer.status === 'degraded')
|
|
1081
|
-
? '这次数据本身有可信度问题(比如 skill 没真的被加载),先确认数据再下判断。'
|
|
1082
|
-
: answers.some((answer) => answer.status === 'attention')
|
|
1083
|
-
? '这次有几条需要看一眼的事项,从红色标记的事实和原文开始看。'
|
|
1084
|
-
: answers.every((answer) => answer.status === 'ok')
|
|
1085
|
-
? '这次从目标、执行到反馈都没有明显异常,进入常规抽样。'
|
|
1086
|
-
: '这次链路已按语义节点展开,但部分结论仍需要人工结合原文判断。';
|
|
1087
|
-
return {
|
|
1088
|
-
schemaVersion: 1,
|
|
1089
|
-
summary,
|
|
1090
|
-
invocationCount: invocations.length,
|
|
1091
|
-
goalSliceCount: session.goalSliceIds.length,
|
|
1092
|
-
branchCount: subagentDispatches.length,
|
|
1093
|
-
progressUpdateCount: progressUpdates.length,
|
|
1094
|
-
finalDeliverySignalCount: finalDeliveries.length,
|
|
1095
|
-
mainlineNodeIds: [
|
|
1096
|
-
userGoalNode.id,
|
|
1097
|
-
invocationNode.id,
|
|
1098
|
-
...(subagentNode ? [subagentNode.id] : []),
|
|
1099
|
-
executionNode.id,
|
|
1100
|
-
deliveryNode.id,
|
|
1101
|
-
feedbackNode.id,
|
|
1102
|
-
],
|
|
1103
|
-
goalSlices,
|
|
1104
|
-
subagentDispatches,
|
|
1105
|
-
skillLinks,
|
|
1106
|
-
graph: sessionStoryGraph(nodes, skillLinks),
|
|
1107
|
-
nodes,
|
|
1108
|
-
answers,
|
|
1109
|
-
};
|
|
1110
|
-
}
|
|
1111
|
-
function assistantFinalDeliveryEvents(session) {
|
|
1112
|
-
return (session.fullSessionTimeline.length > 0 ? session.fullSessionTimeline : session.timelinePreview)
|
|
1113
|
-
.filter(isAssistantDeliveryEvent);
|
|
1114
|
-
}
|
|
1115
|
-
function assistantProgressUpdateEvents(session) {
|
|
1116
|
-
return (session.fullSessionTimeline.length > 0 ? session.fullSessionTimeline : session.timelinePreview)
|
|
1117
|
-
.filter(isAssistantProgressUpdateEvent);
|
|
1118
|
-
}
|
|
1119
|
-
function sessionStoryGoalSlices(session, invocations) {
|
|
1120
|
-
const byId = new Map();
|
|
1121
|
-
for (const invocation of invocations) {
|
|
1122
|
-
const group = byId.get(invocation.goalSliceId) ?? [];
|
|
1123
|
-
group.push(invocation);
|
|
1124
|
-
byId.set(invocation.goalSliceId, group);
|
|
1125
|
-
}
|
|
1126
|
-
return Array.from(byId.entries()).map(([id, group], index) => {
|
|
1127
|
-
const timeline = uniqueTimelineEvents(group.flatMap((invocation) => invocation.timeline)).sort(compareTimelineEvents);
|
|
1128
|
-
const userEvents = timeline.filter((event) => event.kind === 'user_message');
|
|
1129
|
-
const startTimestamp = minString(group.map((invocation) => invocation.startTimestamp)) ?? session.startTimestamp;
|
|
1130
|
-
const endTimestamp = maxString(group.map((invocation) => invocation.endTimestamp)) ?? session.endTimestamp;
|
|
1131
|
-
const hasGoalShift = userEvents.some((event) => hasUserGoalShiftSignal(event.snippet ?? ''));
|
|
1132
|
-
const reasonCode = hasGoalShift
|
|
1133
|
-
? 'explicit_user_goal_shift'
|
|
1134
|
-
: group.length > 1 ? 'skill_segment_boundary' : 'default_session_slice';
|
|
1135
|
-
return {
|
|
1136
|
-
id,
|
|
1137
|
-
order: index + 1,
|
|
1138
|
-
skillNames: unique(group.map((invocation) => invocation.skillName)).sort(),
|
|
1139
|
-
startTimestamp,
|
|
1140
|
-
endTimestamp,
|
|
1141
|
-
reasonCode,
|
|
1142
|
-
inferredUserGoal: inferUserGoal(userEvents),
|
|
1143
|
-
evidenceRefs: userEvents.slice(0, 3).map(evidenceRefFromTimeline),
|
|
1144
|
-
};
|
|
1145
|
-
}).sort((a, b) => a.startTimestamp.localeCompare(b.startTimestamp));
|
|
1146
|
-
}
|
|
1147
|
-
function sessionStorySubagentDispatches(session) {
|
|
1148
|
-
const branches = session.timelineTree?.branches ?? [];
|
|
1149
|
-
return branches.map((branch, index) => ({
|
|
1150
|
-
id: hashParts('session-story-dispatch', session.id, branch.id),
|
|
1151
|
-
order: index + 1,
|
|
1152
|
-
branchId: branch.id,
|
|
1153
|
-
label: branch.label,
|
|
1154
|
-
sourceTrace: branch.sourceTrace,
|
|
1155
|
-
attachTo: branch.attachTo ? {
|
|
1156
|
-
messageIndex: branch.attachTo.messageIndex,
|
|
1157
|
-
toolUseId: branch.attachTo.toolUseId,
|
|
1158
|
-
label: branch.attachTo.label,
|
|
1159
|
-
} : undefined,
|
|
1160
|
-
eventCount: branch.events.length,
|
|
1161
|
-
evidenceRefs: branch.events.slice(0, 3).map(evidenceRefFromTimeline),
|
|
1162
|
-
}));
|
|
1163
|
-
}
|
|
1164
|
-
function sessionStorySkillLinks(session, invocations) {
|
|
1165
|
-
const bySkill = new Map();
|
|
1166
|
-
for (const invocation of invocations) {
|
|
1167
|
-
const group = bySkill.get(invocation.skillName) ?? [];
|
|
1168
|
-
group.push(invocation);
|
|
1169
|
-
bySkill.set(invocation.skillName, group);
|
|
1170
|
-
}
|
|
1171
|
-
return Array.from(bySkill.entries()).map(([skillName, group], index) => {
|
|
1172
|
-
const role = inferSkillRole(group, invocations, session);
|
|
1173
|
-
return {
|
|
1174
|
-
id: hashParts('session-story-skill-link', session.id, skillName),
|
|
1175
|
-
order: index + 1,
|
|
1176
|
-
skillName,
|
|
1177
|
-
role,
|
|
1178
|
-
invocationIds: group.map((invocation) => invocation.id),
|
|
1179
|
-
goalSliceIds: unique(group.map((invocation) => invocation.goalSliceId)),
|
|
1180
|
-
evidenceRefs: uniqueEvidenceRefs(group.flatMap((invocation) => [
|
|
1181
|
-
invocation.evidenceChain.firstSkillContext,
|
|
1182
|
-
invocation.evidenceChain.firstToolUse,
|
|
1183
|
-
...routingEvidenceEvents(invocation).map(evidenceRefFromTimeline),
|
|
1184
|
-
].filter((ref) => Boolean(ref)))).slice(0, 5),
|
|
1185
|
-
};
|
|
1186
|
-
}).sort((a, b) => a.order - b.order);
|
|
1187
|
-
}
|
|
1188
|
-
function inferSkillRole(group, allInvocations, session) {
|
|
1189
|
-
const hasRoutingSignal = group.some((invocation) => routingEvidenceEvents(invocation).length > 0);
|
|
1190
|
-
const hasBranchDispatch = (session.timelineTree?.branches.length ?? 0) > 0 && group.some((invocation) => invocation.timeline.some((event) => event.kind === 'tool_use' && /^(Task|Agent|Skill)$/i.test(event.toolName ?? '')));
|
|
1191
|
-
const hasExecutionSignal = group.some((invocation) => invocation.timeline.some((event) => event.kind === 'tool_use' && !/^(Task|Agent|Skill)$/i.test(event.toolName ?? '')));
|
|
1192
|
-
if ((hasRoutingSignal || hasBranchDispatch) && allInvocations.length > group.length)
|
|
1193
|
-
return hasExecutionSignal ? 'mixed' : 'router';
|
|
1194
|
-
if (hasRoutingSignal || hasBranchDispatch)
|
|
1195
|
-
return 'router';
|
|
1196
|
-
if (hasExecutionSignal)
|
|
1197
|
-
return 'executor';
|
|
1198
|
-
return 'unknown';
|
|
1199
|
-
}
|
|
1200
|
-
function routingEvidenceEvents(invocation) {
|
|
1201
|
-
return invocation.timeline.filter((event) => {
|
|
1202
|
-
if (event.kind !== 'assistant_message' && event.kind !== 'tool_use')
|
|
1203
|
-
return false;
|
|
1204
|
-
const text = event.fullText ?? event.snippet ?? '';
|
|
1205
|
-
return /子\s*Claude|subagent|子任务|分发|委派|调用.+skill|走\s*`?[\w-]+`?\s*skill|\/consult|task-runner/i.test(text);
|
|
1206
|
-
}).slice(0, 3);
|
|
1207
|
-
}
|
|
1208
|
-
function skillRoleLabel(role) {
|
|
1209
|
-
if (role === 'router')
|
|
1210
|
-
return '路由';
|
|
1211
|
-
if (role === 'executor')
|
|
1212
|
-
return '执行';
|
|
1213
|
-
if (role === 'mixed')
|
|
1214
|
-
return '路由 + 执行';
|
|
1215
|
-
return '未确认';
|
|
1216
|
-
}
|
|
1217
|
-
function sessionStoryGraph(nodes, skillLinks) {
|
|
1218
|
-
const graphNodes = nodes.map((node) => ({
|
|
1219
|
-
id: node.id,
|
|
1220
|
-
label: node.label,
|
|
1221
|
-
kind: node.kind,
|
|
1222
|
-
status: node.status,
|
|
1223
|
-
detailNodeId: node.id,
|
|
1224
|
-
}));
|
|
1225
|
-
for (const link of skillLinks) {
|
|
1226
|
-
graphNodes.push({
|
|
1227
|
-
id: link.id,
|
|
1228
|
-
label: `${link.skillName}(${skillRoleLabel(link.role)})`,
|
|
1229
|
-
kind: 'skill_invocation',
|
|
1230
|
-
status: link.role === 'unknown' ? 'unknown' : 'ok',
|
|
1231
|
-
role: link.role,
|
|
1232
|
-
});
|
|
1233
|
-
}
|
|
1234
|
-
const edges = [];
|
|
1235
|
-
for (let index = 1; index < nodes.length; index += 1) {
|
|
1236
|
-
edges.push({ fromId: nodes[index - 1].id, toId: nodes[index].id, label: '下一步' });
|
|
1237
|
-
}
|
|
1238
|
-
const goalNode = nodes.find((node) => node.kind === 'user_goal');
|
|
1239
|
-
const executionNode = nodes.find((node) => node.kind === 'tool_execution');
|
|
1240
|
-
if (goalNode && executionNode) {
|
|
1241
|
-
for (const link of skillLinks) {
|
|
1242
|
-
edges.push({ fromId: goalNode.id, toId: link.id, label: '触发' });
|
|
1243
|
-
edges.push({ fromId: link.id, toId: executionNode.id, label: skillRoleLabel(link.role) });
|
|
1244
|
-
}
|
|
1245
|
-
}
|
|
1246
|
-
return { nodes: graphNodes, edges };
|
|
1247
|
-
}
|
|
1248
|
-
function sessionStoryAnswer(key, label, checklistItems, evidenceRefs) {
|
|
1249
|
-
const folded = foldExperienceChecklistItems(checklistItems);
|
|
1250
|
-
return {
|
|
1251
|
-
key,
|
|
1252
|
-
label,
|
|
1253
|
-
status: folded.status,
|
|
1254
|
-
reason: folded.reason,
|
|
1255
|
-
sourceItemKeys: folded.sourceItemKeys,
|
|
1256
|
-
text: sessionStoryAnswerText(key, folded.reason),
|
|
1257
|
-
evidenceRefs: uniqueEvidenceRefs(evidenceRefs.filter((ref) => Boolean(ref))).slice(0, 5),
|
|
1258
|
-
checklistItems,
|
|
1259
|
-
};
|
|
1260
|
-
}
|
|
1261
|
-
function sessionStoryAnswerText(key, reason) {
|
|
1262
|
-
const texts = {
|
|
1263
|
-
goal_satisfaction: {
|
|
1264
|
-
data_degraded: '这次没看到 skill 真的被加载,先确认数据,再判断目标是否满足。',
|
|
1265
|
-
blocking_failed: '用户出现了不满或叫停,目标没真的满足。',
|
|
1266
|
-
attention_accumulated: '有几条要看一眼,打开原文确认目标是否真的达成。',
|
|
1267
|
-
unknown_dominant: '现有证据不够,判断不了目标是否满足。',
|
|
1268
|
-
all_passed: '关键信号都没问题,看起来目标已满足。',
|
|
1269
|
-
not_applicable: '当前场景不适合回答这个问题。',
|
|
1270
|
-
},
|
|
1271
|
-
declared_behavior_fit: {
|
|
1272
|
-
data_degraded: '没看到 skill 真的被加载,先确认这次任务是不是真的命中了你的 skill。',
|
|
1273
|
-
blocking_failed: '关键执行项没过,skill 行为需要优先看一眼。',
|
|
1274
|
-
attention_accumulated: 'SKILL.md 声明的标准流程、硬性规则或核心工具有几条要看一眼。',
|
|
1275
|
-
unknown_dominant: 'SKILL.md 声明不全或执行证据不够,判不出行为是否符合用途。',
|
|
1276
|
-
all_passed: '执行情况看起来符合 skill 声明的用途。',
|
|
1277
|
-
not_applicable: '当前场景不适合回答这个问题。',
|
|
1278
|
-
},
|
|
1279
|
-
user_feeling: {
|
|
1280
|
-
data_degraded: '这次数据本身有问题,用户感受判断先放一放。',
|
|
1281
|
-
blocking_failed: '看到用户不满或主动叫停,可能觉得没用或绕路了。',
|
|
1282
|
-
attention_accumulated: '看到用户纠正或追问,结合原文判断用户感受。',
|
|
1283
|
-
unknown_dominant: '用户没给明确反馈,判断不了是否觉得有用。',
|
|
1284
|
-
all_passed: '没看到明显不满,用户体感看起来正常。',
|
|
1285
|
-
not_applicable: '当前场景不适合回答这个问题。',
|
|
1286
|
-
},
|
|
1287
|
-
};
|
|
1288
|
-
return texts[key][reason];
|
|
1289
|
-
}
|
|
1290
|
-
function checklistItemsForAnswer(session, key) {
|
|
1291
|
-
if (key === 'goal_satisfaction')
|
|
1292
|
-
return goalSatisfactionChecklistItems(session);
|
|
1293
|
-
if (key === 'declared_behavior_fit')
|
|
1294
|
-
return declaredBehaviorChecklistItems(session);
|
|
1295
|
-
return userFeelingChecklistItems(session);
|
|
1296
|
-
}
|
|
1297
|
-
function attributionSourcesToLabel(sources) {
|
|
1298
|
-
if (sources.length === 0)
|
|
1299
|
-
return '未识别(旧数据可能没记录来源)';
|
|
1300
|
-
const map = {
|
|
1301
|
-
'skill-tool': 'assistant 调用 Skill 工具',
|
|
1302
|
-
'command-name': '用户用 slash command',
|
|
1303
|
-
'aima-cmd': '用户用 aima-cmd 块',
|
|
1304
|
-
'skill-script': '跑了 skills/<name>/scripts 脚本',
|
|
1305
|
-
'read-skill-md': 'LLM 主动 Read SKILL.md',
|
|
1306
|
-
unknown: '未知',
|
|
1307
|
-
};
|
|
1308
|
-
return sources.map((s) => map[s] ?? s).join(' + ');
|
|
1309
|
-
}
|
|
1310
|
-
export function isExperienceTraceInProgress(session) {
|
|
1311
|
-
if (session.indicators.assistantDeliverySignalCount > 0)
|
|
1312
|
-
return false;
|
|
1313
|
-
if (session.indicators.deliverableArtifactSignalCount > 0)
|
|
1314
|
-
return false;
|
|
1315
|
-
// 用户已经主动表达不满(纠正 / 负向 / 中断)属于「被打断」, 不是「在途中」, 仍需触发 final_delivery_absent。
|
|
1316
|
-
if (session.indicators.userCorrectionCount > 0)
|
|
1317
|
-
return false;
|
|
1318
|
-
if (session.indicators.negativeFeedbackCount > 0)
|
|
1319
|
-
return false;
|
|
1320
|
-
if (session.indicators.userInterruptionCount > 0)
|
|
1321
|
-
return false;
|
|
1322
|
-
const last = session.evidenceChain.lastAssistantMessage?.snippet ?? '';
|
|
1323
|
-
// 完全没有最后助手回复时不强判 in-progress, 走原 failed / unknown 路径。
|
|
1324
|
-
if (!last.trim())
|
|
1325
|
-
return false;
|
|
1326
|
-
if (isAssistantProgressUpdateText(last))
|
|
1327
|
-
return true;
|
|
1328
|
-
// 预备语(让我看 / 先看看 / 先读 / 接下来)也算 in-progress, 仍未给出最终回复。
|
|
1329
|
-
return /让我(?:先|来|看|读|检查|分析|确认|拉|获取|继续)|先(?:看(?:看|一?下)|读(?:取|一下)?|确认|检查|分析|拉取|获取)|接下来/i.test(last);
|
|
1330
|
-
}
|
|
1331
|
-
function checklistItem(input) {
|
|
1332
|
-
const { statusCandidates, ...item } = input;
|
|
1333
|
-
return {
|
|
1334
|
-
...item,
|
|
1335
|
-
status: aggregateExperienceChecklistItemStatus([input.status, ...(statusCandidates ?? [])]),
|
|
1336
|
-
source: input.source ?? 'deterministic_rule',
|
|
1337
|
-
evidenceRefs: uniqueEvidenceRefs((input.evidenceRefs ?? []).filter((ref) => Boolean(ref))).slice(0, 5),
|
|
1338
|
-
};
|
|
1339
|
-
}
|
|
1340
|
-
export function hasRecognizableUserGoalText(value) {
|
|
1341
|
-
const text = value?.trim() ?? '';
|
|
1342
|
-
if (!text)
|
|
1343
|
-
return false;
|
|
1344
|
-
if (/^(嗯+|啊+|好的|好|继续|可以|收到|ok|OK|yes|no|不用|不需要)[。.!!??\s]*$/.test(text))
|
|
1345
|
-
return false;
|
|
1346
|
-
if (/(帮我|请|需要|想要|我要|给我|看下|看一下|基于|根据|重新|继续|先|把|将)/.test(text)
|
|
1347
|
-
&& /(生成|创建|写|实现|修复|优化|调整|修改|新增|删除|分析|review|评价|检查|看|拉取|执行|运行|验证|整理|总结|回复|评论|设计|拆分|合并|标注|定位|排查|上传|导出|发布|查询|对齐|沉淀|补充|改|做)/i.test(text)) {
|
|
1348
|
-
return true;
|
|
1349
|
-
}
|
|
1350
|
-
if (/(生成|创建|写一个|实现|修复|优化|调整|修改|新增|分析|review|检查|排查|验证|总结|设计|标注|定位|查询|对齐|补充|改一下|做一个)/i.test(text))
|
|
1351
|
-
return true;
|
|
1352
|
-
return text.length >= 12 && /[??]/.test(text) && !/^(为什么|怎么|哪里)[??]?$/.test(text);
|
|
1353
|
-
}
|
|
1354
|
-
function hasRecognizableUserGoal(ref) {
|
|
1355
|
-
return hasRecognizableUserGoalText(ref?.snippet);
|
|
1356
|
-
}
|
|
1357
|
-
function goalSatisfactionChecklistItems(session) {
|
|
1358
|
-
const feedbackRefs = userFeedbackEvidenceRefs(session);
|
|
1359
|
-
const goalIdentified = hasRecognizableUserGoal(session.evidenceChain.firstUserMessage);
|
|
1360
|
-
const inProgress = isExperienceTraceInProgress(session);
|
|
1361
|
-
const hasDelivery = session.indicators.assistantDeliverySignalCount > 0;
|
|
1362
|
-
const hasArtifact = session.indicators.deliverableArtifactSignalCount > 0;
|
|
1363
|
-
return [
|
|
1364
|
-
checklistItem({
|
|
1365
|
-
key: 'goal_identified',
|
|
1366
|
-
label: goalIdentified ? '目标已识别' : '目标不明确',
|
|
1367
|
-
status: goalIdentified ? 'passed' : 'unknown',
|
|
1368
|
-
contribution: 'informational',
|
|
1369
|
-
reason: goalIdentified
|
|
1370
|
-
? '真实用户原文里能识别出目标动作或明确请求。'
|
|
1371
|
-
: session.evidenceChain.firstUserMessage ? '看到真实用户原文,但目标动作不够明确。' : '没有看到真实用户目标原文。',
|
|
1372
|
-
evidenceRefs: [session.evidenceChain.firstUserMessage],
|
|
1373
|
-
}),
|
|
1374
|
-
checklistItem({
|
|
1375
|
-
key: 'completion_result_present',
|
|
1376
|
-
label: hasDelivery ? '给了用户最终答复' : inProgress ? '会话进行中' : '没给用户最终答复',
|
|
1377
|
-
status: hasDelivery ? 'passed' : inProgress ? 'not_applicable' : 'failed',
|
|
1378
|
-
contribution: hasDelivery ? 'attention' : inProgress ? 'neutral' : 'attention',
|
|
1379
|
-
reason: hasDelivery
|
|
1380
|
-
? '看到 assistant 给出了明确的完成话术或结果反馈。'
|
|
1381
|
-
: inProgress
|
|
1382
|
-
? '最后一句还是过程态(「先看看」「让我」),任务还没收尾,先不判定。'
|
|
1383
|
-
: '没看到 assistant 给用户明确的完成话术或结果反馈。',
|
|
1384
|
-
evidenceRefs: [session.evidenceChain.lastAssistantMessage],
|
|
1385
|
-
suggestionKey: hasDelivery || inProgress ? undefined : 'final_delivery_absent',
|
|
1386
|
-
}),
|
|
1387
|
-
checklistItem({
|
|
1388
|
-
key: 'deliverable_artifact_present',
|
|
1389
|
-
label: hasArtifact ? '给了可点开的产物' : inProgress ? '会话进行中' : '没给可点开的产物',
|
|
1390
|
-
status: hasArtifact ? 'passed' : inProgress ? 'not_applicable' : 'unknown',
|
|
1391
|
-
contribution: hasArtifact ? 'informational' : inProgress ? 'neutral' : 'informational',
|
|
1392
|
-
reason: hasArtifact
|
|
1393
|
-
? '看到 assistant 回复里附了链接、路径、代码块或文件。'
|
|
1394
|
-
: inProgress
|
|
1395
|
-
? '任务还没收尾,先不判定产物。'
|
|
1396
|
-
: '没看到明确的链接、路径、代码块或文件;不一定失败,得按 skill 目标判断。',
|
|
1397
|
-
evidenceRefs: [session.evidenceChain.lastAssistantMessage],
|
|
1398
|
-
suggestionKey: hasArtifact || inProgress ? undefined : 'artifact_absent',
|
|
1399
|
-
}),
|
|
1400
|
-
checklistItem({
|
|
1401
|
-
key: 'negative_feedback_seen',
|
|
1402
|
-
label: session.indicators.negativeFeedbackCount > 0 ? '看到用户负向反馈' : '未见用户负向反馈',
|
|
1403
|
-
status: session.indicators.negativeFeedbackCount > 0 ? 'failed' : 'passed',
|
|
1404
|
-
contribution: 'blocking',
|
|
1405
|
-
reason: session.indicators.negativeFeedbackCount > 0 ? '看到用户负向表达,不能直接认为目标已满足。' : '没有看到用户负向表达。',
|
|
1406
|
-
evidenceRefs: feedbackRefs,
|
|
1407
|
-
suggestionKey: session.indicators.negativeFeedbackCount > 0 ? 'negative_feedback_review' : undefined,
|
|
1408
|
-
}),
|
|
1409
|
-
checklistItem({
|
|
1410
|
-
key: 'user_correction_seen',
|
|
1411
|
-
label: session.indicators.userCorrectionCount > 0 ? '看到用户纠正' : '未见用户纠正',
|
|
1412
|
-
status: session.indicators.userCorrectionCount > 0 ? 'failed' : 'passed',
|
|
1413
|
-
contribution: 'attention',
|
|
1414
|
-
reason: session.indicators.userCorrectionCount > 0 ? '用户中途纠正了方向,目标是否满足要打开原文看。' : '没有看到用户纠正。',
|
|
1415
|
-
evidenceRefs: feedbackRefs,
|
|
1416
|
-
suggestionKey: session.indicators.userCorrectionCount > 0 ? 'user_correction_review' : undefined,
|
|
1417
|
-
}),
|
|
1418
|
-
checklistItem({
|
|
1419
|
-
key: 'user_interruption_seen',
|
|
1420
|
-
label: session.indicators.userInterruptionCount > 0 ? '看到用户中断' : '未见用户中断',
|
|
1421
|
-
status: session.indicators.userInterruptionCount > 0 ? 'failed' : 'passed',
|
|
1422
|
-
contribution: 'blocking',
|
|
1423
|
-
reason: session.indicators.userInterruptionCount > 0 ? '看到用户中断或停止任务信号,不能认为执行链路自然完成。' : '没有看到用户中断信号。',
|
|
1424
|
-
evidenceRefs: feedbackRefs,
|
|
1425
|
-
suggestionKey: session.indicators.userInterruptionCount > 0 ? 'user_interruption_review' : undefined,
|
|
1426
|
-
}),
|
|
1427
|
-
checklistItem({
|
|
1428
|
-
key: 'goal_shift_seen',
|
|
1429
|
-
label: session.indicators.userGoalShiftCount > 0 ? '看到目标切换' : '未见目标切换',
|
|
1430
|
-
status: session.indicators.userGoalShiftCount > 0 ? 'failed' : 'passed',
|
|
1431
|
-
contribution: 'attention',
|
|
1432
|
-
reason: session.indicators.userGoalShiftCount > 0 ? '用户中途切换了目标,后续诉求可能不属于这个 skill。' : '没有看到目标切换。',
|
|
1433
|
-
evidenceRefs: feedbackRefs,
|
|
1434
|
-
suggestionKey: session.indicators.userGoalShiftCount > 0 ? 'goal_shift_review' : undefined,
|
|
1435
|
-
}),
|
|
1436
|
-
];
|
|
1437
|
-
}
|
|
1438
|
-
function declaredBehaviorChecklistItems(session) {
|
|
1439
|
-
const expectedToolCheck = expectedToolCheckForSession(session);
|
|
1440
|
-
const declarations = skillDeclarationCheckForSession(session);
|
|
1441
|
-
const hasSkillRead = session.evidenceChain.skillContextCount > 0;
|
|
1442
|
-
const attributionLabel = attributionSourcesToLabel(session.attributionSources ?? []);
|
|
1443
|
-
const items = [
|
|
1444
|
-
checklistItem({
|
|
1445
|
-
key: 'attribution_source',
|
|
1446
|
-
label: hasSkillRead
|
|
1447
|
-
? 'LLM 读了 SKILL.md'
|
|
1448
|
-
: `skill 判定来源:${attributionLabel}`,
|
|
1449
|
-
status: 'passed',
|
|
1450
|
-
contribution: 'informational',
|
|
1451
|
-
reason: hasSkillRead
|
|
1452
|
-
? `看到 ${session.evidenceChain.skillContextCount} 次 SKILL.md 加载事件,可作为能力归因证据。`
|
|
1453
|
-
: `日志里没看到 LLM 主动 Read SKILL.md。这次 skill 归因来自:${attributionLabel}。OpenClaw 脚本 / Skill 工具 / slash command 触发时这是常态,不代表 skill 没用上。`,
|
|
1454
|
-
evidenceRefs: [session.evidenceChain.firstSkillContext, session.evidenceChain.firstToolUse],
|
|
1455
|
-
}),
|
|
1456
|
-
checklistItem({
|
|
1457
|
-
key: 'workflow_declared',
|
|
1458
|
-
label: declarations.workflows.declared ? '标准流程已声明' : '标准流程未声明',
|
|
1459
|
-
status: declarations.workflows.declared ? 'passed' : 'not_declared',
|
|
1460
|
-
contribution: declarations.workflows.declared ? 'informational' : 'attention',
|
|
1461
|
-
reason: declarations.workflows.declared ? `SKILL.md 里声明了 ${declarations.workflows.count} 个标准流程节点。` : 'SKILL.md 没声明标准流程,运行时只能猜流程是否完整。',
|
|
1462
|
-
suggestionKey: declarations.workflows.declared ? undefined : 'workflow_not_declared',
|
|
1463
|
-
}),
|
|
1464
|
-
];
|
|
1465
|
-
if (declarations.workflows.declared) {
|
|
1466
|
-
const executed = session.indicators.toolCallCount > 0;
|
|
1467
|
-
items.push(checklistItem({
|
|
1468
|
-
key: 'workflow_executed',
|
|
1469
|
-
label: executed ? '标准流程已执行' : '标准流程未执行',
|
|
1470
|
-
status: executed ? 'unknown' : 'failed',
|
|
1471
|
-
contribution: 'attention',
|
|
1472
|
-
reason: executed ? '看到了工具调用,但是不是真的覆盖了完整流程,还要打开原文确认。' : '声明了标准流程,但没看到工具执行的证据。',
|
|
1473
|
-
evidenceRefs: [session.evidenceChain.firstToolUse],
|
|
1474
|
-
suggestionKey: 'workflow_execution_review',
|
|
1475
|
-
}));
|
|
1476
|
-
}
|
|
1477
|
-
items.push(checklistItem({
|
|
1478
|
-
key: 'hardrule_declared',
|
|
1479
|
-
label: declarations.hardRules.declared ? '硬性规则已声明' : '硬性规则未声明',
|
|
1480
|
-
status: declarations.hardRules.declared ? 'passed' : 'not_declared',
|
|
1481
|
-
contribution: declarations.hardRules.declared ? 'informational' : 'attention',
|
|
1482
|
-
reason: declarations.hardRules.declared ? `SKILL.md 里声明了 ${declarations.hardRules.count} 条硬性规则。` : 'SKILL.md 没声明硬性规则。',
|
|
1483
|
-
suggestionKey: declarations.hardRules.declared ? undefined : 'hardrule_not_declared',
|
|
1484
|
-
}));
|
|
1485
|
-
if (declarations.hardRules.declared) {
|
|
1486
|
-
items.push(checklistItem({
|
|
1487
|
-
key: 'hardrule_executed',
|
|
1488
|
-
label: '硬性规则执行情况需打开原文看',
|
|
1489
|
-
status: 'unknown',
|
|
1490
|
-
contribution: 'attention',
|
|
1491
|
-
reason: '声明了硬性规则,但当前规则没法完整证明每条都执行了,要打开原文看。',
|
|
1492
|
-
suggestionKey: 'hardrule_execution_review',
|
|
1493
|
-
}));
|
|
1494
|
-
}
|
|
1495
|
-
items.push(checklistItem({
|
|
1496
|
-
key: 'core_tools_declared',
|
|
1497
|
-
label: expectedToolCheck.declared ? '核心工具已声明' : '核心工具未声明',
|
|
1498
|
-
status: expectedToolCheck.declared ? 'passed' : 'not_declared',
|
|
1499
|
-
contribution: expectedToolCheck.declared ? 'informational' : 'attention',
|
|
1500
|
-
reason: expectedToolCheck.declared ? `SKILL.md 声明的核心工具:${expectedToolCheck.expectedTools.join('、')}。` : 'SKILL.md 没声明核心工具,分不出「真用上了 skill 工具」还是「只是随便调了个工具」。',
|
|
1501
|
-
suggestionKey: expectedToolCheck.declared ? undefined : 'expected_tools_not_declared',
|
|
1502
|
-
}));
|
|
1503
|
-
if (expectedToolCheck.declared) {
|
|
1504
|
-
const hit = expectedToolCheck.matchedTools.length > 0;
|
|
1505
|
-
items.push(checklistItem({
|
|
1506
|
-
key: 'core_tools_hit',
|
|
1507
|
-
label: hit ? '核心工具用上了' : '核心工具没用上',
|
|
1508
|
-
status: hit ? 'passed' : 'failed',
|
|
1509
|
-
contribution: 'blocking',
|
|
1510
|
-
reason: hit ? `用上了核心工具:${expectedToolCheck.matchedTools.join('、')}。` : '没用上 SKILL.md 声明的核心工具。',
|
|
1511
|
-
evidenceRefs: [session.evidenceChain.firstToolUse],
|
|
1512
|
-
suggestionKey: hit ? undefined : 'expected_tools_missed',
|
|
1513
|
-
}));
|
|
1514
|
-
}
|
|
1515
|
-
return items;
|
|
1516
|
-
}
|
|
1517
|
-
function userFeelingChecklistItems(session) {
|
|
1518
|
-
const feedbackRefs = userFeedbackEvidenceRefs(session);
|
|
1519
|
-
const hasAnyFeedback = session.indicators.positiveFeedbackCount > 0
|
|
1520
|
-
|| session.indicators.negativeFeedbackCount > 0
|
|
1521
|
-
|| session.indicators.userCorrectionCount > 0
|
|
1522
|
-
|| session.indicators.userInterruptionCount > 0
|
|
1523
|
-
|| session.indicators.userFollowUpCount > 0
|
|
1524
|
-
|| session.indicators.userGoalShiftCount > 0;
|
|
1525
|
-
return [
|
|
1526
|
-
checklistItem({
|
|
1527
|
-
key: 'user_feedback_signal_present',
|
|
1528
|
-
label: hasAnyFeedback ? '看到用户反馈信号' : '未见用户反馈信号',
|
|
1529
|
-
status: hasAnyFeedback ? 'passed' : 'unknown',
|
|
1530
|
-
contribution: 'informational',
|
|
1531
|
-
reason: hasAnyFeedback ? '看到至少一种用户反馈或后续行为信号。' : '没有看到明确用户反馈信号。',
|
|
1532
|
-
evidenceRefs: feedbackRefs,
|
|
1533
|
-
}),
|
|
1534
|
-
checklistItem({
|
|
1535
|
-
key: 'positive_feedback_seen',
|
|
1536
|
-
label: session.indicators.positiveFeedbackCount > 0 ? '看到用户正向反馈' : '未见用户正向反馈',
|
|
1537
|
-
status: session.indicators.positiveFeedbackCount > 0 ? 'passed' : 'unknown',
|
|
1538
|
-
contribution: session.indicators.positiveFeedbackCount > 0 ? 'positive' : 'neutral',
|
|
1539
|
-
reason: session.indicators.positiveFeedbackCount > 0 ? '看到用户认可或正向反馈。' : '没有看到明确正向反馈。',
|
|
1540
|
-
evidenceRefs: feedbackRefs,
|
|
1541
|
-
}),
|
|
1542
|
-
checklistItem({
|
|
1543
|
-
key: 'negative_feedback_seen',
|
|
1544
|
-
label: session.indicators.negativeFeedbackCount > 0 ? '看到用户负向反馈' : '未见用户负向反馈',
|
|
1545
|
-
status: session.indicators.negativeFeedbackCount > 0 ? 'failed' : 'passed',
|
|
1546
|
-
contribution: session.indicators.negativeFeedbackCount > 0 ? 'blocking' : 'neutral',
|
|
1547
|
-
reason: session.indicators.negativeFeedbackCount > 0 ? '看到用户负向表达。' : '没有看到用户负向表达。',
|
|
1548
|
-
evidenceRefs: feedbackRefs,
|
|
1549
|
-
suggestionKey: session.indicators.negativeFeedbackCount > 0 ? 'negative_feedback_review' : undefined,
|
|
1550
|
-
}),
|
|
1551
|
-
checklistItem({
|
|
1552
|
-
key: 'user_correction_seen',
|
|
1553
|
-
label: session.indicators.userCorrectionCount > 0 ? '看到用户纠正' : '未见用户纠正',
|
|
1554
|
-
status: session.indicators.userCorrectionCount > 0 ? 'failed' : 'passed',
|
|
1555
|
-
contribution: session.indicators.userCorrectionCount > 0 ? 'attention' : 'neutral',
|
|
1556
|
-
reason: session.indicators.userCorrectionCount > 0 ? '看到用户重新解释或要求修正。' : '没有看到用户纠正信号。',
|
|
1557
|
-
evidenceRefs: feedbackRefs,
|
|
1558
|
-
suggestionKey: session.indicators.userCorrectionCount > 0 ? 'user_correction_review' : undefined,
|
|
1559
|
-
}),
|
|
1560
|
-
checklistItem({
|
|
1561
|
-
key: 'user_follow_up_seen',
|
|
1562
|
-
label: session.indicators.userFollowUpCount > 0 ? '看到用户追问' : '未见用户追问',
|
|
1563
|
-
status: session.indicators.userFollowUpCount > 0 ? 'unknown' : 'passed',
|
|
1564
|
-
contribution: session.indicators.userFollowUpCount > 0 ? 'informational' : 'neutral',
|
|
1565
|
-
reason: session.indicators.userFollowUpCount > 0 ? '看到用户追问;需要结合上下文区分推进使用还是不满意。' : '没有看到用户追问。',
|
|
1566
|
-
evidenceRefs: feedbackRefs,
|
|
1567
|
-
suggestionKey: session.indicators.userFollowUpCount > 0 ? 'follow_up_review' : undefined,
|
|
1568
|
-
}),
|
|
1569
|
-
checklistItem({
|
|
1570
|
-
key: 'user_interruption_seen',
|
|
1571
|
-
label: session.indicators.userInterruptionCount > 0 ? '看到用户中断' : '未见用户中断',
|
|
1572
|
-
status: session.indicators.userInterruptionCount > 0 ? 'failed' : 'passed',
|
|
1573
|
-
contribution: session.indicators.userInterruptionCount > 0 ? 'blocking' : 'neutral',
|
|
1574
|
-
reason: session.indicators.userInterruptionCount > 0 ? '看到用户中断或停止任务信号。' : '没有看到用户中断信号。',
|
|
1575
|
-
evidenceRefs: feedbackRefs,
|
|
1576
|
-
suggestionKey: session.indicators.userInterruptionCount > 0 ? 'user_interruption_review' : undefined,
|
|
1577
|
-
}),
|
|
1578
|
-
];
|
|
1579
|
-
}
|
|
1580
|
-
export function foldExperienceChecklistItems(items) {
|
|
1581
|
-
const relevant = items.filter((item) => item.contribution !== 'neutral');
|
|
1582
|
-
const active = relevant.length > 0 ? relevant : items;
|
|
1583
|
-
const degraded = active.filter((item) => item.status === 'degraded');
|
|
1584
|
-
if (degraded.length > 0)
|
|
1585
|
-
return { status: 'degraded', reason: 'data_degraded', sourceItemKeys: degraded.map((item) => item.key) };
|
|
1586
|
-
const blockingFailed = active.filter((item) => item.contribution === 'blocking' && item.status === 'failed');
|
|
1587
|
-
if (blockingFailed.length > 0)
|
|
1588
|
-
return { status: 'attention', reason: 'blocking_failed', sourceItemKeys: blockingFailed.map((item) => item.key) };
|
|
1589
|
-
const attentionFailed = active.filter((item) => item.contribution === 'attention' && item.status === 'failed');
|
|
1590
|
-
if (attentionFailed.length > 0)
|
|
1591
|
-
return { status: 'attention', reason: 'attention_accumulated', sourceItemKeys: attentionFailed.map((item) => item.key) };
|
|
1592
|
-
const unknown = active.filter((item) => item.status === 'unknown' || item.status === 'not_declared');
|
|
1593
|
-
const positivePassed = active.filter((item) => item.status === 'passed' && item.contribution === 'positive');
|
|
1594
|
-
const decisivePassed = active.filter((item) => item.status === 'passed' && (item.contribution === 'blocking' || item.contribution === 'attention' || item.contribution === 'positive'));
|
|
1595
|
-
const informationalPassed = active.filter((item) => item.status === 'passed' && item.contribution === 'informational');
|
|
1596
|
-
const passed = [...positivePassed, ...decisivePassed.filter((item) => item.contribution !== 'positive'), ...informationalPassed];
|
|
1597
|
-
if (unknown.length > 0 && (decisivePassed.length === 0 || unknown.length >= passed.length)) {
|
|
1598
|
-
return { status: 'unknown', reason: 'unknown_dominant', sourceItemKeys: unknown.map((item) => item.key) };
|
|
1599
|
-
}
|
|
1600
|
-
if (passed.length > 0)
|
|
1601
|
-
return { status: 'ok', reason: 'all_passed', sourceItemKeys: passed.map((item) => item.key) };
|
|
1602
|
-
return { status: 'not_applicable', reason: 'not_applicable', sourceItemKeys: active.map((item) => item.key) };
|
|
1603
|
-
}
|
|
1604
|
-
function reviewerScopeReasonCodes(session) {
|
|
1605
|
-
const reasons = [];
|
|
1606
|
-
if (session.invocationIds.length !== 1)
|
|
1607
|
-
reasons.push('multiple_invocations');
|
|
1608
|
-
if (session.goalSliceIds.length !== 1)
|
|
1609
|
-
reasons.push('multiple_goal_slices');
|
|
1610
|
-
if ((session.timelineTree?.branches.length ?? 0) > 0)
|
|
1611
|
-
reasons.push('subagent_branches_present');
|
|
1612
|
-
if (session.pluginNames.length > 1 || session.commandNames.length > 1)
|
|
1613
|
-
reasons.push('multiple_skill_entrypoints');
|
|
1614
|
-
return reasons;
|
|
1615
|
-
}
|
|
1616
|
-
function reviewerStep(order, label, text, status, evidenceRefs = []) {
|
|
1617
|
-
return {
|
|
1618
|
-
order,
|
|
1619
|
-
label,
|
|
1620
|
-
status,
|
|
1621
|
-
text,
|
|
1622
|
-
evidenceRefs: uniqueEvidenceRefs(evidenceRefs).slice(0, 4),
|
|
1623
|
-
};
|
|
1624
|
-
}
|
|
1625
|
-
function userGoalStepText(session) {
|
|
1626
|
-
const goal = session.evidenceChain.firstUserMessage?.snippet;
|
|
1627
|
-
if (!goal)
|
|
1628
|
-
return '没有看到明确人工用户目标;当前只能按运行证据做常规复盘。';
|
|
1629
|
-
return `用户目标:${goal}`;
|
|
1630
|
-
}
|
|
1631
|
-
function skillSelectionStepText(session) {
|
|
1632
|
-
const entrypoint = session.commandNames.length > 0 ? `,入口 ${session.commandNames.join('、')}` : session.entrypoint ? `,入口 ${session.entrypoint}` : '';
|
|
1633
|
-
return `本次使用的能力:${session.skillName}${entrypoint}。`;
|
|
1634
|
-
}
|
|
1635
|
-
function executionStepStatus(session, expectedToolCheck) {
|
|
1636
|
-
if (session.indicators.toolFailureCount > 0 || expectedToolCheck.declared && expectedToolCheck.matchedTools.length === 0)
|
|
1637
|
-
return 'attention';
|
|
1638
|
-
if (session.indicators.toolCallCount > 0)
|
|
1639
|
-
return 'ok';
|
|
1640
|
-
return 'unknown';
|
|
1641
|
-
}
|
|
1642
|
-
function executionStepText(session, expectedToolCheck = expectedToolCheckForSession(session)) {
|
|
1643
|
-
const failures = session.indicators.toolFailureCount > 0 ? `,其中失败 ${session.indicators.toolFailureCount} 次` : '';
|
|
1644
|
-
const expected = expectedToolCheck.declared
|
|
1645
|
-
? expectedToolCheck.matchedTools.length > 0
|
|
1646
|
-
? `命中声明的核心工具:${expectedToolCheck.matchedTools.join('、')}。`
|
|
1647
|
-
: `但没有命中能力声明的核心工具:${expectedToolCheck.expectedTools.join('、')}。`
|
|
1648
|
-
: '';
|
|
1649
|
-
return `执行中看到 ${session.indicators.toolCallCount} 次工具调用${failures}。${expected}`;
|
|
1650
|
-
}
|
|
1651
|
-
function deliveryStepText(session) {
|
|
1652
|
-
if (session.indicators.assistantDeliverySignalCount > 0) {
|
|
1653
|
-
const artifact = session.indicators.deliverableArtifactSignalCount > 0
|
|
1654
|
-
? `,其中 ${session.indicators.deliverableArtifactSignalCount} 次包含具体产物线索`
|
|
1655
|
-
: ',但未看到明确产物线索';
|
|
1656
|
-
return `看到 ${session.indicators.assistantDeliverySignalCount} 次完成态或结果反馈${artifact}。`;
|
|
1657
|
-
}
|
|
1658
|
-
return '没有发现最后结果反馈;当前不能把过程进展当成完成。';
|
|
1659
|
-
}
|
|
1660
|
-
function userFeedbackStepText(session) {
|
|
1661
|
-
const parts = [
|
|
1662
|
-
session.indicators.userFollowUpCount > 0 ? `追问/补充 ${session.indicators.userFollowUpCount} 次` : '',
|
|
1663
|
-
session.indicators.userCorrectionCount > 0 ? `纠正 ${session.indicators.userCorrectionCount} 次` : '',
|
|
1664
|
-
session.indicators.negativeFeedbackCount > 0 ? `负向反馈 ${session.indicators.negativeFeedbackCount} 次` : '',
|
|
1665
|
-
session.indicators.positiveFeedbackCount > 0 ? `正向反馈 ${session.indicators.positiveFeedbackCount} 次` : '',
|
|
1666
|
-
session.indicators.userGoalShiftCount > 0 ? `目标切换 ${session.indicators.userGoalShiftCount} 次` : '',
|
|
1667
|
-
].filter(Boolean);
|
|
1668
|
-
return parts.length > 0 ? `用户反馈信号:${parts.join(',')}。` : '原始记录里没有看到人工追问、纠正、负向反馈或目标切换。';
|
|
1669
|
-
}
|
|
1670
|
-
function userFeedbackStepStatus(session) {
|
|
1671
|
-
if (session.indicators.userCorrectionCount > 0 || session.indicators.negativeFeedbackCount > 0 || session.indicators.userInterruptionCount > 0)
|
|
1672
|
-
return 'attention';
|
|
1673
|
-
if (session.indicators.positiveFeedbackCount > 0)
|
|
1674
|
-
return 'ok';
|
|
1675
|
-
return 'unknown';
|
|
1676
|
-
}
|
|
1677
|
-
function userFeedbackEvidenceRefs(session) {
|
|
1678
|
-
return uniqueEvidenceRefs(session.ruleFindings
|
|
1679
|
-
.filter((finding) => finding.code === 'user_correction_seen' || finding.code === 'negative_feedback_seen' || finding.code === 'positive_feedback_seen' || finding.code === 'user_goal_shift_seen' || finding.code === 'user_interruption_seen')
|
|
1680
|
-
.flatMap((finding) => finding.evidenceRefs)).slice(0, 5);
|
|
1681
|
-
}
|
|
1682
|
-
function expectedToolCheckForSession(session) {
|
|
1683
|
-
const expectedTools = loadExpectedToolsForSkill(session.skillName, session.cwd);
|
|
1684
|
-
if (expectedTools.length === 0)
|
|
1685
|
-
return { expectedTools: [], matchedTools: [], declared: false };
|
|
1686
|
-
const events = session.fullSessionTimeline.length > 0 ? session.fullSessionTimeline : session.timelinePreview;
|
|
1687
|
-
const matchedTools = expectedTools.filter((tool) => events.some((event) => eventMatchesExpectedTool(event, tool)));
|
|
1688
|
-
return {
|
|
1689
|
-
expectedTools,
|
|
1690
|
-
matchedTools,
|
|
1691
|
-
declared: true,
|
|
1692
|
-
};
|
|
1693
|
-
}
|
|
1694
|
-
function skillDeclarationCheckForSession(session) {
|
|
1695
|
-
const path = findSkillMdPathForExperience(session.skillName, session.cwd ?? process.cwd());
|
|
1696
|
-
if (!path) {
|
|
1697
|
-
return {
|
|
1698
|
-
hardRules: { declared: false, count: 0 },
|
|
1699
|
-
workflows: { declared: false, count: 0 },
|
|
1700
|
-
};
|
|
1701
|
-
}
|
|
1702
|
-
try {
|
|
1703
|
-
const content = readFileSync(path, 'utf-8');
|
|
1704
|
-
const hardRules = validateSkillHardRules(content);
|
|
1705
|
-
const workflows = validateSkillWorkflows(content);
|
|
1706
|
-
return {
|
|
1707
|
-
hardRules: { declared: hardRules.declared, count: hardRules.rules.length },
|
|
1708
|
-
workflows: { declared: workflows.declared, count: workflows.workflows.reduce((sum, workflow) => sum + workflow.nodes.length, 0) },
|
|
1709
|
-
};
|
|
1710
|
-
}
|
|
1711
|
-
catch {
|
|
1712
|
-
return {
|
|
1713
|
-
hardRules: { declared: false, count: 0 },
|
|
1714
|
-
workflows: { declared: false, count: 0 },
|
|
1715
|
-
};
|
|
1716
|
-
}
|
|
1717
|
-
}
|
|
1718
|
-
function loadExpectedToolsForSkill(skillName, cwd) {
|
|
1719
|
-
const path = findSkillMdPathForExperience(skillName, cwd ?? process.cwd());
|
|
1720
|
-
if (!path)
|
|
1721
|
-
return [];
|
|
1722
|
-
try {
|
|
1723
|
-
const parsed = parseSkillFrontmatter(readFileSync(path, 'utf-8'));
|
|
1724
|
-
const data = parsed.ok ? parsed.data : undefined;
|
|
1725
|
-
const value = data?.expected_tools ?? data?.expectedTools;
|
|
1726
|
-
return Array.isArray(value)
|
|
1727
|
-
? unique(value.filter((item) => typeof item === 'string' && Boolean(item.trim())).map((item) => item.trim()))
|
|
1728
|
-
: [];
|
|
1729
|
-
}
|
|
1730
|
-
catch {
|
|
1731
|
-
return [];
|
|
1732
|
-
}
|
|
1733
|
-
}
|
|
1734
|
-
function eventMatchesExpectedTool(event, expectedTool) {
|
|
1735
|
-
if (event.kind !== 'tool_use')
|
|
1736
|
-
return false;
|
|
1737
|
-
const text = `${event.toolName ?? ''}\n${event.label ?? ''}\n${event.snippet ?? ''}\n${event.fullText ?? ''}`.toLowerCase();
|
|
1738
|
-
const normalized = expectedTool.toLowerCase().trim();
|
|
1739
|
-
const aliases = unique([
|
|
1740
|
-
normalized,
|
|
1741
|
-
normalized.replace(/[-_]?cli$/, ''),
|
|
1742
|
-
].filter(Boolean));
|
|
1743
|
-
return aliases.some((alias) => new RegExp(`(^|[^a-z0-9_-])${escapeRegExp(alias)}([^a-z0-9_-]|$)`, 'i').test(text));
|
|
1744
|
-
}
|
|
1745
|
-
function escapeRegExp(value) {
|
|
1746
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
1747
|
-
}
|
|
1748
|
-
function findSkillMdPathForExperience(skillName, cwd) {
|
|
1749
|
-
if (!/^[A-Za-z0-9_.-]+$/.test(skillName))
|
|
1750
|
-
return undefined;
|
|
1751
|
-
const candidates = [
|
|
1752
|
-
join(cwd, '.claude', 'skills', skillName, 'SKILL.md'),
|
|
1753
|
-
join(cwd, '.openclaw', 'workspace', 'skills', skillName, 'SKILL.md'),
|
|
1754
|
-
join(cwd, 'workspace', 'skills', skillName, 'SKILL.md'),
|
|
1755
|
-
join(cwd, 'skills', skillName, 'SKILL.md'),
|
|
1756
|
-
join(homedir(), '.openclaw', 'workspace', 'skills', skillName, 'SKILL.md'),
|
|
1757
|
-
join(homedir(), '.claude', 'skills', skillName, 'SKILL.md'),
|
|
1758
|
-
join(homedir(), '.codex', 'skills', skillName, 'SKILL.md'),
|
|
1759
|
-
join(homedir(), '.agents', 'skills', skillName, 'SKILL.md'),
|
|
1760
|
-
];
|
|
1761
|
-
return candidates.find((candidate) => existsSync(candidate));
|
|
1762
|
-
}
|
|
1763
|
-
function reviewerFindingsForSession(session, reviewState) {
|
|
1764
|
-
const findings = [];
|
|
1765
|
-
const push = (level, title, body, ruleSource, evidenceRefs = []) => {
|
|
1766
|
-
const id = hashParts('reviewer-finding', session.id, ruleSource, title);
|
|
1767
|
-
const judgmentId = hashParts('reviewer-judgment', session.id, ruleSource, title, evidenceRefs.map((ref) => ref.id).join('|'));
|
|
1768
|
-
const reviewEntry = reviewState?.entries[observationReviewStateKey('reviewer_judgment', judgmentId)];
|
|
1769
|
-
findings.push({
|
|
1770
|
-
id,
|
|
1771
|
-
judgmentId,
|
|
1772
|
-
source: 'deterministic_rule',
|
|
1773
|
-
level,
|
|
1774
|
-
title,
|
|
1775
|
-
body,
|
|
1776
|
-
ruleSource,
|
|
1777
|
-
ruleVersion: REVIEWER_REPORT_RULE_VERSION,
|
|
1778
|
-
evidenceRefs: uniqueEvidenceRefs(evidenceRefs).slice(0, 5),
|
|
1779
|
-
reviewStateRef: {
|
|
1780
|
-
targetType: 'reviewer_judgment',
|
|
1781
|
-
targetId: judgmentId,
|
|
1782
|
-
...(reviewEntry?.verdict ? { verdict: reviewEntry.verdict } : {}),
|
|
1783
|
-
...(reviewEntry?.reason ? { reason: reviewEntry.reason } : {}),
|
|
1784
|
-
...(reviewEntry?.note ? { note: reviewEntry.note } : {}),
|
|
1785
|
-
...(reviewEntry?.reviewedAt ? { reviewedAt: reviewEntry.reviewedAt } : {}),
|
|
1786
|
-
},
|
|
1787
|
-
});
|
|
1788
|
-
};
|
|
1789
|
-
const findingRefs = (code) => session.ruleFindings.filter((finding) => finding.code === code).flatMap((finding) => finding.evidenceRefs);
|
|
1790
|
-
const expectedToolCheck = expectedToolCheckForSession(session);
|
|
1791
|
-
if (session.indicators.toolFailureCount > 0) {
|
|
1792
|
-
push('attention', `工具调用失败 ${session.indicators.toolFailureCount} 次`, '执行中遇到工具报错。看下失败的步骤是否在 SKILL.md 里写明了重试或回退方式。', 'tool_error_recovery', findingRefs('tool_failure_seen'));
|
|
1793
|
-
}
|
|
1794
|
-
if (session.indicators.assistantDeliverySignalCount === 0) {
|
|
1795
|
-
push('attention', '没看到给用户的最终答复', 'assistant 没说「完成 / 结果如下」这种收尾,可能任务还没跑完,或收尾文案不够清楚让用户知道事情结束了。', 'final_delivery_absent', session.evidenceChain.lastAssistantMessage ? [session.evidenceChain.lastAssistantMessage] : []);
|
|
1796
|
-
}
|
|
1797
|
-
if (session.indicators.sessionInterruptedCount > 0) {
|
|
1798
|
-
push('attention', `会话异常断开 ${session.indicators.sessionInterruptedCount} 次`, '任务中途被异常中断或重启。如果是网络/超时,看是否要在 skill 里加重试;如果是程序原因,跟开发反馈。', 'session_interrupted', findingRefs('session_interrupted_seen'));
|
|
1799
|
-
}
|
|
1800
|
-
if (expectedToolCheck.declared && expectedToolCheck.matchedTools.length === 0) {
|
|
1801
|
-
push('attention', '没用上 SKILL.md 声明的核心工具', `SKILL.md 里声明 ${expectedToolCheck.expectedTools.join('、')} 是核心工具,但这次没看到调用。要么 description 指引不够清楚,要么用户的诉求不属于这个 skill 的场景。`, 'expected_tools_missed', session.evidenceChain.firstToolUse ? [session.evidenceChain.firstToolUse] : []);
|
|
1802
|
-
}
|
|
1803
|
-
if (session.indicators.userCorrectionCount > 0) {
|
|
1804
|
-
push('attention', `用户纠正 ${session.indicators.userCorrectionCount} 次`, '用户在过程中纠正了方向。看原文确认是 skill 理解偏差,还是 skill 不该处理这种诉求。', 'user_correction', findingRefs('user_correction_seen'));
|
|
1805
|
-
}
|
|
1806
|
-
if (session.indicators.userInterruptionCount > 0) {
|
|
1807
|
-
push('attention', `用户手动叫停 ${session.indicators.userInterruptionCount} 次`, '用户主动喊停了执行。常见原因:跑偏 / 太慢 / 用错工具。看原文定位是哪一步触发的。', 'user_interruption', findingRefs('user_interruption_seen'));
|
|
1808
|
-
}
|
|
1809
|
-
if (session.indicators.negativeFeedbackCount > 0) {
|
|
1810
|
-
push('attention', `用户说了 ${session.indicators.negativeFeedbackCount} 次不满意`, '用户出现了「不对 / 错了 / 不行」等负向表达。先看是 skill 给的结果不达预期,还是用户对方向本身有疑问。', 'negative_feedback', findingRefs('negative_feedback_seen'));
|
|
1811
|
-
}
|
|
1812
|
-
if (session.indicators.hardRuleTextHitCount > 0) {
|
|
1813
|
-
push('note', `用户提了 ${session.indicators.hardRuleTextHitCount} 次硬性要求`, '用户在对话里强调了某些必须做/不能做的规则。如果同类要求反复出现,可以沉淀到 SKILL.md 的 hardRules。', 'user_hard_rule', findingRefs('hard_rule_seen'));
|
|
1814
|
-
}
|
|
1815
|
-
if (reviewerScopeReasonCodes(session).length > 0) {
|
|
1816
|
-
push('note', '复杂链路降级展示', '本次不是严格的 1 次会话 × 1 个目标 × 1 个能力场景。当前先做通用展示,不强行拆分多能力、子任务或目标切换。', 'complex_scope_degraded', []);
|
|
1817
|
-
}
|
|
1818
|
-
if (findings.length === 0) {
|
|
1819
|
-
push('note', '未命中优先问题信号', '没有看到需要优先关注的纠正、中断、负向反馈、工具失败或没收尾的信号。', 'no_priority_signal', []);
|
|
1820
|
-
}
|
|
1821
|
-
return findings;
|
|
1822
|
-
}
|
|
1823
|
-
function reviewerTitle(session, attentionCount, possibleFalsePositiveCount) {
|
|
1824
|
-
const suffix = possibleFalsePositiveCount > 0 ? ` · ${possibleFalsePositiveCount} 项疑似误判` : '';
|
|
1825
|
-
if (attentionCount > 0)
|
|
1826
|
-
return `${session.skillName} · ${attentionCount} 项要看一眼${suffix}`;
|
|
1827
|
-
if (session.indicators.assistantDeliverySignalCount > 0)
|
|
1828
|
-
return `${session.skillName} · 看起来有结果 · 常规抽样${suffix}`;
|
|
1829
|
-
return `${session.skillName} · 常规抽样 · 未见高优先级信号${suffix}`;
|
|
1830
|
-
}
|
|
1831
|
-
function reviewerSummary(session, scopeKind, attentionCount, possibleFalsePositiveCount) {
|
|
1832
|
-
const scopeText = scopeKind === 'single_skill_single_goal'
|
|
1833
|
-
? '本次属于单个能力 / 单个目标报告范围。'
|
|
1834
|
-
: '本次是复杂链路,当前先做降级展示,不强行拆分语义分支。';
|
|
1835
|
-
const reviewText = attentionCount > 0
|
|
1836
|
-
? `发现 ${attentionCount} 条事实层复核点。`
|
|
1837
|
-
: '没有发现优先级较高的事实层复核点。';
|
|
1838
|
-
const falsePositiveText = possibleFalsePositiveCount > 0 ? `另有 ${possibleFalsePositiveCount} 条疑似误判需要人工确认。` : '';
|
|
1839
|
-
return [scopeText, reviewText, falsePositiveText].filter(Boolean).join(' ');
|
|
1840
|
-
}
|
|
1841
|
-
function reviewerAuthorSuggestions(session, findings) {
|
|
1842
|
-
const suggestions = new Map();
|
|
1843
|
-
const pushSuggestion = (key, text, severity) => {
|
|
1844
|
-
const existing = suggestions.get(key);
|
|
1845
|
-
if (!existing || severity > existing.severity)
|
|
1846
|
-
suggestions.set(key, { text, severity });
|
|
1847
|
-
};
|
|
1848
|
-
for (const answer of session.sessionStory?.answers ?? []) {
|
|
1849
|
-
for (const item of answer.checklistItems ?? []) {
|
|
1850
|
-
if (!item.suggestionKey)
|
|
1851
|
-
continue;
|
|
1852
|
-
const text = suggestionTextForChecklistItem(item.suggestionKey);
|
|
1853
|
-
if (!text)
|
|
1854
|
-
continue;
|
|
1855
|
-
pushSuggestion(item.suggestionKey, text, severityForChecklistStatus(item.status));
|
|
1856
|
-
}
|
|
1857
|
-
}
|
|
1858
|
-
if (findings.some((finding) => finding.ruleSource === 'final_delivery_absent')) {
|
|
1859
|
-
pushSuggestion('final_delivery_absent', '补充明确的产物交付表达或交付标记,避免过程进展被当成完成。', 4);
|
|
1860
|
-
}
|
|
1861
|
-
if (findings.some((finding) => finding.ruleSource === 'tool_error_recovery')) {
|
|
1862
|
-
pushSuggestion('tool_error_recovery', '复查失败工具调用前后的执行流程,必要时把稳定路径写入能力说明文档。', 4);
|
|
1863
|
-
}
|
|
1864
|
-
if (findings.some((finding) => finding.ruleSource === 'session_interrupted')) {
|
|
1865
|
-
pushSuggestion('session_interrupted', '复查会话异常中断前后的上下文,确认是否需要补充中断恢复或重跑策略。', 4);
|
|
1866
|
-
}
|
|
1867
|
-
if (findings.some((finding) => finding.ruleSource === 'expected_tools_missed')) {
|
|
1868
|
-
pushSuggestion('expected_tools_missed', '如果能力依赖核心工具,请在能力定义里维护 expected_tools,并确认运行链路实际命中这些工具。', 4);
|
|
1869
|
-
}
|
|
1870
|
-
if (session.indicators.hardRuleTextHitCount > 0) {
|
|
1871
|
-
pushSuggestion('user_hard_rule', '把反复出现的用户硬性要求沉淀为能力规则,并在后续观测中追踪是否减少纠偏。', 2);
|
|
1872
|
-
}
|
|
1873
|
-
if (session.indicators.userCorrectionCount > 0 || session.indicators.negativeFeedbackCount > 0) {
|
|
1874
|
-
pushSuggestion('user_negative_review', '优先打开原始片段,确认用户纠正/负向反馈发生在交付前还是交付后。', 4);
|
|
1875
|
-
}
|
|
1876
|
-
if (reviewerScopeReasonCodes(session).length > 0) {
|
|
1877
|
-
pushSuggestion('complex_scope_review', '复杂链路暂按降级报告处理;后续再拆多能力、子任务或目标切换。', 1);
|
|
1878
|
-
}
|
|
1879
|
-
if (suggestions.size === 0)
|
|
1880
|
-
pushSuggestion('routine_sample', '进入常规抽样池,保留 evidenceRef 以便人工抽查。', 0);
|
|
1881
|
-
return Array.from(suggestions.values())
|
|
1882
|
-
.sort((a, b) => b.severity - a.severity || a.text.localeCompare(b.text))
|
|
1883
|
-
.map((entry) => entry.text);
|
|
1884
|
-
}
|
|
1885
|
-
function severityForChecklistStatus(status) {
|
|
1886
|
-
if (status === 'degraded')
|
|
1887
|
-
return 5;
|
|
1888
|
-
if (status === 'failed')
|
|
1889
|
-
return 4;
|
|
1890
|
-
if (status === 'unknown')
|
|
1891
|
-
return 3;
|
|
1892
|
-
if (status === 'not_declared')
|
|
1893
|
-
return 2;
|
|
1894
|
-
if (status === 'passed')
|
|
1895
|
-
return 1;
|
|
1896
|
-
return 0;
|
|
1897
|
-
}
|
|
1898
|
-
function suggestionTextForChecklistItem(key) {
|
|
1899
|
-
const suggestions = {
|
|
1900
|
-
final_delivery_absent: '在最后回复里加上「已完成 / 结果如下」之类的明确收尾,让用户知道任务跑完了。',
|
|
1901
|
-
artifact_absent: '如果 skill 应该产出文档、demo、代码或报告,最终回复里要附上文件路径、链接或代码块。',
|
|
1902
|
-
goal_shift_review: '用户中途切了目标,后续追问不属于这个 skill。看下是否要在 description 里说清楚 skill 的边界。',
|
|
1903
|
-
user_negative_or_interrupted: '用户出现了不满 / 纠正 / 叫停。先看原文是哪一步触发的,再决定改 description、补标准流程还是补硬性规则。',
|
|
1904
|
-
workflow_not_declared: '在 SKILL.md 里补一个标准流程声明,把这个 skill 的执行步骤写清楚。否则报告只能猜流程是否完整。',
|
|
1905
|
-
workflow_execution_review: '声明了标准流程但执行证据不够。补一下每个步骤的输出形态,让运行时能验证是否真的跑过。',
|
|
1906
|
-
hardrule_not_declared: '在 SKILL.md 里补硬性规则声明,把那些「必须做 / 不能做」的约束写明。',
|
|
1907
|
-
hardrule_execution_review: '声明了硬性规则但执行证据不够。补一下每条规则的触发场景,让运行时能验证。',
|
|
1908
|
-
expected_tools_not_declared: '在 SKILL.md frontmatter 里声明 expected_tools。否则报告分不出「真用上了 skill 工具」还是「只是随便调了个工具」。',
|
|
1909
|
-
expected_tools_missed: '声明了核心工具但没用上。先确认 description 是否清楚指引到这些工具,或者用户的诉求不属于这个 skill。',
|
|
1910
|
-
negative_feedback_review: '打开用户负向反馈的原文,看问题出在理解目标、执行过程还是最后没收尾。',
|
|
1911
|
-
user_correction_review: '用户纠正了多次。把纠正内容沉淀到 SKILL.md 的标准流程或硬性规则,避免下次同类返工。',
|
|
1912
|
-
follow_up_review: '用户追问比较多。看是围绕产物继续推进(好事),还是因为没拿到结果而反复问(要改)。',
|
|
1913
|
-
user_interruption_review: '用户叫停了执行。看下断的那一步是不是 skill 没声明标准流程导致跑偏。',
|
|
1914
|
-
};
|
|
1915
|
-
return suggestions[key];
|
|
1916
|
-
}
|
|
1917
|
-
function sumTokenUsage(invocations) {
|
|
1918
|
-
return invocations.reduce((sum, invocation) => ({
|
|
1919
|
-
inputTokens: sum.inputTokens + (invocation.metrics.inputTokens ?? 0),
|
|
1920
|
-
outputTokens: sum.outputTokens + (invocation.metrics.outputTokens ?? 0),
|
|
1921
|
-
cacheReadTokens: sum.cacheReadTokens + (invocation.metrics.cacheReadTokens ?? 0),
|
|
1922
|
-
cacheCreationTokens: sum.cacheCreationTokens + (invocation.metrics.cacheCreationTokens ?? 0),
|
|
1923
|
-
}), {
|
|
1924
|
-
inputTokens: 0,
|
|
1925
|
-
outputTokens: 0,
|
|
1926
|
-
cacheReadTokens: 0,
|
|
1927
|
-
cacheCreationTokens: 0,
|
|
1928
|
-
});
|
|
1929
|
-
}
|
|
1930
|
-
function summarizeExperienceSkills(sessions, invocations) {
|
|
1931
|
-
const bySkill = new Map();
|
|
1932
|
-
for (const session of sessions) {
|
|
1933
|
-
const group = bySkill.get(session.skillName) ?? [];
|
|
1934
|
-
group.push(session);
|
|
1935
|
-
bySkill.set(session.skillName, group);
|
|
1936
|
-
}
|
|
1937
|
-
const invocationCountBySkill = invocations.reduce((acc, invocation) => {
|
|
1938
|
-
acc[invocation.skillName] = (acc[invocation.skillName] ?? 0) + 1;
|
|
1939
|
-
return acc;
|
|
1940
|
-
}, {});
|
|
1941
|
-
const invocationGroupBySkill = invocations.reduce((acc, invocation) => {
|
|
1942
|
-
const group = acc.get(invocation.skillName) ?? [];
|
|
1943
|
-
group.push(invocation);
|
|
1944
|
-
acc.set(invocation.skillName, group);
|
|
1945
|
-
return acc;
|
|
1946
|
-
}, new Map());
|
|
1947
|
-
return Array.from(bySkill.entries()).map(([skillName, group]) => {
|
|
1948
|
-
const first = group[0];
|
|
1949
|
-
const skillInvocations = invocationGroupBySkill.get(skillName) ?? [];
|
|
1950
|
-
const indicators = sumIndicators(group.map((session) => session.indicators));
|
|
1951
|
-
const evidenceChain = sumEvidenceChains(group.map((session) => session.evidenceChain));
|
|
1952
|
-
const ruleFindings = mergeRuleFindings(group.flatMap((session) => session.ruleFindings));
|
|
1953
|
-
const problemPatterns = mergeExperienceProblemPatterns(group.flatMap((session) => session.problemPatterns));
|
|
1954
|
-
return {
|
|
1955
|
-
skillName,
|
|
1956
|
-
invocationCount: invocationCountBySkill[skillName] ?? 0,
|
|
1957
|
-
sessionCount: group.length,
|
|
1958
|
-
sourceKinds: unique(group.map((session) => session.sourceKind)).sort(),
|
|
1959
|
-
entrypoints: unique(group.map((session) => session.entrypoint).filter((value) => Boolean(value))).sort(),
|
|
1960
|
-
entrypointCounts: countBy(skillInvocations.map((invocation) => invocation.entrypoint ?? invocation.sourceKind ?? 'unknown')),
|
|
1961
|
-
sourceMetadataCounts: summarizeSourceMetadataCounts(skillInvocations.map((invocation) => invocation.sourceMetadata)),
|
|
1962
|
-
attributionCounts: countBy(skillInvocations.map((invocation) => invocation.attribution.source || 'unknown')),
|
|
1963
|
-
pluginNames: unique(skillInvocations.map((invocation) => invocation.attribution.pluginName).filter((value) => Boolean(value))).sort(),
|
|
1964
|
-
rawSkillRefs: unique(skillInvocations.map((invocation) => invocation.attribution.rawSkillRef).filter((value) => Boolean(value))).sort(),
|
|
1965
|
-
commandNames: unique(skillInvocations.map((invocation) => invocation.attribution.commandName).filter((value) => Boolean(value))).sort(),
|
|
1966
|
-
toolCounts: sumRecordCounts(skillInvocations.map((invocation) => invocation.toolCounts)),
|
|
1967
|
-
firstSeen: group.reduce((min, session) => session.startTimestamp < min ? session.startTimestamp : min, first.startTimestamp),
|
|
1968
|
-
lastSeen: group.reduce((max, session) => session.endTimestamp > max ? session.endTimestamp : max, first.endTimestamp),
|
|
1969
|
-
reviewFirstSessionCount: group.filter((session) => session.reviewPriority === 'review_first').length,
|
|
1970
|
-
sampleReviewSessionCount: group.filter((session) => session.reviewPriority === 'sample_review').length,
|
|
1971
|
-
indicators,
|
|
1972
|
-
evidenceChain,
|
|
1973
|
-
ruleFindings,
|
|
1974
|
-
assistiveInference: assistiveInferenceForEvidence(indicators, evidenceChain, ruleFindings),
|
|
1975
|
-
problemPatterns,
|
|
1976
|
-
relatedObservationIds: unique(group.flatMap((session) => session.relatedObservationIds)),
|
|
1977
|
-
};
|
|
1978
|
-
}).sort((a, b) => {
|
|
1979
|
-
const aScore = a.reviewFirstSessionCount * 100 + a.sampleReviewSessionCount * 10 + a.indicators.highObservationCount;
|
|
1980
|
-
const bScore = b.reviewFirstSessionCount * 100 + b.sampleReviewSessionCount * 10 + b.indicators.highObservationCount;
|
|
1981
|
-
if (bScore !== aScore)
|
|
1982
|
-
return bScore - aScore;
|
|
1983
|
-
return b.invocationCount - a.invocationCount;
|
|
1984
|
-
});
|
|
1985
|
-
}
|
|
1986
|
-
function mergeSourceMetadata(values) {
|
|
1987
|
-
const channels = unique(values.map((value) => value?.channel).filter((value) => Boolean(value)));
|
|
1988
|
-
const senders = unique(values.map((value) => value?.sender).filter((value) => Boolean(value)));
|
|
1989
|
-
const senderIds = unique(values.map((value) => value?.senderId).filter((value) => Boolean(value)));
|
|
1990
|
-
const providers = unique(values.map((value) => value?.provider).filter((value) => Boolean(value)));
|
|
1991
|
-
const models = unique(values.map((value) => value?.model).filter((value) => Boolean(value)));
|
|
1992
|
-
const modelApis = unique(values.map((value) => value?.modelApi).filter((value) => Boolean(value)));
|
|
1993
|
-
const aimaCommands = unique(values.flatMap((value) => value?.aimaCommands ?? []));
|
|
1994
|
-
const merged = {};
|
|
1995
|
-
if (channels.length > 0)
|
|
1996
|
-
merged.channel = channels.join(', ');
|
|
1997
|
-
if (senders.length > 0)
|
|
1998
|
-
merged.sender = senders.join(', ');
|
|
1999
|
-
if (senderIds.length > 0)
|
|
2000
|
-
merged.senderId = senderIds.join(', ');
|
|
2001
|
-
if (providers.length > 0)
|
|
2002
|
-
merged.provider = providers.join(', ');
|
|
2003
|
-
if (models.length > 0)
|
|
2004
|
-
merged.model = models.join(', ');
|
|
2005
|
-
if (modelApis.length > 0)
|
|
2006
|
-
merged.modelApi = modelApis.join(', ');
|
|
2007
|
-
if (aimaCommands.length > 0)
|
|
2008
|
-
merged.aimaCommands = aimaCommands.sort();
|
|
2009
|
-
return Object.keys(merged).length > 0 ? merged : undefined;
|
|
2010
|
-
}
|
|
2011
|
-
function summarizeSourceMetadataCounts(values) {
|
|
2012
|
-
return {
|
|
2013
|
-
channels: countBy(values.map((value) => value?.channel).filter((value) => Boolean(value))),
|
|
2014
|
-
senders: countBy(values.map((value) => sourceSenderLabel(value)).filter((value) => Boolean(value))),
|
|
2015
|
-
aimaCommands: countBy(values.flatMap((value) => value?.aimaCommands ?? [])),
|
|
2016
|
-
providers: countBy(values.map((value) => value?.provider).filter((value) => Boolean(value))),
|
|
2017
|
-
models: countBy(values.map((value) => value?.model).filter((value) => Boolean(value))),
|
|
2018
|
-
};
|
|
2019
|
-
}
|
|
2020
|
-
function sourceSenderLabel(value) {
|
|
2021
|
-
if (!value?.sender && !value?.senderId)
|
|
2022
|
-
return undefined;
|
|
2023
|
-
if (value.sender && value.senderId)
|
|
2024
|
-
return `${value.sender}(${value.senderId})`;
|
|
2025
|
-
return value.sender ?? value.senderId;
|
|
2026
|
-
}
|
|
2027
|
-
function scoreForIndicators(indicators) {
|
|
2028
|
-
return indicators.highObservationCount * 3
|
|
2029
|
-
+ indicators.mediumObservationCount
|
|
2030
|
-
+ indicators.userCorrectionCount * 2
|
|
2031
|
-
+ indicators.userInterruptionCount * 2
|
|
2032
|
-
+ indicators.sessionInterruptedCount * 2
|
|
2033
|
-
+ indicators.negativeFeedbackCount * 2
|
|
2034
|
-
+ indicators.hardRuleTextHitCount
|
|
2035
|
-
+ indicators.toolFailureCount
|
|
2036
|
-
+ indicators.hedgingCount
|
|
2037
|
-
+ indicators.explicitMarkerCount * 2;
|
|
2038
|
-
}
|
|
2039
|
-
function priorityForScore(score) {
|
|
2040
|
-
if (score >= 3)
|
|
2041
|
-
return 'review_first';
|
|
2042
|
-
if (score > 0)
|
|
2043
|
-
return 'sample_review';
|
|
2044
|
-
return 'routine_sample';
|
|
2045
|
-
}
|
|
2046
|
-
function priorityForReviewerFindings(session, findings) {
|
|
2047
|
-
const fallback = priorityForScore(session.reviewPriorityScore);
|
|
2048
|
-
const attentionFindings = findings.filter((finding) => finding.level === 'attention');
|
|
2049
|
-
if (attentionFindings.length === 0)
|
|
2050
|
-
return fallback;
|
|
2051
|
-
const criticalMissing = attentionFindings.some((finding) => finding.ruleSource === 'final_delivery_absent'
|
|
2052
|
-
|| finding.ruleSource === 'session_interrupted'
|
|
2053
|
-
|| finding.ruleSource === 'expected_tools_missed')
|
|
2054
|
-
|| session.indicators.userMessageCount === 0
|
|
2055
|
-
|| session.indicators.toolCallCount === 0;
|
|
2056
|
-
if (criticalMissing)
|
|
2057
|
-
return 'review_first';
|
|
2058
|
-
return fallback === 'routine_sample' ? 'sample_review' : fallback;
|
|
2059
|
-
}
|
|
2060
|
-
function basisCodesForIndicators(indicators) {
|
|
2061
|
-
const codes = [];
|
|
2062
|
-
if (indicators.highObservationCount > 0)
|
|
2063
|
-
codes.push('has_high_observation');
|
|
2064
|
-
if (indicators.mediumObservationCount > 0)
|
|
2065
|
-
codes.push('has_medium_observation');
|
|
2066
|
-
if (indicators.userCorrectionCount > 0)
|
|
2067
|
-
codes.push('user_correction');
|
|
2068
|
-
if (indicators.userInterruptionCount > 0)
|
|
2069
|
-
codes.push('user_interruption');
|
|
2070
|
-
if (indicators.sessionInterruptedCount > 0)
|
|
2071
|
-
codes.push('session_interrupted');
|
|
2072
|
-
if (indicators.negativeFeedbackCount > 0)
|
|
2073
|
-
codes.push('negative_feedback');
|
|
2074
|
-
if (indicators.hardRuleTextHitCount > 0)
|
|
2075
|
-
codes.push('hard_rule_text_hit');
|
|
2076
|
-
if (indicators.toolFailureCount > 0)
|
|
2077
|
-
codes.push('tool_failure');
|
|
2078
|
-
if (indicators.hedgingCount > 0)
|
|
2079
|
-
codes.push('hedging_signal');
|
|
2080
|
-
if (indicators.explicitMarkerCount > 0)
|
|
2081
|
-
codes.push('explicit_marker');
|
|
2082
|
-
return codes;
|
|
2083
|
-
}
|
|
2084
|
-
function countTools(segment) {
|
|
2085
|
-
const counts = {};
|
|
2086
|
-
for (const toolCall of segment.toolCalls) {
|
|
2087
|
-
counts[toolCall.tool] = (counts[toolCall.tool] ?? 0) + 1;
|
|
2088
|
-
}
|
|
2089
|
-
return counts;
|
|
2090
|
-
}
|
|
2091
|
-
function countBy(values) {
|
|
2092
|
-
const counts = {};
|
|
2093
|
-
for (const value of values) {
|
|
2094
|
-
counts[value] = (counts[value] ?? 0) + 1;
|
|
2095
|
-
}
|
|
2096
|
-
return counts;
|
|
2097
|
-
}
|
|
2098
|
-
function sumRecordCounts(values) {
|
|
2099
|
-
const counts = {};
|
|
2100
|
-
for (const value of values) {
|
|
2101
|
-
for (const [key, count] of Object.entries(value)) {
|
|
2102
|
-
counts[key] = (counts[key] ?? 0) + count;
|
|
2103
|
-
}
|
|
2104
|
-
}
|
|
2105
|
-
return counts;
|
|
2106
|
-
}
|
|
2107
|
-
function sumIndicators(values) {
|
|
2108
|
-
return values.reduce((acc, value) => ({
|
|
2109
|
-
userMessageCount: acc.userMessageCount + value.userMessageCount,
|
|
2110
|
-
userFollowUpCount: acc.userFollowUpCount + value.userFollowUpCount,
|
|
2111
|
-
userCorrectionCount: acc.userCorrectionCount + value.userCorrectionCount,
|
|
2112
|
-
userInterruptionCount: acc.userInterruptionCount + value.userInterruptionCount,
|
|
2113
|
-
sessionInterruptedCount: acc.sessionInterruptedCount + (value.sessionInterruptedCount ?? 0),
|
|
2114
|
-
negativeFeedbackCount: acc.negativeFeedbackCount + (value.negativeFeedbackCount ?? 0),
|
|
2115
|
-
positiveFeedbackCount: acc.positiveFeedbackCount + (value.positiveFeedbackCount ?? 0),
|
|
2116
|
-
userGoalShiftCount: acc.userGoalShiftCount + (value.userGoalShiftCount ?? 0),
|
|
2117
|
-
hardRuleTextHitCount: acc.hardRuleTextHitCount + value.hardRuleTextHitCount,
|
|
2118
|
-
assistantDeliverySignalCount: acc.assistantDeliverySignalCount + (value.assistantDeliverySignalCount ?? 0),
|
|
2119
|
-
deliverableArtifactSignalCount: acc.deliverableArtifactSignalCount + (value.deliverableArtifactSignalCount ?? 0),
|
|
2120
|
-
selfCorrectionCount: acc.selfCorrectionCount + (value.selfCorrectionCount ?? 0),
|
|
2121
|
-
repeatedExecutionCount: acc.repeatedExecutionCount + (value.repeatedExecutionCount ?? 0),
|
|
2122
|
-
toolCallCount: acc.toolCallCount + value.toolCallCount,
|
|
2123
|
-
toolFailureCount: acc.toolFailureCount + value.toolFailureCount,
|
|
2124
|
-
highObservationCount: acc.highObservationCount + value.highObservationCount,
|
|
2125
|
-
mediumObservationCount: acc.mediumObservationCount + value.mediumObservationCount,
|
|
2126
|
-
hedgingCount: acc.hedgingCount + value.hedgingCount,
|
|
2127
|
-
explicitMarkerCount: acc.explicitMarkerCount + value.explicitMarkerCount,
|
|
2128
|
-
}), { ...ZERO_INDICATORS });
|
|
2129
|
-
}
|
|
2130
|
-
function sumEvidenceChains(values) {
|
|
2131
|
-
return values.reduce((acc, value) => ({
|
|
2132
|
-
userMessageCount: acc.userMessageCount + (value?.userMessageCount ?? 0),
|
|
2133
|
-
runtimeContextCount: acc.runtimeContextCount + (value?.runtimeContextCount ?? 0),
|
|
2134
|
-
skillContextCount: acc.skillContextCount + (value?.skillContextCount ?? 0),
|
|
2135
|
-
assistantMessageCount: acc.assistantMessageCount + (value?.assistantMessageCount ?? 0),
|
|
2136
|
-
toolUseCount: acc.toolUseCount + (value?.toolUseCount ?? 0),
|
|
2137
|
-
toolResultCount: acc.toolResultCount + (value?.toolResultCount ?? 0),
|
|
2138
|
-
toolFailureResultCount: acc.toolFailureResultCount + (value?.toolFailureResultCount ?? 0),
|
|
2139
|
-
observationCount: acc.observationCount + (value?.observationCount ?? 0),
|
|
2140
|
-
firstUserMessage: acc.firstUserMessage ?? value?.firstUserMessage,
|
|
2141
|
-
firstRuntimeContext: acc.firstRuntimeContext ?? value?.firstRuntimeContext,
|
|
2142
|
-
firstSkillContext: acc.firstSkillContext ?? value?.firstSkillContext,
|
|
2143
|
-
firstToolUse: acc.firstToolUse ?? value?.firstToolUse,
|
|
2144
|
-
firstToolFailure: acc.firstToolFailure ?? value?.firstToolFailure,
|
|
2145
|
-
lastAssistantMessage: value?.lastAssistantMessage ?? acc.lastAssistantMessage,
|
|
2146
|
-
}), {
|
|
2147
|
-
userMessageCount: 0,
|
|
2148
|
-
runtimeContextCount: 0,
|
|
2149
|
-
skillContextCount: 0,
|
|
2150
|
-
assistantMessageCount: 0,
|
|
2151
|
-
toolUseCount: 0,
|
|
2152
|
-
toolResultCount: 0,
|
|
2153
|
-
toolFailureResultCount: 0,
|
|
2154
|
-
observationCount: 0,
|
|
2155
|
-
});
|
|
2156
|
-
}
|
|
2157
|
-
function mergeRuleFindings(values) {
|
|
2158
|
-
const byCode = new Map();
|
|
2159
|
-
for (const value of values) {
|
|
2160
|
-
const existing = byCode.get(value.code);
|
|
2161
|
-
if (existing) {
|
|
2162
|
-
existing.count += value.count;
|
|
2163
|
-
existing.evidenceRefs = uniqueEvidenceRefs([...existing.evidenceRefs, ...value.evidenceRefs]).slice(0, 5);
|
|
2164
|
-
}
|
|
2165
|
-
else {
|
|
2166
|
-
byCode.set(value.code, { ...value, evidenceRefs: uniqueEvidenceRefs(value.evidenceRefs).slice(0, 5) });
|
|
2167
|
-
}
|
|
2168
|
-
}
|
|
2169
|
-
return Array.from(byCode.values()).sort((a, b) => {
|
|
2170
|
-
const rank = { attention: 0, sample: 1, normal: 2 };
|
|
2171
|
-
if (rank[a.level] !== rank[b.level])
|
|
2172
|
-
return rank[a.level] - rank[b.level];
|
|
2173
|
-
return b.count - a.count;
|
|
2174
|
-
});
|
|
2175
|
-
}
|
|
2176
|
-
function uniqueTimelineEvents(events) {
|
|
2177
|
-
const byId = new Map();
|
|
2178
|
-
for (const event of events) {
|
|
2179
|
-
byId.set(event.id, event);
|
|
2180
|
-
}
|
|
2181
|
-
return Array.from(byId.values());
|
|
2182
|
-
}
|
|
2183
|
-
function compareTimelineEvents(a, b) {
|
|
2184
|
-
const ta = a.timestamp;
|
|
2185
|
-
const tb = b.timestamp;
|
|
2186
|
-
// 双方都有非空 timestamp 且不同 → 按时间穿插(主线 + subagent 真实交互序)
|
|
2187
|
-
if (ta && tb && ta !== tb) {
|
|
2188
|
-
return ta.localeCompare(tb);
|
|
2189
|
-
}
|
|
2190
|
-
// 同一条 trace 内 → 按 messageIndex 派生的 order(跨 trace 比 order 没意义)
|
|
2191
|
-
if (a.sourceTrace === b.sourceTrace) {
|
|
2192
|
-
return a.order - b.order;
|
|
2193
|
-
}
|
|
2194
|
-
// 跨 trace 且 timestamp 不可比 → 主线优先(避免缺 timestamp 时 subagent 顶到最前)
|
|
2195
|
-
const roleRank = (event) => event.traceRole === 'main' || event.traceRole === 'standalone' ? 0 : 1;
|
|
2196
|
-
const rankDiff = roleRank(a) - roleRank(b);
|
|
2197
|
-
if (rankDiff !== 0)
|
|
2198
|
-
return rankDiff;
|
|
2199
|
-
// 同 traceRole 跨文件兜底:sourceTrace 字典序保证稳定
|
|
2200
|
-
return a.sourceTrace.localeCompare(b.sourceTrace);
|
|
2201
|
-
}
|
|
2202
|
-
function buildSessionTimelineTree(sessionId, sessions) {
|
|
2203
|
-
const mainSession = sessions.find((session) => session.traceRole === 'main')
|
|
2204
|
-
?? sessions.find((session) => session.traceRole === 'standalone');
|
|
2205
|
-
const main = mainSession ? buildTimelineWindow(mainSession, 0, mainSession.records.length) : [];
|
|
2206
|
-
const branches = sessions
|
|
2207
|
-
.filter((session) => !mainSession || session !== mainSession)
|
|
2208
|
-
.map((session) => {
|
|
2209
|
-
const events = buildTimelineWindow(session, 0, session.records.length);
|
|
2210
|
-
const attachTo = inferSubagentAttachment(main, session);
|
|
2211
|
-
return {
|
|
2212
|
-
id: hashParts('timeline-branch', session.sourcePath),
|
|
2213
|
-
label: session.traceLabel ?? session.sourcePath.split('/').pop() ?? 'subagent',
|
|
2214
|
-
sourceTrace: session.sourcePath,
|
|
2215
|
-
traceRole: session.traceRole ?? 'subagent',
|
|
2216
|
-
attachTo,
|
|
2217
|
-
events,
|
|
2218
|
-
};
|
|
2219
|
-
});
|
|
2220
|
-
return {
|
|
2221
|
-
sessionId,
|
|
2222
|
-
main,
|
|
2223
|
-
branches,
|
|
2224
|
-
};
|
|
2225
|
-
}
|
|
2226
|
-
function inferSubagentAttachment(mainEvents, branchSession) {
|
|
2227
|
-
const startedAt = branchSession.startTimestamp;
|
|
2228
|
-
const taskUses = mainEvents.filter((event) => event.kind === 'tool_use' && /^(Task|Agent|Skill)$/i.test(event.toolName ?? ''));
|
|
2229
|
-
const candidates = startedAt
|
|
2230
|
-
? taskUses.filter((event) => !event.timestamp || event.timestamp <= startedAt)
|
|
2231
|
-
: taskUses;
|
|
2232
|
-
const event = candidates.at(-1) ?? taskUses.at(-1);
|
|
2233
|
-
if (!event)
|
|
2234
|
-
return undefined;
|
|
2235
|
-
return {
|
|
2236
|
-
sourceTrace: event.sourceTrace,
|
|
2237
|
-
messageIndex: event.messageIndex,
|
|
2238
|
-
toolUseId: event.toolUseId,
|
|
2239
|
-
label: event.toolName,
|
|
2240
|
-
};
|
|
2241
|
-
}
|
|
2242
|
-
function minDefined(values) {
|
|
2243
|
-
const filtered = values.filter((value) => typeof value === 'number');
|
|
2244
|
-
return filtered.length > 0 ? Math.min(...filtered) : undefined;
|
|
2245
|
-
}
|
|
2246
|
-
function maxDefined(values) {
|
|
2247
|
-
const filtered = values.filter((value) => typeof value === 'number');
|
|
2248
|
-
return filtered.length > 0 ? Math.max(...filtered) : undefined;
|
|
2249
|
-
}
|
|
2250
|
-
function minString(values) {
|
|
2251
|
-
const filtered = values.filter((value) => Boolean(value));
|
|
2252
|
-
return filtered.length > 0 ? filtered.reduce((min, value) => value < min ? value : min, filtered[0]) : undefined;
|
|
2253
|
-
}
|
|
2254
|
-
function maxString(values) {
|
|
2255
|
-
const filtered = values.filter((value) => Boolean(value));
|
|
2256
|
-
return filtered.length > 0 ? filtered.reduce((max, value) => value > max ? value : max, filtered[0]) : undefined;
|
|
2257
|
-
}
|
|
2258
|
-
function uniqueEvidenceRefs(refs) {
|
|
2259
|
-
const byId = new Map();
|
|
2260
|
-
for (const ref of refs) {
|
|
2261
|
-
byId.set(ref.id, ref);
|
|
2262
|
-
}
|
|
2263
|
-
return Array.from(byId.values());
|
|
2264
|
-
}
|
|
2265
|
-
function inferUserGoal(userRefs) {
|
|
2266
|
-
const first = userRefs.find((ref) => ref.snippet && !ref.snippet.includes('tool_result'));
|
|
2267
|
-
return snippet(first?.snippet, 180);
|
|
2268
|
-
}
|
|
2269
|
-
export function findUserCorrectionMatches(value) {
|
|
2270
|
-
const ranges = [];
|
|
2271
|
-
for (const term of PHRASE_USER_CORRECTION_TERMS) {
|
|
2272
|
-
pushTermMatches(value, term, ranges, false);
|
|
2273
|
-
}
|
|
2274
|
-
for (const term of BOUNDED_USER_CORRECTION_TERMS) {
|
|
2275
|
-
pushTermMatches(value, term, ranges, true);
|
|
2276
|
-
}
|
|
2277
|
-
return ranges.sort((a, b) => a.start - b.start);
|
|
2278
|
-
}
|
|
2279
|
-
export function hasUserCorrectionSignal(value) {
|
|
2280
|
-
return findUserCorrectionMatches(value).length > 0;
|
|
2281
|
-
}
|
|
2282
|
-
export function findUserGoalShiftMatches(value) {
|
|
2283
|
-
const ranges = [];
|
|
2284
|
-
for (const term of USER_GOAL_SHIFT_TERMS) {
|
|
2285
|
-
pushTermMatches(value, term, ranges, false);
|
|
2286
|
-
}
|
|
2287
|
-
return ranges.sort((a, b) => a.start - b.start);
|
|
2288
|
-
}
|
|
2289
|
-
export function hasUserGoalShiftSignal(value) {
|
|
2290
|
-
return findUserGoalShiftMatches(value).length > 0;
|
|
2291
|
-
}
|
|
2292
|
-
export function findNegativeFeedbackMatches(value) {
|
|
2293
|
-
const ranges = [];
|
|
2294
|
-
for (const term of [...NEGATIVE_FEEDBACK_TERMS, ...ADDITIONAL_NEGATIVE_FEEDBACK_TERMS].sort((a, b) => b.length - a.length)) {
|
|
2295
|
-
pushTermMatches(value, term, ranges, false);
|
|
2296
|
-
}
|
|
2297
|
-
for (const term of [...BOUNDED_NEGATIVE_FEEDBACK_TERMS].sort((a, b) => b.length - a.length)) {
|
|
2298
|
-
pushTermMatches(value, term, ranges, true);
|
|
2299
|
-
}
|
|
2300
|
-
return ranges.sort((a, b) => a.start - b.start);
|
|
2301
|
-
}
|
|
2302
|
-
export function hasNegativeFeedbackSignal(value) {
|
|
2303
|
-
return findNegativeFeedbackMatches(value).length > 0;
|
|
2304
|
-
}
|
|
2305
|
-
export function findPositiveFeedbackMatches(value) {
|
|
2306
|
-
const ranges = [];
|
|
2307
|
-
for (const term of POSITIVE_FEEDBACK_TERMS) {
|
|
2308
|
-
pushTermMatches(value, term, ranges, false, true);
|
|
2309
|
-
}
|
|
2310
|
-
return ranges.sort((a, b) => a.start - b.start);
|
|
2311
|
-
}
|
|
2312
|
-
export function hasPositiveFeedbackSignal(value) {
|
|
2313
|
-
return findPositiveFeedbackMatches(value).length > 0;
|
|
2314
|
-
}
|
|
2315
|
-
function pushTermMatches(value, term, ranges, requireBoundary, caseInsensitive = false) {
|
|
2316
|
-
const haystack = caseInsensitive ? value.toLowerCase() : value;
|
|
2317
|
-
const needle = caseInsensitive ? term.toLowerCase() : term;
|
|
2318
|
-
let index = haystack.indexOf(needle);
|
|
2319
|
-
while (index >= 0) {
|
|
2320
|
-
const end = index + needle.length;
|
|
2321
|
-
if ((!requireBoundary || (isTextBoundary(value[index - 1]) && isTextBoundary(value[end])))
|
|
2322
|
-
&& !ranges.some((range) => index < range.end && end > range.start)) {
|
|
2323
|
-
ranges.push({ start: index, end });
|
|
2324
|
-
}
|
|
2325
|
-
index = haystack.indexOf(needle, index + needle.length);
|
|
2326
|
-
}
|
|
2327
|
-
}
|
|
2328
|
-
function isTextBoundary(value) {
|
|
2329
|
-
if (value === undefined)
|
|
2330
|
-
return true;
|
|
2331
|
-
return TEXT_BOUNDARY_CHARS.has(value);
|
|
2332
|
-
}
|
|
2333
|
-
function isSkillContextRecord(record, text) {
|
|
2334
|
-
const meta = record;
|
|
2335
|
-
if (meta.isMeta === true && typeof meta.sourceToolUseID === 'string')
|
|
2336
|
-
return true;
|
|
2337
|
-
return /^Base directory for this skill:\s+.+(?:\n| )#\s+[a-z0-9][\w.-]*/i.test(text);
|
|
2338
|
-
}
|
|
2339
|
-
function isRuntimeContextRecord(record, text) {
|
|
2340
|
-
const meta = record;
|
|
2341
|
-
if (isRuntimeProtocolPromptText(text))
|
|
2342
|
-
return true;
|
|
2343
|
-
if (/^Conversation info \(untrusted metadata\):\s*```json/i.test(text))
|
|
2344
|
-
return true;
|
|
2345
|
-
if (meta.entrypoint !== 'sdk-ts' || typeof meta.promptId !== 'string')
|
|
2346
|
-
return false;
|
|
2347
|
-
return /^进入.+流程。当前页面已经完成本地工作区恢复/.test(text)
|
|
2348
|
-
|| /gui-workflow route/.test(text)
|
|
2349
|
-
|| /当前页面已经完成本地工作区恢复/.test(text);
|
|
2350
|
-
}
|
|
2351
|
-
function timestampOf(record) {
|
|
2352
|
-
if (!record || typeof record !== 'object')
|
|
2353
|
-
return undefined;
|
|
2354
|
-
const value = record.timestamp;
|
|
2355
|
-
return typeof value === 'string' ? value : undefined;
|
|
2356
|
-
}
|
|
2357
|
-
function sourceKindForPath(path) {
|
|
2358
|
-
if (path.includes('/openclaw') || path.includes('/.openclaw/'))
|
|
2359
|
-
return 'openclaw';
|
|
2360
|
-
if (path.endsWith('.jsonl'))
|
|
2361
|
-
return 'claude';
|
|
2362
|
-
if (path.endsWith('.log'))
|
|
2363
|
-
return 'markdown_log';
|
|
2364
|
-
return 'unknown';
|
|
2365
|
-
}
|
|
2366
|
-
function inferEntrypointFromRecords(session) {
|
|
2367
|
-
for (const record of session.records) {
|
|
2368
|
-
if (!record || typeof record !== 'object')
|
|
2369
|
-
continue;
|
|
2370
|
-
const entrypoint = record.entrypoint;
|
|
2371
|
-
if (typeof entrypoint === 'string' && entrypoint.trim())
|
|
2372
|
-
return entrypoint;
|
|
2373
|
-
}
|
|
2374
|
-
if (session.entrypoint)
|
|
2375
|
-
return session.entrypoint;
|
|
2376
|
-
if (session.sourceKind === 'openclaw')
|
|
2377
|
-
return 'openclaw';
|
|
2378
|
-
if (session.sourceKind === 'markdown_log')
|
|
2379
|
-
return 'markdown_log';
|
|
2380
|
-
if (session.sourcePath.endsWith('.log'))
|
|
2381
|
-
return 'markdown_log';
|
|
2382
|
-
return undefined;
|
|
2383
|
-
}
|
|
2384
|
-
function snippet(value, max = 240) {
|
|
2385
|
-
const text = typeof value === 'string' ? value : String(value ?? '');
|
|
2386
|
-
const normalized = text.replace(/\s+/g, ' ').trim();
|
|
2387
|
-
return normalized ? normalized.slice(0, max) : undefined;
|
|
2388
|
-
}
|
|
2389
|
-
function fullText(value) {
|
|
2390
|
-
const text = typeof value === 'string' ? value : String(value ?? '');
|
|
2391
|
-
const normalized = text.trim();
|
|
2392
|
-
return normalized || undefined;
|
|
2393
|
-
}
|
|
2394
|
-
function unique(values) {
|
|
2395
|
-
return Array.from(new Set(values));
|
|
2396
|
-
}
|
|
2397
|
-
function hashParts(...parts) {
|
|
2398
|
-
return createHash('sha256').update(parts.join('\u0000')).digest('hex').slice(0, 16);
|
|
2399
|
-
}
|
|
2400
|
-
//# sourceMappingURL=experience.js.map
|