@khoavu882/doflow 2.0.0-beta.5 → 2.0.1
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 +16 -16
- package/bin/doflow.js +22 -12
- package/core/.antigravity-plugin/plugin.json +1 -2
- package/core/.claude-plugin/plugin.json +1 -1
- package/core/.codex-plugin/plugin.json +1 -1
- package/core/.plugin/plugin.json +1 -1
- package/core/harnesses/claude/hooks/lib.sh +43 -24
- package/core/harnesses/claude/hooks/mcp-tool-guard.sh +4 -1
- package/core/harnesses/claude/hooks/permission-audit.sh +3 -0
- package/core/harnesses/claude/hooks/post-compact.sh +35 -32
- package/core/harnesses/claude/hooks/post-edit-lint.sh +2 -0
- package/core/harnesses/claude/hooks/post-shell-observe.sh +48 -0
- package/core/harnesses/claude/hooks/post-tool-failure.sh +3 -0
- package/core/harnesses/claude/hooks/pre-compact.sh +23 -27
- package/core/harnesses/claude/hooks/pre-implement-gate.sh +4 -1
- package/core/harnesses/claude/hooks/session-end.sh +23 -10
- package/core/harnesses/claude/hooks/skill-config-audit.sh +3 -0
- package/core/harnesses/claude/settings/settings.json +26 -9
- package/core/harnesses/claude/statusline/doflow-statusline.sh +1 -0
- package/core/harnesses/codex/agents/core-implementer.toml +1 -0
- package/core/harnesses/codex/agents/delivery-lead.toml +10 -0
- package/core/harnesses/codex/agents/quality-guardian.toml +1 -1
- package/core/harnesses/codex/agents/research-writer.toml +1 -1
- package/core/harnesses/codex/agents/reviewer.toml +10 -0
- package/core/harnesses/codex/agents/spec-analyst.toml +1 -1
- package/core/harnesses/codex/agents/system-architect.toml +1 -1
- package/core/harnesses/codex/hooks/hooks.json +0 -10
- package/core/harnesses/codex/hooks/lib.sh +44 -25
- package/core/harnesses/codex/hooks/mcp-tool-guard.sh +4 -1
- package/core/harnesses/codex/hooks/post-edit-lint.impl.sh +3 -1
- package/core/harnesses/codex/hooks/pre-compact.impl.sh +29 -26
- package/core/harnesses/codex/hooks/pre-implement-gate.sh +4 -1
- package/core/harnesses/codex/hooks/session-end.impl.sh +23 -10
- package/core/harnesses/codex/hooks/subagent-audit.sh +1 -0
- package/core/harnesses/copilot/hooks/doflow-lib.sh +94 -0
- package/core/harnesses/copilot/hooks/doflow-mcp-tool-guard.sh +9 -0
- package/core/harnesses/copilot/hooks/doflow-pre-implement-gate.sh +9 -0
- package/core/harnesses/copilot/hooks/doflow-session-start.sh +9 -0
- package/core/harnesses/copilot/hooks/doflow-stop-check.sh +9 -0
- package/core/harnesses/copilot/hooks/doflow-subagent-start.sh +9 -0
- package/core/harnesses/copilot/hooks/doflow-subagent-stop.sh +9 -0
- package/core/harnesses/copilot/hooks/doflow.json +51 -0
- package/core/harnesses/kiro/agents/doflow.json +1 -11
- package/core/harnesses/kiro/hooks/doflow.json +0 -10
- package/core/harnesses/kiro/hooks/lib.sh +26 -6
- package/core/harnesses/kiro/hooks/mcp-tool-guard.sh +8 -3
- package/core/harnesses/kiro/hooks/pre-implement-gate.sh +8 -3
- package/core/harnesses/kiro/hooks/session-start.sh +1 -0
- package/core/harnesses/kiro/hooks/stop-check.sh +1 -0
- package/core/harnesses/pi/extensions/doflow-guard.js +11 -2
- package/core/harnesses/shared/hooks/ENVELOPE_MIGRATION.md +1 -2
- package/core/harnesses/shared/hooks/adapters/antigravity.js +1 -1
- package/core/harnesses/shared/hooks/bridge/bridge.sh +126 -23
- package/core/harnesses/shared/hooks/bridge/envelope.jq +87 -18
- package/core/harnesses/shared/hooks/bridge/observe-model.sh +75 -0
- package/core/harnesses/shared/hooks/bridge/respond.sh +16 -2
- package/core/harnesses/shared/hooks/policies/capture-failure.sh +49 -16
- package/core/harnesses/shared/hooks/policies/compact-text.sh +46 -0
- package/core/harnesses/shared/hooks/policies/contract.sh +3 -0
- package/core/harnesses/shared/hooks/policies/deny-json.sh +20 -7
- package/core/harnesses/shared/hooks/policies/emission-rules.sh +37 -0
- package/core/harnesses/shared/hooks/policies/emission.jq +209 -0
- package/core/harnesses/shared/hooks/policies/emission.sh +383 -0
- package/core/harnesses/shared/hooks/policies/identity.sh +177 -0
- package/core/harnesses/shared/hooks/policies/lib.sh +63 -40
- package/core/harnesses/shared/hooks/policies/mcp-policy.conf +1 -1
- package/core/harnesses/shared/hooks/policies/mcp-tool-guard.sh +7 -8
- package/core/harnesses/shared/hooks/policies/pre-implementation-gate.sh +132 -57
- package/core/harnesses/shared/hooks/policies/session-context.sh +30 -1
- package/core/harnesses/shared/hooks/policies/stop-check.sh +27 -15
- package/core/harnesses/shared/hooks/policies/subagent-audit.sh +6 -3
- package/core/harnesses/shared/hooks/policies/summary-store.sh +347 -0
- package/core/harnesses/shared/hooks/policies/user-prompt-submit.sh +60 -155
- package/core/harnesses/shared/hooks/stream-hook-runner.js +58 -20
- package/core/harnesses/shared/locator/doflow-run +2 -3
- package/core/registry/advice.json +3 -3
- package/core/registry/assets.json +55 -82
- package/core/registry/capabilities.json +12 -0
- package/core/registry/contracts.json +58 -31
- package/core/registry/contribution-points.json +35 -0
- package/core/registry/gates.json +32 -0
- package/core/registry/guidance-caps.json +40 -0
- package/core/registry/harnesses.json +1445 -366
- package/core/registry/intake.json +53 -0
- package/core/registry/lifecycle.json +599 -996
- package/core/registry/mcp.json +5 -1
- package/core/registry/models.json +7 -1
- package/core/registry/package-templates/README.md +19 -0
- package/core/registry/package-templates/agent/files/agent.md +9 -0
- package/core/registry/package-templates/agent/template.json +4 -0
- package/core/registry/package-templates/capability-provider/files/provider.json +9 -0
- package/core/registry/package-templates/capability-provider/template.json +11 -0
- package/core/registry/package-templates/debate-preset/files/preset.json +26 -0
- package/core/registry/package-templates/debate-preset/template.json +4 -0
- package/core/registry/package-templates/intake-category/files/category.json +8 -0
- package/core/registry/package-templates/intake-category/template.json +4 -0
- package/core/registry/package-templates/review-preset/files/preset.json +30 -0
- package/core/registry/package-templates/review-preset/template.json +4 -0
- package/core/registry/package-templates/skill/files/SKILL.md +8 -0
- package/core/registry/package-templates/skill/template.json +4 -0
- package/core/registry/package-templates/worker/files/worker.json +92 -0
- package/core/registry/package-templates/worker/template.json +11 -0
- package/core/registry/packages/doflow/doflow-package.json +15 -0
- package/core/registry/packages/doflow/presets/debate-3.json +26 -0
- package/core/registry/protocols.json +61 -0
- package/core/registry/routes.json +17 -0
- package/core/registry/rules.json +431 -0
- package/core/registry/settings.json +272 -0
- package/core/registry/storage.json +687 -31
- package/core/registry/telemetry.json +236 -0
- package/core/registry/transcripts.json +142 -0
- package/core/registry/verification.json +76 -6
- package/core/registry/workflows.json +55 -0
- package/core/shared/agent-specs/core-implementer.md +3 -0
- package/core/shared/agent-specs/delivery-lead.md +68 -0
- package/core/shared/agent-specs/quality-guardian.md +5 -1
- package/core/shared/agent-specs/research-writer.md +10 -3
- package/core/shared/agent-specs/reviewer.md +53 -0
- package/core/shared/agent-specs/spec-analyst.md +5 -6
- package/core/shared/agent-specs/system-architect.md +5 -1
- package/core/shared/guidance/DOFLOW_CORE.md +1 -5
- package/core/shared/guidance/modes/MODE_DeepResearch.md +1 -1
- package/core/shared/guidance/modes/MODE_Orchestration.md +4 -3
- package/core/shared/guidance/modes/MODE_Task_Management.md +14 -14
- package/core/shared/guidance/pointers/codex.md +1 -4
- package/core/shared/guidance/references/ARTIFACT_FORMAT.md +30 -16
- package/core/shared/guidance/references/ARTIFACT_VOICE.md +3 -2
- package/core/shared/guidance/references/CONSTITUTION_BASE.md +17 -15
- package/core/shared/guidance/references/DIAGRAM_GUIDE.md +1 -1
- package/core/shared/guidance/references/DOFLOW_CHAIN.md +17 -19
- package/core/shared/guidance/references/EVIDENCE_LEDGER.md +7 -8
- package/core/shared/guidance/references/MODEL_SELECTION.md +5 -3
- package/core/shared/guidance/references/ORCHESTRATION.md +3 -2
- package/core/shared/guidance/references/WORKFLOW_HANDOFF.md +19 -1
- package/core/shared/guidance/rules/RULES.md +45 -0
- package/core/shared/scripts/doflow/bash/do-args.sh +37 -0
- package/core/shared/scripts/doflow/bash/do-exec-paths.sh +4 -0
- package/core/shared/scripts/doflow/bash/do-git-state.sh +15 -4
- package/core/shared/scripts/doflow/bash/do-parallel-check.sh +4 -0
- package/core/shared/scripts/doflow/bash/do-paths.sh +40 -2
- package/core/shared/scripts/doflow/bash/do-prereqs.sh +2 -1
- package/core/shared/scripts/doflow/bash/do-review-package.sh +4 -0
- package/core/shared/scripts/doflow/bash/do-task-brief.sh +58 -16
- package/core/shared/scripts/doflow/bash/render-audit.sh +26 -2
- package/core/shared/scripts/doflow/bash/render-diagrams.sh +1 -0
- package/core/shared/scripts/doflow/bash/render-puml.sh +2 -1
- package/core/shared/scripts/doflow/bash/validate-artifacts.sh +49 -5
- package/core/shared/scripts/doflow/bin/doflow-run +152 -34
- package/core/shared/skills/do/SKILL.md +14 -12
- package/core/shared/skills/do/references/advice_calls.md +26 -0
- package/core/shared/skills/do/references/pm_routing.md +1 -2
- package/core/shared/skills/do/references/program_mode.md +31 -0
- package/core/shared/skills/do-brainstorm/SKILL.md +45 -97
- package/core/shared/skills/do-brainstorm/references/handoff_branches.md +36 -0
- package/core/shared/skills/do-brainstorm/references/intent_seed.md +21 -0
- package/core/shared/skills/do-brainstorm/references/round_log.md +17 -0
- package/core/shared/skills/do-code-review/SKILL.md +48 -148
- package/core/shared/skills/do-code-review/content-types/markdown.md +24 -2
- package/core/shared/skills/do-code-review/references/tools.md +90 -0
- package/core/shared/skills/do-code-review/scripts/doc_quality_checker.py +549 -7
- package/core/shared/skills/do-design/SKILL.md +23 -20
- package/core/shared/skills/do-diagnose/SKILL.md +18 -6
- package/core/shared/skills/do-document/SKILL.md +12 -1
- package/core/shared/skills/do-document/references/deep_research.md +1 -2
- package/core/shared/skills/do-document/references/embedded-research.md +19 -7
- package/core/shared/skills/do-document/references/implementation-flow.md +5 -6
- package/core/shared/skills/do-execute-plan/SKILL.md +19 -60
- package/core/shared/skills/do-execute-plan/references/handoff_record.md +7 -2
- package/core/shared/skills/do-execute-plan/references/parallel_dispatch.md +13 -0
- package/core/shared/skills/do-execute-plan/references/readiness_gate.md +26 -1
- package/core/shared/skills/do-execute-plan/references/run_position.md +16 -2
- package/core/shared/skills/do-execute-plan/references/scaffold.md +17 -9
- package/core/shared/skills/do-execute-plan/references/state_checkpoint.md +11 -0
- package/core/shared/skills/do-execute-plan/references/task_attempts.md +78 -24
- package/core/shared/skills/do-flow/SKILL.md +10 -11
- package/core/shared/skills/do-flow/references/task_classes.md +5 -5
- package/core/shared/skills/do-git/SKILL.md +4 -0
- package/core/shared/skills/do-implement/SKILL.md +13 -14
- package/core/shared/skills/do-plan/SKILL.md +34 -20
- package/core/shared/skills/do-test/SKILL.md +7 -4
- package/core/shared/templates/doflow/constitution-template.md +9 -3
- package/core/shared/templates/doflow/data-model-template.md +1 -1
- package/core/shared/templates/doflow/design-template.md +113 -16
- package/core/shared/templates/doflow/plan-template.md +11 -10
- package/core/shared/templates/doflow/question-log-template.md +14 -2
- package/core/shared/templates/doflow/requirement-template.md +1 -1
- package/core/shared/workflows/do-flow-chain.md +2 -0
- package/core/worker-evidence/antigravity/checks.json +14 -0
- package/core/worker-evidence/codex/2026-10-18-cli-check.json +107 -0
- package/core/worker-evidence/codex/2026-10-18-live-run-edit.json +73 -0
- package/core/worker-evidence/codex/2026-10-18-live-run-read-only.json +62 -0
- package/core/worker-evidence/codex/2026-10-24-cli-check.json +126 -0
- package/core/worker-evidence/codex/checks.json +38 -0
- package/package.json +10 -6
- package/src/adapters/antigravity/index.js +143 -66
- package/src/adapters/claude/index.js +46 -5
- package/src/adapters/codex/agents.js +25 -15
- package/src/adapters/codex/hooks.js +39 -3
- package/src/adapters/codex/index.js +61 -13
- package/src/adapters/codex/native-projection.js +6 -2
- package/src/adapters/copilot/index.js +58 -23
- package/src/adapters/copy-tree.js +291 -46
- package/src/adapters/guidance-manifest.js +71 -0
- package/src/adapters/guidance-pointer.js +19 -0
- package/src/adapters/hook-commands.js +6 -10
- package/src/adapters/index.js +1 -0
- package/src/adapters/kiro/index.js +23 -12
- package/src/adapters/opencode/index.js +8 -8
- package/src/adapters/pi/hooks.js +2 -1
- package/src/adapters/pi/index.js +14 -7
- package/src/adapters/resolve-source.js +26 -2
- package/src/cli/commands/install.js +2 -1
- package/src/cli/commands/reconcile.js +53 -9
- package/src/cli/commands/remove.js +2 -2
- package/src/cli/commands/rollback.js +6 -3
- package/src/cli/commands/self-update.js +18 -9
- package/src/cli/commands/status.js +22 -3
- package/src/cli/commands/ui.js +99 -0
- package/src/cli/commands/update.js +2 -1
- package/src/cli/index.js +337 -32
- package/src/cli/runtime-commands.js +220 -60
- package/src/cli/shared.js +0 -2
- package/src/helper/git.js +1 -1
- package/src/helper/guardrails.js +1 -1
- package/src/helper/marker-merge.js +31 -13
- package/src/helper/package-ids.js +37 -0
- package/src/helper/semver.js +94 -0
- package/src/install/backup.js +105 -15
- package/src/install/context.js +1 -1
- package/src/install/targets.js +31 -16
- package/src/lifecycle/coverage.js +4 -16
- package/src/lifecycle/hook-tier.js +160 -0
- package/src/lifecycle/index.js +412 -78
- package/src/lifecycle/retired-harnesses.js +318 -0
- package/src/lifecycle/view.js +35 -15
- package/src/registry/index.js +551 -26
- package/src/registry/worker-ids.js +45 -0
- package/src/release/build-package.js +0 -3
- package/src/release/docs-blocks.js +472 -0
- package/src/release/preflight.js +425 -0
- package/src/release/rehearse.js +401 -0
- package/src/release/release-workflow.js +733 -0
- package/src/release/sync-plugin-versions.js +43 -7
- package/src/runtime/advice/bench-gate.js +25 -0
- package/src/runtime/advice/cli.js +59 -16
- package/src/runtime/advice/client.js +32 -9
- package/src/runtime/advice/config.js +98 -133
- package/src/runtime/advice/doctor.js +1 -1
- package/src/runtime/advice/elevation.js +97 -0
- package/src/runtime/advice/endpoint-guard.js +9 -3
- package/src/runtime/advice/mode.js +37 -0
- package/src/runtime/advice/record.js +18 -5
- package/src/runtime/advice/registry.js +4 -1
- package/src/runtime/advice/shadow-config.js +229 -0
- package/src/runtime/advice/shadow-dispatcher.js +276 -0
- package/src/runtime/brief-rules.js +81 -0
- package/src/runtime/brief-tools.js +111 -34
- package/src/runtime/candidate.js +20 -11
- package/src/runtime/capabilities/executor.js +450 -0
- package/src/runtime/capabilities/loopback.js +41 -0
- package/src/runtime/capabilities/sanitizer.js +88 -0
- package/src/runtime/capability-router.js +135 -3
- package/src/runtime/checkouts.js +73 -11
- package/src/runtime/claims.js +13 -7
- package/src/runtime/cli.js +196 -19
- package/src/runtime/config-home.js +42 -0
- package/src/runtime/context/arbitrate.js +767 -0
- package/src/runtime/context/delivery-store.js +4 -6
- package/src/runtime/context/emission-rules.js +118 -0
- package/src/runtime/context/identity.js +227 -0
- package/src/runtime/context/pointer.js +67 -12
- package/src/runtime/context/primary-command.js +117 -0
- package/src/runtime/context/primary.js +344 -0
- package/src/runtime/context/summary-store.js +655 -0
- package/src/runtime/context-pack.js +158 -79
- package/src/runtime/decision-register.js +13 -4
- package/src/runtime/dispatch/admission.js +392 -0
- package/src/runtime/dispatch/attempt-end.js +274 -0
- package/src/runtime/dispatch/command.js +628 -0
- package/src/runtime/dispatch/controls.js +904 -0
- package/src/runtime/dispatch/envelope.js +276 -0
- package/src/runtime/dispatch/grants.js +310 -0
- package/src/runtime/dispatch/integrate.js +617 -0
- package/src/runtime/dispatch/loop.js +1835 -0
- package/src/runtime/dispatch/store.js +352 -0
- package/src/runtime/dispatch/verify-run.js +201 -0
- package/src/runtime/evidence-ledger.js +52 -7
- package/src/runtime/failure/capture.js +3 -1
- package/src/runtime/failure/cli.js +25 -9
- package/src/runtime/failure/home.js +57 -30
- package/src/runtime/failure/store.js +7 -2
- package/src/runtime/feature-pointer.js +174 -0
- package/src/runtime/feature-resolve.js +13 -2
- package/src/runtime/fleet/command.js +77 -0
- package/src/runtime/fleet/projects.js +178 -0
- package/src/runtime/fleet/tree.js +383 -0
- package/src/runtime/freshness.js +33 -3
- package/src/runtime/git-memo.js +46 -0
- package/src/runtime/guidance/ablation.js +427 -0
- package/src/runtime/health.js +624 -18
- package/src/runtime/history-compactor.js +13 -3
- package/src/runtime/implementation-gate.js +281 -26
- package/src/runtime/intake/engine.js +677 -0
- package/src/runtime/intake/index.js +136 -0
- package/src/runtime/intake/manifest.js +140 -0
- package/src/runtime/intake/taxonomy.js +206 -0
- package/src/runtime/inventory/coverage.js +1 -1
- package/src/runtime/inventory/index.js +1 -1
- package/src/runtime/inventory/precedence.js +2 -2
- package/src/runtime/inventory/siblings.js +6 -4
- package/src/runtime/knowledge/code-corpus.js +277 -0
- package/src/runtime/knowledge/code-lexical.js +130 -0
- package/src/runtime/knowledge/code-retrieval.js +307 -0
- package/src/runtime/knowledge/code-validation.js +106 -0
- package/src/runtime/knowledge/gp3-gate.js +74 -0
- package/src/runtime/knowledge/graph-adapter.js +288 -0
- package/src/runtime/knowledge/graph-fallback.js +394 -0
- package/src/runtime/knowledge/hybrid.js +136 -8
- package/src/runtime/knowledge/retrieval.js +34 -1
- package/src/runtime/knowledge/rtk-compress.js +77 -0
- package/src/runtime/knowledge/semble-bridge.py +106 -0
- package/src/runtime/knowledge/semble-lifecycle.js +114 -0
- package/src/runtime/knowledge/semble-provider.js +365 -0
- package/src/runtime/lifecycle/cli.js +88 -10
- package/src/runtime/lifecycle/event-store.js +8 -6
- package/src/runtime/lifecycle/followup.js +38 -7
- package/src/runtime/lifecycle/overview.js +26 -2
- package/src/runtime/lifecycle/report-store.js +8 -10
- package/src/runtime/lifecycle/retention.js +95 -31
- package/src/runtime/lifecycle/root.js +9 -1
- package/src/runtime/lifecycle/status.js +34 -17
- package/src/runtime/lifecycle/store-upkeep.js +56 -7
- package/src/runtime/mask.js +134 -7
- package/src/runtime/mcp-consultations.js +40 -6
- package/src/runtime/model-router.js +79 -7
- package/src/runtime/models/catalogue.js +191 -0
- package/src/runtime/models/command.js +153 -0
- package/src/runtime/off-words.js +12 -0
- package/src/runtime/outcome.js +2 -2
- package/src/runtime/packages/command.js +1009 -0
- package/src/runtime/packages/contributions.js +116 -0
- package/src/runtime/packages/digest.js +132 -0
- package/src/runtime/packages/fetch.js +182 -0
- package/src/runtime/packages/grants.js +192 -0
- package/src/runtime/packages/index-file.js +134 -0
- package/src/runtime/packages/instruction.js +90 -0
- package/src/runtime/packages/manifest.js +331 -0
- package/src/runtime/packages/points.js +487 -0
- package/src/runtime/packages/programs.js +216 -0
- package/src/runtime/packages/scaffold.js +277 -0
- package/src/runtime/packages/source.js +90 -0
- package/src/runtime/packages/state.js +164 -0
- package/src/runtime/packages/store.js +449 -0
- package/src/runtime/packages/tar.js +106 -0
- package/src/runtime/packages/view.js +406 -0
- package/src/runtime/plan-check.js +59 -0
- package/src/runtime/plan-content.js +324 -0
- package/src/runtime/policy-init.js +118 -0
- package/src/runtime/profiles/doctor.js +96 -0
- package/src/runtime/profiles/resolve.js +244 -0
- package/src/runtime/profiles/rollback.js +254 -0
- package/src/runtime/profiles/sampler.js +41 -0
- package/src/runtime/readiness-record.js +16 -11
- package/src/runtime/readiness.js +46 -5
- package/src/runtime/research-request.js +50 -25
- package/src/runtime/retrieval-plan.js +10 -30
- package/src/runtime/retrieval-record.js +75 -5
- package/src/runtime/review/command.js +246 -0
- package/src/runtime/review/dominance.js +68 -0
- package/src/runtime/review/findings.js +434 -0
- package/src/runtime/review/identity.js +255 -0
- package/src/runtime/review/protocol-command.js +109 -0
- package/src/runtime/review/protocols.js +405 -0
- package/src/runtime/review/resolve-protocol.js +302 -0
- package/src/runtime/review/start.js +530 -0
- package/src/runtime/roadmap/attendance.js +137 -0
- package/src/runtime/roadmap/facts.js +479 -0
- package/src/runtime/roadmap/gates.js +273 -0
- package/src/runtime/roadmap/loop.js +1719 -0
- package/src/runtime/roadmap/merge.js +390 -0
- package/src/runtime/roadmap/rows.js +1122 -0
- package/src/runtime/roadmap/seed.js +1063 -0
- package/src/runtime/roadmap/worktree-cleanup.js +147 -0
- package/src/runtime/rules-report.js +336 -0
- package/src/runtime/scaffold/artifacts.js +60 -9
- package/src/runtime/scaffold/generate.js +21 -9
- package/src/runtime/settings/autopilot.js +106 -0
- package/src/runtime/settings/cli.js +280 -0
- package/src/runtime/settings/config-write.js +314 -0
- package/src/runtime/settings/files.js +271 -0
- package/src/runtime/settings/legacy.js +154 -0
- package/src/runtime/settings/lexical.js +56 -0
- package/src/runtime/settings/prepared-run.js +269 -0
- package/src/runtime/settings/project-layers.js +118 -0
- package/src/runtime/settings/refs.js +288 -0
- package/src/runtime/settings/registry.js +553 -0
- package/src/runtime/settings/resolve.js +713 -0
- package/src/runtime/settings/shared.js +37 -0
- package/src/runtime/settings/worker-billing.js +107 -0
- package/src/runtime/settings/write.js +269 -0
- package/src/runtime/slot-command.js +78 -0
- package/src/runtime/slots.js +671 -0
- package/src/runtime/source-version.js +1 -0
- package/src/runtime/state-root.js +217 -0
- package/src/runtime/storage/cli.js +12 -5
- package/src/runtime/storage/engine.js +9 -2
- package/src/runtime/storage/registry.js +14 -1
- package/src/runtime/storage/roots.js +66 -16
- package/src/runtime/storage/rules.js +82 -10
- package/src/runtime/storage/upkeep.js +10 -2
- package/src/runtime/storage/work-status.js +245 -26
- package/src/runtime/task-attempts.js +589 -69
- package/src/runtime/task-classifier.js +85 -14
- package/src/runtime/task-graph.js +373 -0
- package/src/runtime/task-run.js +778 -0
- package/src/runtime/task-scope.js +176 -55
- package/src/runtime/task-sources.js +147 -0
- package/src/runtime/task-state.js +373 -64
- package/src/runtime/team/admission.js +301 -0
- package/src/runtime/team/envelope.js +324 -0
- package/src/runtime/team/review-guard.js +156 -0
- package/src/runtime/trace/analyze.js +427 -0
- package/src/runtime/trace/baseline.js +770 -0
- package/src/runtime/trace/ledger.js +63 -140
- package/src/runtime/trace/otlp-export.js +568 -0
- package/src/runtime/trace/otlp-map.js +481 -0
- package/src/runtime/trace/spans.js +745 -0
- package/src/runtime/trace/telemetry.js +225 -0
- package/src/runtime/trace/views.js +1 -0
- package/src/runtime/transcripts/command.js +98 -0
- package/src/runtime/transcripts/cursor.js +326 -0
- package/src/runtime/transcripts/read.js +126 -0
- package/src/runtime/transcripts/readers/claude-jsonl.js +74 -0
- package/src/runtime/transcripts/readers/codex-rollout.js +70 -0
- package/src/runtime/transcripts/readers/copilot-events.js +90 -0
- package/src/runtime/transcripts/readers/kiro-jsonl.js +77 -0
- package/src/runtime/transcripts/readers/pi-jsonl.js +59 -0
- package/src/runtime/transcripts/registry.js +161 -0
- package/src/runtime/transcripts/stats.js +161 -0
- package/src/runtime/verb-view.js +267 -0
- package/src/runtime/verification/check-key.js +628 -0
- package/src/runtime/verification/contract-runner.js +546 -11
- package/src/runtime/verification/engine.js +499 -54
- package/src/runtime/verification/impact.js +617 -0
- package/src/runtime/verification/inflight.js +205 -0
- package/src/runtime/verification/registry.js +176 -0
- package/src/runtime/verification/reuse.js +184 -0
- package/src/runtime/verification/telemetry-emit.js +254 -0
- package/src/runtime/verification/test-selection.js +67 -7
- package/src/runtime/worker/active.js +90 -0
- package/src/runtime/worker/cancel.js +222 -0
- package/src/runtime/worker/catalogue.js +122 -0
- package/src/runtime/worker/command.js +677 -0
- package/src/runtime/worker/evidence.js +288 -0
- package/src/runtime/worker/launch.js +256 -0
- package/src/runtime/worker/models.js +137 -0
- package/src/runtime/worker/parsers.js +218 -0
- package/src/runtime/worker/probes/index.js +706 -0
- package/src/runtime/worker/process-tree.js +415 -0
- package/src/runtime/worker/quota.js +43 -0
- package/src/runtime/worker/readiness.js +713 -0
- package/src/runtime/worker/run-store.js +166 -0
- package/src/runtime/worker/supervisor.js +541 -0
- package/src/runtime/worker/worktree-check.js +252 -0
- package/src/runtime/workflow-engine.js +5 -1
- package/src/runtime/workflow-orchestrator.js +610 -67
- package/src/runtime/worktree.js +149 -22
- package/src/state/index.js +1 -1
- package/src/state/lockfile.js +64 -10
- package/src/state/run-lock.js +1 -1
- package/types/node-commonjs.d.ts +106 -7
- package/core/harnesses/claude/hooks/pre-bash-guard.sh +0 -10
- package/core/harnesses/codex/hooks/pre-bash-guard.sh +0 -10
- package/core/harnesses/gemini/hooks/hooks.json +0 -77
- package/core/harnesses/gemini/hooks/lib.sh +0 -302
- package/core/harnesses/gemini/hooks/mcp-tool-guard.sh +0 -10
- package/core/harnesses/gemini/hooks/post-edit-lint.sh +0 -39
- package/core/harnesses/gemini/hooks/pre-bash-guard.sh +0 -10
- package/core/harnesses/gemini/hooks/pre-compact.sh +0 -38
- package/core/harnesses/gemini/hooks/pre-implement-gate.sh +0 -10
- package/core/harnesses/gemini/hooks/session-end.impl.sh +0 -89
- package/core/harnesses/gemini/hooks/session-end.sh +0 -5
- package/core/harnesses/gemini/hooks/session-start.sh +0 -7
- package/core/harnesses/gemini/settings/adapter-defaults.json +0 -4
- package/core/harnesses/kiro/hooks/pre-bash-guard.sh +0 -24
- package/core/harnesses/shared/hooks/policies/blocked-patterns.conf +0 -91
- package/core/harnesses/shared/hooks/policies/pre-bash-guard.sh +0 -378
- package/core/shared/guidance/FLAGS.md +0 -25
- package/core/shared/guidance/rules/RULE_01_SAFETY.md +0 -25
- package/core/shared/guidance/rules/RULE_02_WORKFLOW.md +0 -23
- package/core/shared/guidance/rules/RULE_03_QUALITY.md +0 -14
- package/core/shared/guidance/rules/RULE_04_QUESTIONS.md +0 -46
- package/src/adapters/gemini/hooks.js +0 -251
- package/src/adapters/gemini/index.js +0 -429
|
@@ -0,0 +1,770 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
|
|
4
|
+
|
|
5
|
+
const ISO_UTC = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/;
|
|
6
|
+
const msOf = (v ) =>
|
|
7
|
+
(typeof v === 'string' && ISO_UTC.test(v) && Number.isFinite(Date.parse(v)) ? Date.parse(v) : null);
|
|
8
|
+
|
|
9
|
+
const THIRTY_MINUTES_MS = 30 * 60 * 1000;
|
|
10
|
+
|
|
11
|
+
/** Sort object keys at every level to ensure deterministic JSON representation. */
|
|
12
|
+
function sorted(value ) {
|
|
13
|
+
if (Array.isArray(value)) return value.map(sorted);
|
|
14
|
+
if (value && typeof value === 'object') {
|
|
15
|
+
const out = {};
|
|
16
|
+
for (const k of Object.keys(value).sort()) {
|
|
17
|
+
out[k] = sorted(value[k]);
|
|
18
|
+
}
|
|
19
|
+
return out;
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Union of overlapping half-open intervals [start, end]. Counted once in the union. */
|
|
25
|
+
function unionIntervals(intervals ) {
|
|
26
|
+
const valid = intervals.filter(([s, e]) => Number.isFinite(s) && Number.isFinite(e) && e > s);
|
|
27
|
+
if (valid.length === 0) return 0;
|
|
28
|
+
valid.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
|
|
29
|
+
const merged = [valid[0].slice() ];
|
|
30
|
+
for (let i = 1; i < valid.length; i++) {
|
|
31
|
+
const [currStart, currEnd] = valid[i];
|
|
32
|
+
const last = merged[merged.length - 1];
|
|
33
|
+
if (currStart <= last[1]) {
|
|
34
|
+
last[1] = Math.max(last[1], currEnd);
|
|
35
|
+
} else {
|
|
36
|
+
merged.push([currStart, currEnd]);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return merged.reduce((sum, [s, e]) => sum + (e - s), 0);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Detect idle gaps between activity intervals that exceed thresholdMs (D-8). */
|
|
43
|
+
function findIdleGaps(activityIntervals , thresholdMs = THIRTY_MINUTES_MS) {
|
|
44
|
+
const valid = activityIntervals.filter(([s, e]) => Number.isFinite(s) && Number.isFinite(e) && e >= s);
|
|
45
|
+
if (valid.length === 0) return [];
|
|
46
|
+
valid.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
|
|
47
|
+
const merged = [valid[0].slice() ];
|
|
48
|
+
for (let i = 1; i < valid.length; i++) {
|
|
49
|
+
const [currStart, currEnd] = valid[i];
|
|
50
|
+
const last = merged[merged.length - 1];
|
|
51
|
+
if (currStart <= last[1]) {
|
|
52
|
+
last[1] = Math.max(last[1], currEnd);
|
|
53
|
+
} else {
|
|
54
|
+
merged.push([currStart, currEnd]);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const gaps = [];
|
|
58
|
+
for (let i = 0; i < merged.length - 1; i++) {
|
|
59
|
+
const gapStart = merged[i][1];
|
|
60
|
+
const gapEnd = merged[i + 1][0];
|
|
61
|
+
const durationMs = gapEnd - gapStart;
|
|
62
|
+
if (durationMs > thresholdMs) {
|
|
63
|
+
gaps.push({
|
|
64
|
+
start: new Date(gapStart).toISOString(),
|
|
65
|
+
end: new Date(gapEnd).toISOString(),
|
|
66
|
+
durationMs,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return gaps;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function calcMedian(numbers ) {
|
|
74
|
+
if (numbers.length === 0) return 0;
|
|
75
|
+
const sortedNums = [...numbers].sort((a, b) => a - b);
|
|
76
|
+
const mid = Math.floor(sortedNums.length / 2);
|
|
77
|
+
if (sortedNums.length % 2 === 1) return sortedNums[mid];
|
|
78
|
+
return (sortedNums[mid - 1] + sortedNums[mid]) / 2;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function calcRange(numbers ) {
|
|
82
|
+
if (numbers.length === 0) return [0, 0];
|
|
83
|
+
return [Math.min(...numbers), Math.max(...numbers)];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Pure baseline computation over trace spans and manifest (088 IC-012, FR-010, FR-011). */
|
|
87
|
+
function buildBaseline(spansView = {}, manifest = {}) {
|
|
88
|
+
const traces = Array.isArray(spansView?.traces) ? spansView.traces : (Array.isArray(spansView) ? spansView : []);
|
|
89
|
+
const allHarnesses = new Set ();
|
|
90
|
+
if (manifest?.harness && typeof manifest.harness === 'string') {
|
|
91
|
+
allHarnesses.add(manifest.harness);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
let totalBroadTestsChecks = 0;
|
|
95
|
+
let totalTestFullSpans = 0;
|
|
96
|
+
let anyCpuRecorded = false;
|
|
97
|
+
|
|
98
|
+
const goalLoops = traces.map((tr) => {
|
|
99
|
+
const spanList = Array.isArray(tr.spans) ? tr.spans : [];
|
|
100
|
+
|
|
101
|
+
// Find harness for this trace
|
|
102
|
+
let traceHarness = null;
|
|
103
|
+
for (const s of spanList) {
|
|
104
|
+
if (s.attrs?.harness && typeof s.attrs.harness === 'string') {
|
|
105
|
+
traceHarness = s.attrs.harness;
|
|
106
|
+
allHarnesses.add(s.attrs.harness);
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (!traceHarness && manifest?.harness) {
|
|
111
|
+
traceHarness = manifest.harness;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// 1. Spans classification & boundaries
|
|
115
|
+
const starts = [];
|
|
116
|
+
const closedEnds = [];
|
|
117
|
+
const upperEnds = [];
|
|
118
|
+
const activityIntervals = [];
|
|
119
|
+
|
|
120
|
+
const closedVerificationIntervals = [];
|
|
121
|
+
const upperVerificationIntervals = [];
|
|
122
|
+
|
|
123
|
+
let executedCheckTotalDurationLower = 0;
|
|
124
|
+
let executedCheckTotalDurationUpper = 0;
|
|
125
|
+
let outsideVerbTestTotalDurationLower = 0;
|
|
126
|
+
let outsideVerbTestTotalDurationUpper = 0;
|
|
127
|
+
|
|
128
|
+
let loopBroadTestsChecks = 0;
|
|
129
|
+
let loopTestFull = 0;
|
|
130
|
+
let loopCpuMs = 0;
|
|
131
|
+
let hasProcChildren = false;
|
|
132
|
+
|
|
133
|
+
// Duplicates tracking
|
|
134
|
+
const checkKeyCounts = new Map ();
|
|
135
|
+
const sessionTestClassCounts = new Map ();
|
|
136
|
+
|
|
137
|
+
// Collect trace window boundaries if present
|
|
138
|
+
if (tr.window?.from) {
|
|
139
|
+
const fromMs = msOf(tr.window.from);
|
|
140
|
+
if (fromMs !== null) starts.push(fromMs);
|
|
141
|
+
}
|
|
142
|
+
if (tr.window?.to) {
|
|
143
|
+
const toMs = msOf(tr.window.to);
|
|
144
|
+
if (toMs !== null) {
|
|
145
|
+
closedEnds.push(toMs);
|
|
146
|
+
upperEnds.push(toMs);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const pairedTestKeys = new Set ();
|
|
151
|
+
for (const s of spanList) {
|
|
152
|
+
if (s.kind === 'test') {
|
|
153
|
+
const sess = s.session || s.attrs?.session;
|
|
154
|
+
const toolCall = s.attrs?.tool_call_id;
|
|
155
|
+
if (sess && toolCall) {
|
|
156
|
+
pairedTestKeys.add(`${sess}\n${toolCall}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
for (let i = 0; i < spanList.length; i++) {
|
|
162
|
+
const s = spanList[i];
|
|
163
|
+
const startMs = msOf(s.start);
|
|
164
|
+
let endMs = msOf(s.end);
|
|
165
|
+
if (startMs !== null && endMs === null && Number.isInteger(s.durationMs) && s.durationMs >= 0) {
|
|
166
|
+
endMs = startMs + s.durationMs;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (startMs !== null) starts.push(startMs);
|
|
170
|
+
if (endMs !== null) {
|
|
171
|
+
closedEnds.push(endMs);
|
|
172
|
+
upperEnds.push(endMs);
|
|
173
|
+
if (startMs !== null) activityIntervals.push([startMs, endMs]);
|
|
174
|
+
} else if (startMs !== null) {
|
|
175
|
+
// Open-ended span: determine upper bound end (until next span start or window.to)
|
|
176
|
+
const nextSpan = spanList.slice(i + 1).find((n) => n.start !== null);
|
|
177
|
+
const nextStartMs = nextSpan ? msOf(nextSpan.start) : (tr.window?.to ? msOf(tr.window.to) : null);
|
|
178
|
+
const upperEnd = nextStartMs !== null && nextStartMs > startMs ? nextStartMs : startMs;
|
|
179
|
+
upperEnds.push(upperEnd);
|
|
180
|
+
activityIntervals.push([startMs, upperEnd]);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
let isOutsideVerbTest = false;
|
|
184
|
+
if (s.kind === 'test') {
|
|
185
|
+
isOutsideVerbTest = true;
|
|
186
|
+
} else if (s.kind === 'hook' && typeof s.attrs?.test_class === 'string' && s.attrs.test_class.startsWith('test.')) {
|
|
187
|
+
const sess = s.session || s.attrs?.session;
|
|
188
|
+
const toolCall = s.attrs?.tool_call_id;
|
|
189
|
+
const isPaired = Boolean(sess && toolCall && pairedTestKeys.has(`${sess}\n${toolCall}`));
|
|
190
|
+
if (!isPaired) {
|
|
191
|
+
isOutsideVerbTest = true;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const isVerifyRun = s.kind === 'verify.run';
|
|
195
|
+
const isVerifyCheck = s.kind === 'verify.check';
|
|
196
|
+
|
|
197
|
+
// Verification intervals for verificationWallMs
|
|
198
|
+
if (isVerifyRun || isOutsideVerbTest) {
|
|
199
|
+
if (startMs !== null && endMs !== null && endMs > startMs) {
|
|
200
|
+
closedVerificationIntervals.push([startMs, endMs]);
|
|
201
|
+
upperVerificationIntervals.push([startMs, endMs]);
|
|
202
|
+
} else if (startMs !== null && endMs === null) {
|
|
203
|
+
// Open-ended verification span: excluded from lower end, included in upper bound
|
|
204
|
+
const nextSpan = spanList.slice(i + 1).find((n) => n.start !== null);
|
|
205
|
+
const nextStartMs = nextSpan ? msOf(nextSpan.start) : (tr.window?.to ? msOf(tr.window.to) : null);
|
|
206
|
+
const upperEnd = nextStartMs !== null && nextStartMs > startMs ? nextStartMs : startMs;
|
|
207
|
+
if (upperEnd > startMs) {
|
|
208
|
+
upperVerificationIntervals.push([startMs, upperEnd]);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Check executions for totalTestMs, duplicates, fullSuiteRuns, cpuMs
|
|
214
|
+
if (isVerifyCheck) {
|
|
215
|
+
const isNotRun = s.attrs?.status === 'NOT_RUN';
|
|
216
|
+
const isSharedInRun = s.attrs?.shared === 'in-run';
|
|
217
|
+
const isSharedFollower = s.attrs?.shared === 'follower';
|
|
218
|
+
// 089 IC-007: a reused check read a recorded PASS; like in-run and follower, it ran nothing.
|
|
219
|
+
const isReused = s.attrs?.shared === 'reused';
|
|
220
|
+
const isExecuted = !isNotRun && !isSharedInRun && !isSharedFollower && !isReused;
|
|
221
|
+
|
|
222
|
+
if (isExecuted) {
|
|
223
|
+
const duration = typeof s.durationMs === 'number' ? s.durationMs : (startMs !== null && endMs !== null ? Math.max(0, endMs - startMs) : 0);
|
|
224
|
+
executedCheckTotalDurationLower += duration;
|
|
225
|
+
if (startMs !== null && endMs === null && duration === 0) {
|
|
226
|
+
const nextSpan = spanList.slice(i + 1).find((n) => n.start !== null);
|
|
227
|
+
const nextStartMs = nextSpan ? msOf(nextSpan.start) : (tr.window?.to ? msOf(tr.window.to) : null);
|
|
228
|
+
const upperDur = nextStartMs !== null && nextStartMs > startMs ? nextStartMs - startMs : 0;
|
|
229
|
+
executedCheckTotalDurationUpper += upperDur;
|
|
230
|
+
} else {
|
|
231
|
+
executedCheckTotalDurationUpper += duration;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (s.attrs?.tier === 'broad-tests') {
|
|
235
|
+
loopBroadTestsChecks += 1;
|
|
236
|
+
totalBroadTestsChecks += 1;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (s.attrs?.resource_basis === 'proc-children') {
|
|
240
|
+
hasProcChildren = true;
|
|
241
|
+
anyCpuRecorded = true;
|
|
242
|
+
if (typeof s.attrs.cpu_ms === 'number') {
|
|
243
|
+
loopCpuMs += s.attrs.cpu_ms;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (s.attrs?.check_key && typeof s.attrs.check_key === 'string') {
|
|
248
|
+
checkKeyCounts.set(s.attrs.check_key, (checkKeyCounts.get(s.attrs.check_key) || 0) + 1);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Outside-verb test durations and duplicates
|
|
254
|
+
if (isOutsideVerbTest) {
|
|
255
|
+
const duration = typeof s.durationMs === 'number' ? s.durationMs : (startMs !== null && endMs !== null ? Math.max(0, endMs - startMs) : 0);
|
|
256
|
+
outsideVerbTestTotalDurationLower += duration;
|
|
257
|
+
if (startMs !== null && endMs === null && duration === 0) {
|
|
258
|
+
const nextSpan = spanList.slice(i + 1).find((n) => n.start !== null);
|
|
259
|
+
const nextStartMs = nextSpan ? msOf(nextSpan.start) : (tr.window?.to ? msOf(tr.window.to) : null);
|
|
260
|
+
const upperDur = nextStartMs !== null && nextStartMs > startMs ? nextStartMs - startMs : 0;
|
|
261
|
+
outsideVerbTestTotalDurationUpper += upperDur;
|
|
262
|
+
} else {
|
|
263
|
+
outsideVerbTestTotalDurationUpper += duration;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (s.attrs?.test_class === 'test.full') {
|
|
267
|
+
loopTestFull += 1;
|
|
268
|
+
totalTestFullSpans += 1;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const testClass = s.attrs?.test_class;
|
|
272
|
+
const session = s.session || s.attrs?.session || 'default';
|
|
273
|
+
if (testClass && typeof testClass === 'string') {
|
|
274
|
+
const key = `${session}::${testClass}`;
|
|
275
|
+
sessionTestClassCounts.set(key, (sessionTestClassCounts.get(key) || 0) + 1);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Boundary timings
|
|
281
|
+
const firstSpanMs = starts.length > 0 ? Math.min(...starts) : 0;
|
|
282
|
+
const lastClosedSpanMs = closedEnds.length > 0 ? Math.max(...closedEnds) : (starts.length > 0 ? Math.max(...starts) : firstSpanMs);
|
|
283
|
+
const lastUpperSpanMs = upperEnds.length > 0 ? Math.max(...upperEnds) : lastClosedSpanMs;
|
|
284
|
+
|
|
285
|
+
const loopWallMsLower = Math.max(0, lastClosedSpanMs - firstSpanMs);
|
|
286
|
+
const loopWallMsUpper = Math.max(0, lastUpperSpanMs - firstSpanMs);
|
|
287
|
+
|
|
288
|
+
// Verification union (counted once in the union)
|
|
289
|
+
const verificationWallMsLower = unionIntervals(closedVerificationIntervals);
|
|
290
|
+
const verificationWallMsUpper = unionIntervals(upperVerificationIntervals);
|
|
291
|
+
|
|
292
|
+
// Total test durations (summed twice in the sum)
|
|
293
|
+
const totalTestMsLower = executedCheckTotalDurationLower + outsideVerbTestTotalDurationLower;
|
|
294
|
+
const totalTestMsUpper = executedCheckTotalDurationUpper + outsideVerbTestTotalDurationUpper;
|
|
295
|
+
|
|
296
|
+
// Idle gaps > 30 min (D-8)
|
|
297
|
+
const idleGaps = findIdleGaps(activityIntervals, THIRTY_MINUTES_MS);
|
|
298
|
+
const idleGapsMs = idleGaps.reduce((acc, g) => acc + g.durationMs, 0);
|
|
299
|
+
|
|
300
|
+
// Implementation time: loop - union - idle gaps > 30 min
|
|
301
|
+
const implementationMsLower = Math.max(0, loopWallMsLower - verificationWallMsLower - idleGapsMs);
|
|
302
|
+
const implementationMsUpper = Math.max(0, loopWallMsUpper - verificationWallMsUpper - idleGapsMs);
|
|
303
|
+
|
|
304
|
+
// Ratio and Share
|
|
305
|
+
const ratioLower = loopWallMsLower > 0 ? Number((verificationWallMsLower / loopWallMsLower).toPrecision(3)) : 0;
|
|
306
|
+
const ratioUpper = loopWallMsUpper > 0 ? Number((verificationWallMsUpper / loopWallMsUpper).toPrecision(3)) : ratioLower;
|
|
307
|
+
|
|
308
|
+
// Duplicates
|
|
309
|
+
let exactDuplicates = 0;
|
|
310
|
+
for (const count of checkKeyCounts.values()) {
|
|
311
|
+
if (count > 1) exactDuplicates += count - 1;
|
|
312
|
+
}
|
|
313
|
+
let candidateDuplicates = 0;
|
|
314
|
+
for (const count of sessionTestClassCounts.values()) {
|
|
315
|
+
if (count > 1) candidateDuplicates += count - 1;
|
|
316
|
+
}
|
|
317
|
+
const totalDuplicates = exactDuplicates + candidateDuplicates;
|
|
318
|
+
|
|
319
|
+
// Full suite runs
|
|
320
|
+
const fullSuiteRuns = loopBroadTestsChecks + loopTestFull;
|
|
321
|
+
|
|
322
|
+
const isOpenWindow = !tr.window?.to;
|
|
323
|
+
|
|
324
|
+
return {
|
|
325
|
+
traceId: tr.traceId || null,
|
|
326
|
+
runKey: tr.runKey || null,
|
|
327
|
+
epoch: tr.epoch !== undefined ? tr.epoch : null,
|
|
328
|
+
harness: traceHarness,
|
|
329
|
+
window: tr.window || null,
|
|
330
|
+
idleGaps,
|
|
331
|
+
metrics: {
|
|
332
|
+
loopWallMs: loopWallMsLower,
|
|
333
|
+
verificationWallMs: verificationWallMsLower,
|
|
334
|
+
totalTestMs: totalTestMsLower,
|
|
335
|
+
implementationMs: implementationMsLower,
|
|
336
|
+
ratio: ratioLower,
|
|
337
|
+
share: ratioLower,
|
|
338
|
+
duplicates: totalDuplicates,
|
|
339
|
+
exactDuplicates,
|
|
340
|
+
candidateDuplicates,
|
|
341
|
+
fullSuiteRuns,
|
|
342
|
+
cpuMs: hasProcChildren ? loopCpuMs : 'unreached',
|
|
343
|
+
peakMemory: 'unreached',
|
|
344
|
+
idleGapsMs,
|
|
345
|
+
},
|
|
346
|
+
upperBound: isOpenWindow ? null : {
|
|
347
|
+
loopWallMs: loopWallMsUpper,
|
|
348
|
+
verificationWallMs: verificationWallMsUpper,
|
|
349
|
+
totalTestMs: totalTestMsUpper,
|
|
350
|
+
implementationMs: implementationMsUpper,
|
|
351
|
+
ratio: ratioUpper,
|
|
352
|
+
share: ratioUpper,
|
|
353
|
+
},
|
|
354
|
+
};
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
const loopsCount = goalLoops.length;
|
|
358
|
+
const harnessesCount = allHarnesses.size;
|
|
359
|
+
const windowFilled = loopsCount >= 5 && harnessesCount >= 2;
|
|
360
|
+
|
|
361
|
+
// Aggregate metrics across goal loops
|
|
362
|
+
const aggLoopWall = goalLoops.map((g) => g.metrics.loopWallMs);
|
|
363
|
+
const aggVerifWall = goalLoops.map((g) => g.metrics.verificationWallMs);
|
|
364
|
+
const aggTotalTest = goalLoops.map((g) => g.metrics.totalTestMs);
|
|
365
|
+
const aggImpl = goalLoops.map((g) => g.metrics.implementationMs);
|
|
366
|
+
const aggRatio = goalLoops.map((g) => g.metrics.ratio);
|
|
367
|
+
const aggDuplicates = goalLoops.map((g) => g.metrics.duplicates);
|
|
368
|
+
const aggFullSuite = goalLoops.map((g) => g.metrics.fullSuiteRuns);
|
|
369
|
+
const aggIdleGaps = goalLoops.map((g) => g.metrics.idleGapsMs);
|
|
370
|
+
|
|
371
|
+
const aggLoopWallUpper = goalLoops.map((g) => g.upperBound?.loopWallMs ?? g.metrics.loopWallMs);
|
|
372
|
+
const aggVerifWallUpper = goalLoops.map((g) => g.upperBound?.verificationWallMs ?? g.metrics.verificationWallMs);
|
|
373
|
+
const aggTotalTestUpper = goalLoops.map((g) => g.upperBound?.totalTestMs ?? g.metrics.totalTestMs);
|
|
374
|
+
const aggImplUpper = goalLoops.map((g) => g.upperBound?.implementationMs ?? g.metrics.implementationMs);
|
|
375
|
+
const aggRatioUpper = goalLoops.map((g) => g.upperBound?.ratio ?? g.metrics.ratio);
|
|
376
|
+
|
|
377
|
+
const numericCpuValues = goalLoops.filter((g) => typeof g.metrics.cpuMs === 'number').map((g) => g.metrics.cpuMs );
|
|
378
|
+
const aggCpuMedian = numericCpuValues.length > 0 ? calcMedian(numericCpuValues) : 'unreached';
|
|
379
|
+
const aggCpuRange = numericCpuValues.length > 0 ? calcRange(numericCpuValues) : null;
|
|
380
|
+
|
|
381
|
+
const medianRatio = calcMedian(aggRatio);
|
|
382
|
+
let verdict = 'verdict not yet derivable';
|
|
383
|
+
if (windowFilled) {
|
|
384
|
+
// D-1 materiality rule: verification wall time >= 20% of goal-loop wall time
|
|
385
|
+
verdict = medianRatio >= 0.2 ? 'material' : 'not material';
|
|
386
|
+
}
|
|
387
|
+
const progress = `${loopsCount} of 5 loops, ${harnessesCount} of 2 harnesses`;
|
|
388
|
+
|
|
389
|
+
const inputTable = [
|
|
390
|
+
{
|
|
391
|
+
metric: 'loopWallMs',
|
|
392
|
+
basis: 'derived',
|
|
393
|
+
recordsRead: 'task-run history start/resume, activity endpoints, trace span window',
|
|
394
|
+
uncapturedInputs: 'open-ended spans without completion events',
|
|
395
|
+
cause: 'derived as last span end minus first span start across trace spans',
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
metric: 'verificationWallMs',
|
|
399
|
+
basis: 'derived',
|
|
400
|
+
recordsRead: 'verify.run spans, outside-verb test spans',
|
|
401
|
+
uncapturedInputs: 'tests on unobserved harnesses (OpenCode, Copilot)',
|
|
402
|
+
cause: 'union of verify.run intervals and outside-verb test intervals',
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
metric: 'totalTestMs',
|
|
406
|
+
basis: 'derived',
|
|
407
|
+
recordsRead: 'executed verify.check spans, outside-verb test spans',
|
|
408
|
+
uncapturedInputs: 'per-check timing on pre-FR-016 records, test durations on non-Claude harnesses',
|
|
409
|
+
cause: 'sum of executed check durations (excluding in-run, follower and reused) + outside-verb test durations',
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
metric: 'implementationMs',
|
|
413
|
+
basis: 'derived',
|
|
414
|
+
recordsRead: 'loop wall time, verification union wall time, idle intervals > 30 min',
|
|
415
|
+
uncapturedInputs: 'fine-grained model thinking / editing time outside observed commands',
|
|
416
|
+
cause: 'goal loop wall time minus verification wall time minus idle gaps > 30 min',
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
metric: 'ratio',
|
|
420
|
+
basis: 'derived',
|
|
421
|
+
recordsRead: 'verificationWallMs, loopWallMs',
|
|
422
|
+
uncapturedInputs: 'none beyond constituent metrics',
|
|
423
|
+
cause: 'verificationWallMs / loopWallMs',
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
metric: 'share',
|
|
427
|
+
basis: 'derived',
|
|
428
|
+
recordsRead: 'verificationWallMs, loopWallMs',
|
|
429
|
+
uncapturedInputs: 'none beyond constituent metrics',
|
|
430
|
+
cause: 'verificationWallMs / loopWallMs',
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
metric: 'duplicates',
|
|
434
|
+
basis: 'derived',
|
|
435
|
+
recordsRead: 'executed verify.check spans with check_key, outside-verb test spans by session and test_class',
|
|
436
|
+
uncapturedInputs: 'edit hook lines not available in 088, so all repeated tests in session are candidate duplicates',
|
|
437
|
+
cause: 'exact check_key duplicates + candidate same-class test repeats in a session',
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
metric: 'fullSuiteRuns',
|
|
441
|
+
basis: 'derived',
|
|
442
|
+
recordsRead: 'executed broad-tests checks, test.full outside-verb test spans',
|
|
443
|
+
uncapturedInputs: 'none',
|
|
444
|
+
cause: 'sum of executed broad-tests checks and test.full runs',
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
metric: 'cpuMs',
|
|
448
|
+
basis: anyCpuRecorded ? 'recorded' : 'unreached',
|
|
449
|
+
recordsRead: 'verify.check spans with resource_basis proc-children',
|
|
450
|
+
uncapturedInputs: 'non-Linux platforms (darwin, win32) and unkeyable/read faults',
|
|
451
|
+
cause: anyCpuRecorded ? 'sum of check cpu_ms where resource_basis is proc-children' : 'child CPU ticks unreached on non-Linux platforms',
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
metric: 'peakMemory',
|
|
455
|
+
basis: 'unreached',
|
|
456
|
+
recordsRead: 'none',
|
|
457
|
+
uncapturedInputs: 'process peak RSS memory measurement',
|
|
458
|
+
cause: 'no portable zero-dependency child memory sampling while spawnSync blocks',
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
metric: 'idleGapsMs',
|
|
462
|
+
basis: 'derived',
|
|
463
|
+
recordsRead: 'inferred from timestamps between consecutive activities',
|
|
464
|
+
uncapturedInputs: 'sub-30-minute idle pauses treated as implementation time',
|
|
465
|
+
cause: 'sum of activity gaps exceeding the 30-minute session threshold (D-8)',
|
|
466
|
+
},
|
|
467
|
+
];
|
|
468
|
+
|
|
469
|
+
const surveyProxies = {
|
|
470
|
+
note: 'pre-telemetry proxies from research/baseline-survey.md §4, context only, never a result',
|
|
471
|
+
range: '0.49 % - 87.0 %',
|
|
472
|
+
proxies: [
|
|
473
|
+
{ id: 'A', name: 'Ledger dispatched time', share: '87.0 %', bias: 'Denominator is only DoFlow verbs; excludes agent, edit and Bash time. Says verify dominates DoFlow verb time, nothing about goal loop.' },
|
|
474
|
+
{ id: 'B', name: 'Idle-gap session wall', share: '1.34 %', bias: '30-minute gap is an inference; single-record sessions have 0 wall; overnight idle excluded only when gap > 30 min.' },
|
|
475
|
+
{ id: 'B2', name: 'Sessions containing verify', share: '4.14 %', bias: 'Selects sessions where verification happened, biased upward.' },
|
|
476
|
+
{ id: 'C', name: 'Orchestration records', share: '1.1 %', bias: 'Stages are completion intervals; verification stage closed almost immediately; suite reruns land in implementation.' },
|
|
477
|
+
{ id: 'total', name: 'Verify verb vs orchestration totalMs', share: '0.49 %', bias: 'Understates verification time; reruns happened outside the verb.' },
|
|
478
|
+
],
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
const samplingRule = 'controlled goal loop on a pinned snapshot with run identity and FR-016/FR-019 telemetry';
|
|
482
|
+
const biases = [
|
|
483
|
+
'union assumes overlapping verification intervals reflect concurrent execution or waiting',
|
|
484
|
+
'outside-verb tests observed with completion duration on Claude only; other harnesses record duration as unreached',
|
|
485
|
+
'child CPU ticks recorded on Linux proc-children only; unreached on Darwin/Windows',
|
|
486
|
+
'peak memory unreached on all platforms',
|
|
487
|
+
'candidate test duplicates treat all same-class repeats within a session as candidates due to absence of edit hook lines',
|
|
488
|
+
];
|
|
489
|
+
|
|
490
|
+
let aggregate = null;
|
|
491
|
+
let observed = null;
|
|
492
|
+
|
|
493
|
+
if (windowFilled) {
|
|
494
|
+
aggregate = {
|
|
495
|
+
metrics: {
|
|
496
|
+
loopWallMs: {
|
|
497
|
+
median: calcMedian(aggLoopWall),
|
|
498
|
+
range: calcRange(aggLoopWall),
|
|
499
|
+
lower: calcMedian(aggLoopWall),
|
|
500
|
+
upper: calcMedian(aggLoopWallUpper),
|
|
501
|
+
basis: 'derived',
|
|
502
|
+
},
|
|
503
|
+
verificationWallMs: {
|
|
504
|
+
median: calcMedian(aggVerifWall),
|
|
505
|
+
range: calcRange(aggVerifWall),
|
|
506
|
+
lower: calcMedian(aggVerifWall),
|
|
507
|
+
upper: calcMedian(aggVerifWallUpper),
|
|
508
|
+
basis: 'derived',
|
|
509
|
+
},
|
|
510
|
+
totalTestMs: {
|
|
511
|
+
median: calcMedian(aggTotalTest),
|
|
512
|
+
range: calcRange(aggTotalTest),
|
|
513
|
+
lower: calcMedian(aggTotalTest),
|
|
514
|
+
upper: calcMedian(aggTotalTestUpper),
|
|
515
|
+
basis: 'derived',
|
|
516
|
+
},
|
|
517
|
+
implementationMs: {
|
|
518
|
+
median: calcMedian(aggImpl),
|
|
519
|
+
range: calcRange(aggImpl),
|
|
520
|
+
lower: calcMedian(aggImpl),
|
|
521
|
+
upper: calcMedian(aggImplUpper),
|
|
522
|
+
basis: 'derived',
|
|
523
|
+
},
|
|
524
|
+
ratio: {
|
|
525
|
+
median: Number(calcMedian(aggRatio).toPrecision(3)),
|
|
526
|
+
range: calcRange(aggRatio).map((r) => Number(r.toPrecision(3))),
|
|
527
|
+
lower: Number(calcMedian(aggRatio).toPrecision(3)),
|
|
528
|
+
upper: Number(calcMedian(aggRatioUpper).toPrecision(3)),
|
|
529
|
+
basis: 'derived',
|
|
530
|
+
},
|
|
531
|
+
share: {
|
|
532
|
+
median: Number(calcMedian(aggRatio).toPrecision(3)),
|
|
533
|
+
range: calcRange(aggRatio).map((r) => Number(r.toPrecision(3))),
|
|
534
|
+
lower: Number(calcMedian(aggRatio).toPrecision(3)),
|
|
535
|
+
upper: Number(calcMedian(aggRatioUpper).toPrecision(3)),
|
|
536
|
+
basis: 'derived',
|
|
537
|
+
},
|
|
538
|
+
duplicates: {
|
|
539
|
+
median: calcMedian(aggDuplicates),
|
|
540
|
+
range: calcRange(aggDuplicates),
|
|
541
|
+
basis: 'derived',
|
|
542
|
+
},
|
|
543
|
+
fullSuiteRuns: {
|
|
544
|
+
median: calcMedian(aggFullSuite),
|
|
545
|
+
range: calcRange(aggFullSuite),
|
|
546
|
+
basis: 'derived',
|
|
547
|
+
},
|
|
548
|
+
cpuMs: {
|
|
549
|
+
median: aggCpuMedian,
|
|
550
|
+
range: aggCpuRange,
|
|
551
|
+
basis: anyCpuRecorded ? 'recorded' : 'unreached',
|
|
552
|
+
},
|
|
553
|
+
peakMemory: {
|
|
554
|
+
median: 'unreached',
|
|
555
|
+
range: null,
|
|
556
|
+
basis: 'unreached',
|
|
557
|
+
},
|
|
558
|
+
idleGapsMs: {
|
|
559
|
+
median: calcMedian(aggIdleGaps),
|
|
560
|
+
range: calcRange(aggIdleGaps),
|
|
561
|
+
basis: 'derived',
|
|
562
|
+
},
|
|
563
|
+
},
|
|
564
|
+
};
|
|
565
|
+
} else {
|
|
566
|
+
observed = {
|
|
567
|
+
n: loopsCount,
|
|
568
|
+
values: {
|
|
569
|
+
cpuMs: {
|
|
570
|
+
basis: anyCpuRecorded ? 'recorded' : 'unreached',
|
|
571
|
+
value: anyCpuRecorded ? aggCpuMedian : 'unreached',
|
|
572
|
+
},
|
|
573
|
+
duplicates: {
|
|
574
|
+
basis: 'derived',
|
|
575
|
+
value: aggDuplicates[0] ?? 0,
|
|
576
|
+
},
|
|
577
|
+
fullSuiteRuns: {
|
|
578
|
+
basis: 'derived',
|
|
579
|
+
value: aggFullSuite[0] ?? 0,
|
|
580
|
+
},
|
|
581
|
+
idleGapsMs: {
|
|
582
|
+
basis: 'derived',
|
|
583
|
+
value: aggIdleGaps[0] ?? 0,
|
|
584
|
+
},
|
|
585
|
+
implementationMs: {
|
|
586
|
+
basis: 'derived',
|
|
587
|
+
value: aggImpl[0] ?? 0,
|
|
588
|
+
},
|
|
589
|
+
loopWallMs: {
|
|
590
|
+
basis: 'derived',
|
|
591
|
+
value: aggLoopWall[0] ?? 0,
|
|
592
|
+
},
|
|
593
|
+
peakMemory: {
|
|
594
|
+
basis: 'unreached',
|
|
595
|
+
value: 'unreached',
|
|
596
|
+
},
|
|
597
|
+
ratio: {
|
|
598
|
+
basis: 'derived',
|
|
599
|
+
value: Number((aggRatio[0] ?? 0).toPrecision(3)),
|
|
600
|
+
},
|
|
601
|
+
share: {
|
|
602
|
+
basis: 'derived',
|
|
603
|
+
value: Number((aggRatio[0] ?? 0).toPrecision(3)),
|
|
604
|
+
},
|
|
605
|
+
totalTestMs: {
|
|
606
|
+
basis: 'derived',
|
|
607
|
+
value: aggTotalTest[0] ?? 0,
|
|
608
|
+
},
|
|
609
|
+
verificationWallMs: {
|
|
610
|
+
basis: 'derived',
|
|
611
|
+
value: aggVerifWall[0] ?? 0,
|
|
612
|
+
},
|
|
613
|
+
},
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
const primaryMetrics = windowFilled ? {
|
|
618
|
+
loopWallMs: aggregate.metrics.loopWallMs.median,
|
|
619
|
+
verificationWallMs: aggregate.metrics.verificationWallMs.median,
|
|
620
|
+
totalTestMs: aggregate.metrics.totalTestMs.median,
|
|
621
|
+
implementationMs: aggregate.metrics.implementationMs.median,
|
|
622
|
+
ratio: aggregate.metrics.ratio.median,
|
|
623
|
+
share: aggregate.metrics.share.median,
|
|
624
|
+
duplicates: aggregate.metrics.duplicates.median,
|
|
625
|
+
fullSuiteRuns: aggregate.metrics.fullSuiteRuns.median,
|
|
626
|
+
cpuMs: aggregate.metrics.cpuMs.median,
|
|
627
|
+
peakMemory: 'unreached',
|
|
628
|
+
idleGapsMs: aggregate.metrics.idleGapsMs.median,
|
|
629
|
+
upperBound: {
|
|
630
|
+
loopWallMs: aggregate.metrics.loopWallMs.upper,
|
|
631
|
+
verificationWallMs: aggregate.metrics.verificationWallMs.upper,
|
|
632
|
+
totalTestMs: aggregate.metrics.totalTestMs.upper,
|
|
633
|
+
implementationMs: aggregate.metrics.implementationMs.upper,
|
|
634
|
+
ratio: aggregate.metrics.ratio.upper,
|
|
635
|
+
share: aggregate.metrics.share.upper,
|
|
636
|
+
},
|
|
637
|
+
} : {
|
|
638
|
+
cpuMs: anyCpuRecorded ? aggCpuMedian : 'unreached',
|
|
639
|
+
duplicates: aggDuplicates[0] ?? 0,
|
|
640
|
+
fullSuiteRuns: aggFullSuite[0] ?? 0,
|
|
641
|
+
idleGapsMs: aggIdleGaps[0] ?? 0,
|
|
642
|
+
implementationMs: aggImpl[0] ?? 0,
|
|
643
|
+
loopWallMs: aggLoopWall[0] ?? 0,
|
|
644
|
+
peakMemory: 'unreached',
|
|
645
|
+
ratio: Number((aggRatio[0] ?? 0).toPrecision(3)),
|
|
646
|
+
share: Number((aggRatio[0] ?? 0).toPrecision(3)),
|
|
647
|
+
totalTestMs: aggTotalTest[0] ?? 0,
|
|
648
|
+
verificationWallMs: aggVerifWall[0] ?? 0,
|
|
649
|
+
};
|
|
650
|
+
|
|
651
|
+
const report = {
|
|
652
|
+
v: 1,
|
|
653
|
+
verdict,
|
|
654
|
+
progress,
|
|
655
|
+
metrics: primaryMetrics,
|
|
656
|
+
...(windowFilled ? { aggregate } : { observed }),
|
|
657
|
+
goalLoops,
|
|
658
|
+
inputTable,
|
|
659
|
+
context: {
|
|
660
|
+
surveyProxies,
|
|
661
|
+
},
|
|
662
|
+
samplingRule,
|
|
663
|
+
biases,
|
|
664
|
+
manifest: {
|
|
665
|
+
commit: manifest?.commit || null,
|
|
666
|
+
node: manifest?.node || null,
|
|
667
|
+
platform: manifest?.platform || null,
|
|
668
|
+
harness: manifest?.harness || null,
|
|
669
|
+
fileCount: Array.isArray(manifest?.files) ? manifest.files.length : 0,
|
|
670
|
+
},
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
return sorted(report);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
/** Render baseline report as readable markdown. */
|
|
677
|
+
function renderReportMarkdown(report ) {
|
|
678
|
+
const lines = [];
|
|
679
|
+
lines.push('# Verification Baseline Report\n');
|
|
680
|
+
lines.push(`**Verdict:** ${report.verdict}`);
|
|
681
|
+
lines.push(`**Measurement Window Progress (D-16):** ${report.progress}\n`);
|
|
682
|
+
|
|
683
|
+
lines.push('## Input Table\n');
|
|
684
|
+
lines.push('| Metric | Basis | Records Read | Uncaptured Inputs | Cause |');
|
|
685
|
+
lines.push('|---|---|---|---|---|');
|
|
686
|
+
for (const row of report.inputTable || []) {
|
|
687
|
+
lines.push(`| ${row.metric} | ${row.basis} | ${row.recordsRead} | ${row.uncapturedInputs} | ${row.cause} |`);
|
|
688
|
+
}
|
|
689
|
+
lines.push('');
|
|
690
|
+
|
|
691
|
+
if (!report.aggregate && report.observed) {
|
|
692
|
+
const n = report.observed.n || 1;
|
|
693
|
+
lines.push(`## Observed (n=${n}), not a result\n`);
|
|
694
|
+
lines.push('| Metric | Observed | Basis |');
|
|
695
|
+
lines.push('|---|---|---|');
|
|
696
|
+
for (const [k, v] of Object.entries(report.observed.values || {})) {
|
|
697
|
+
const val = v ;
|
|
698
|
+
const metricVal = typeof val === 'object' && val !== null && val.value !== undefined ? val.value : val;
|
|
699
|
+
const basisVal = typeof val === 'object' && val !== null && val.basis !== undefined ? val.basis : '-';
|
|
700
|
+
lines.push(`| ${k} | ${metricVal} | ${basisVal} |`);
|
|
701
|
+
}
|
|
702
|
+
lines.push('');
|
|
703
|
+
} else if (report.aggregate) {
|
|
704
|
+
lines.push('## Aggregate Metrics\n');
|
|
705
|
+
lines.push('| Metric | Median | Range | Lower End (D-1) | Upper Bound | Basis |');
|
|
706
|
+
lines.push('|---|---|---|---|---|---|');
|
|
707
|
+
for (const [k, v] of Object.entries(report.aggregate?.metrics || {})) {
|
|
708
|
+
const val = v ;
|
|
709
|
+
const medianVal = val.median !== undefined ? val.median : val;
|
|
710
|
+
const rangeVal = Array.isArray(val.range) ? `${val.range[0]} - ${val.range[1]}` : (val.range ?? '-');
|
|
711
|
+
const lowerVal = val.lower !== undefined ? val.lower : '-';
|
|
712
|
+
const upperVal = val.upper !== undefined ? val.upper : '-';
|
|
713
|
+
const basisVal = val.basis || '-';
|
|
714
|
+
lines.push(`| ${k} | ${medianVal} | ${rangeVal} | ${lowerVal} | ${upperVal} | ${basisVal} |`);
|
|
715
|
+
}
|
|
716
|
+
lines.push('');
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
lines.push('## Goal Loops\n');
|
|
720
|
+
const loops = report.goalLoops || [];
|
|
721
|
+
lines.push(`Total loops recorded: ${loops.length}\n`);
|
|
722
|
+
for (let idx = 0; idx < loops.length; idx++) {
|
|
723
|
+
const gl = loops[idx];
|
|
724
|
+
const isOpenWindow = !gl.window?.to;
|
|
725
|
+
const ubLoop = isOpenWindow ? 'open (unbounded)' : `${gl.upperBound?.loopWallMs ?? gl.metrics.loopWallMs} ms`;
|
|
726
|
+
const ubVerif = isOpenWindow ? 'open (unbounded)' : `${gl.upperBound?.verificationWallMs ?? gl.metrics.verificationWallMs} ms`;
|
|
727
|
+
const ubTest = isOpenWindow ? 'open (unbounded)' : `${gl.upperBound?.totalTestMs ?? gl.metrics.totalTestMs} ms`;
|
|
728
|
+
const ubImpl = isOpenWindow ? 'open (unbounded)' : `${gl.upperBound?.implementationMs ?? gl.metrics.implementationMs} ms`;
|
|
729
|
+
|
|
730
|
+
lines.push(`### Goal Loop ${idx + 1}: ${gl.traceId || gl.runKey || 'unnamed'}`);
|
|
731
|
+
lines.push(`- **Harness:** ${gl.harness || 'unspecified'}`);
|
|
732
|
+
lines.push(`- **Window:** ${gl.window?.from || '-'} .. ${gl.window?.to || 'open'}`);
|
|
733
|
+
lines.push(`- **Loop Wall:** ${gl.metrics.loopWallMs} ms (upper bound: ${ubLoop})`);
|
|
734
|
+
lines.push(`- **Verification Wall:** ${gl.metrics.verificationWallMs} ms (upper bound: ${ubVerif})`);
|
|
735
|
+
lines.push(`- **Total Test Time:** ${gl.metrics.totalTestMs} ms (upper bound: ${ubTest})`);
|
|
736
|
+
lines.push(`- **Implementation Time:** ${gl.metrics.implementationMs} ms (upper bound: ${ubImpl})`);
|
|
737
|
+
lines.push(`- **Verification Ratio:** ${gl.metrics.ratio}`);
|
|
738
|
+
lines.push(`- **Idle Gaps (> 30 min):** ${gl.metrics.idleGapsMs} ms (${gl.idleGaps.length} gap(s))`);
|
|
739
|
+
lines.push(`- **Duplicates:** ${gl.metrics.duplicates} (exact: ${gl.metrics.exactDuplicates}, candidate: ${gl.metrics.candidateDuplicates})`);
|
|
740
|
+
lines.push(`- **Full Suite Runs:** ${gl.metrics.fullSuiteRuns}`);
|
|
741
|
+
lines.push(`- **CPU Time:** ${gl.metrics.cpuMs}`);
|
|
742
|
+
lines.push(`- **Peak Memory:** ${gl.metrics.peakMemory}\n`);
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
lines.push('## Context: Survey Proxies\n');
|
|
746
|
+
const proxies = report.context?.surveyProxies?.proxies || [];
|
|
747
|
+
lines.push(`> [!NOTE]\n> ${report.context?.surveyProxies?.note || 'Context only'}\n`);
|
|
748
|
+
lines.push('| ID | Proxy | Share | Bias |');
|
|
749
|
+
lines.push('|---|---|---|---|');
|
|
750
|
+
for (const p of proxies) {
|
|
751
|
+
lines.push(`| ${p.id} | ${p.name} | ${p.share} | ${p.bias} |`);
|
|
752
|
+
}
|
|
753
|
+
lines.push('');
|
|
754
|
+
|
|
755
|
+
lines.push('## Sampling Rule and Biases\n');
|
|
756
|
+
lines.push(`**Sampling Rule:** ${report.samplingRule}\n`);
|
|
757
|
+
lines.push('**Biases:**');
|
|
758
|
+
for (const b of report.biases || []) {
|
|
759
|
+
lines.push(`- ${b}`);
|
|
760
|
+
}
|
|
761
|
+
lines.push('');
|
|
762
|
+
|
|
763
|
+
return lines.join('\n');
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
module.exports = {
|
|
767
|
+
buildBaseline,
|
|
768
|
+
renderReportMarkdown,
|
|
769
|
+
sorted,
|
|
770
|
+
};
|