@jokerized/getresearchdone 0.4.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/.claude-plugin/plugin.json +103 -0
- package/README.md +211 -0
- package/agents/grd-baseline-assessor.md +684 -0
- package/agents/grd-code-reviewer.md +300 -0
- package/agents/grd-codebase-mapper.md +355 -0
- package/agents/grd-critique-agent.md +119 -0
- package/agents/grd-debugger.md +519 -0
- package/agents/grd-deep-diver.md +737 -0
- package/agents/grd-eval-planner.md +913 -0
- package/agents/grd-eval-reporter.md +717 -0
- package/agents/grd-executor.md +683 -0
- package/agents/grd-feasibility-analyst.md +624 -0
- package/agents/grd-integration-checker.md +367 -0
- package/agents/grd-knowledge-miner.md +81 -0
- package/agents/grd-migrator.md +88 -0
- package/agents/grd-phase-researcher.md +697 -0
- package/agents/grd-plan-checker.md +443 -0
- package/agents/grd-planner.md +1532 -0
- package/agents/grd-product-owner.md +562 -0
- package/agents/grd-project-researcher.md +513 -0
- package/agents/grd-research-synthesizer.md +273 -0
- package/agents/grd-roadmapper.md +798 -0
- package/agents/grd-surveyor.md +566 -0
- package/agents/grd-verifier.md +893 -0
- package/bin/gd.js +4 -0
- package/bin/gd.ts +227 -0
- package/bin/grd-manifest.js +4 -0
- package/bin/grd-manifest.ts +286 -0
- package/bin/grd-mcp-server.js +4 -0
- package/bin/grd-mcp-server.ts +124 -0
- package/bin/grd-tools.js +4 -0
- package/bin/grd-tools.ts +2471 -0
- package/bin/postinstall.js +4 -0
- package/bin/postinstall.ts +80 -0
- package/commands/add-phase.md +123 -0
- package/commands/add-todo.md +87 -0
- package/commands/assess-baseline.md +289 -0
- package/commands/autopilot.md +100 -0
- package/commands/autoplan.md +55 -0
- package/commands/check-todos.md +87 -0
- package/commands/compare-methods.md +262 -0
- package/commands/complete-milestone.md +225 -0
- package/commands/debug.md +372 -0
- package/commands/deep-dive.md +288 -0
- package/commands/discover.md +281 -0
- package/commands/discuss-phase.md +188 -0
- package/commands/discuss.md +55 -0
- package/commands/eval-report.md +310 -0
- package/commands/evolve.md +79 -0
- package/commands/execute-phase.md +1017 -0
- package/commands/feasibility.md +292 -0
- package/commands/help.md +407 -0
- package/commands/init.md +1508 -0
- package/commands/insert-phase.md +113 -0
- package/commands/iterate.md +327 -0
- package/commands/list-phase-assumptions.md +217 -0
- package/commands/long-term-roadmap.md +202 -0
- package/commands/map-codebase.md +111 -0
- package/commands/migrate.md +159 -0
- package/commands/new-milestone.md +169 -0
- package/commands/pause-work.md +83 -0
- package/commands/plan-milestone-gaps.md +373 -0
- package/commands/plan-phase.md +655 -0
- package/commands/principles.md +328 -0
- package/commands/product-plan.md +319 -0
- package/commands/progress.md +481 -0
- package/commands/quick.md +167 -0
- package/commands/reapply-patches.md +154 -0
- package/commands/remove-phase.md +97 -0
- package/commands/requirement.md +96 -0
- package/commands/resume-project.md +113 -0
- package/commands/settings.md +1144 -0
- package/commands/survey.md +242 -0
- package/commands/sync.md +246 -0
- package/commands/tracker-setup.md +322 -0
- package/commands/update.md +202 -0
- package/commands/verify-phase.md +335 -0
- package/commands/verify-work.md +701 -0
- package/commands/wireup.md +29 -0
- package/dist/bin/gd.d.ts +3 -0
- package/dist/bin/gd.d.ts.map +1 -0
- package/dist/bin/gd.js +178 -0
- package/dist/bin/gd.js.map +1 -0
- package/dist/bin/grd-manifest.d.ts +3 -0
- package/dist/bin/grd-manifest.d.ts.map +1 -0
- package/dist/bin/grd-manifest.js +202 -0
- package/dist/bin/grd-manifest.js.map +1 -0
- package/dist/bin/grd-mcp-server.d.ts +3 -0
- package/dist/bin/grd-mcp-server.d.ts.map +1 -0
- package/dist/bin/grd-mcp-server.js +71 -0
- package/dist/bin/grd-mcp-server.js.map +1 -0
- package/dist/bin/grd-tools.d.ts +3 -0
- package/dist/bin/grd-tools.d.ts.map +1 -0
- package/dist/bin/grd-tools.js +1680 -0
- package/dist/bin/grd-tools.js.map +1 -0
- package/dist/bin/postinstall.d.ts +3 -0
- package/dist/bin/postinstall.d.ts.map +1 -0
- package/dist/bin/postinstall.js +61 -0
- package/dist/bin/postinstall.js.map +1 -0
- package/dist/lib/autopilot-milestone.d.ts +2 -0
- package/dist/lib/autopilot-milestone.d.ts.map +1 -0
- package/dist/lib/autopilot-milestone.js +94 -0
- package/dist/lib/autopilot-milestone.js.map +1 -0
- package/dist/lib/autopilot-pipeline.d.ts +2 -0
- package/dist/lib/autopilot-pipeline.d.ts.map +1 -0
- package/dist/lib/autopilot-pipeline.js +830 -0
- package/dist/lib/autopilot-pipeline.js.map +1 -0
- package/dist/lib/autopilot-waves.d.ts +2 -0
- package/dist/lib/autopilot-waves.d.ts.map +1 -0
- package/dist/lib/autopilot-waves.js +266 -0
- package/dist/lib/autopilot-waves.js.map +1 -0
- package/dist/lib/autopilot.d.ts +2 -0
- package/dist/lib/autopilot.d.ts.map +1 -0
- package/dist/lib/autopilot.js +1314 -0
- package/dist/lib/autopilot.js.map +1 -0
- package/dist/lib/autoplan.d.ts +2 -0
- package/dist/lib/autoplan.d.ts.map +1 -0
- package/dist/lib/autoplan.js +198 -0
- package/dist/lib/autoplan.js.map +1 -0
- package/dist/lib/autoresearch.d.ts +2 -0
- package/dist/lib/autoresearch.d.ts.map +1 -0
- package/dist/lib/autoresearch.js +626 -0
- package/dist/lib/autoresearch.js.map +1 -0
- package/dist/lib/backend.d.ts +2 -0
- package/dist/lib/backend.d.ts.map +1 -0
- package/dist/lib/backend.js +1036 -0
- package/dist/lib/backend.js.map +1 -0
- package/dist/lib/benchmark.d.ts +99 -0
- package/dist/lib/benchmark.d.ts.map +1 -0
- package/dist/lib/benchmark.js +278 -0
- package/dist/lib/benchmark.js.map +1 -0
- package/dist/lib/citations.d.ts +2 -0
- package/dist/lib/citations.d.ts.map +1 -0
- package/dist/lib/citations.js +642 -0
- package/dist/lib/citations.js.map +1 -0
- package/dist/lib/cleanup.d.ts +2 -0
- package/dist/lib/cleanup.d.ts.map +1 -0
- package/dist/lib/cleanup.js +1222 -0
- package/dist/lib/cleanup.js.map +1 -0
- package/dist/lib/cli/adapters.d.ts +10 -0
- package/dist/lib/cli/adapters.d.ts.map +1 -0
- package/dist/lib/cli/adapters.js +27 -0
- package/dist/lib/cli/adapters.js.map +1 -0
- package/dist/lib/cli/agent.d.ts +17 -0
- package/dist/lib/cli/agent.d.ts.map +1 -0
- package/dist/lib/cli/agent.js +53 -0
- package/dist/lib/cli/agent.js.map +1 -0
- package/dist/lib/cli/index.d.ts +21 -0
- package/dist/lib/cli/index.d.ts.map +1 -0
- package/dist/lib/cli/index.js +264 -0
- package/dist/lib/cli/index.js.map +1 -0
- package/dist/lib/cli/output.d.ts +20 -0
- package/dist/lib/cli/output.d.ts.map +1 -0
- package/dist/lib/cli/output.js +22 -0
- package/dist/lib/cli/output.js.map +1 -0
- package/dist/lib/cli/scan-dispatch.d.ts +9 -0
- package/dist/lib/cli/scan-dispatch.d.ts.map +1 -0
- package/dist/lib/cli/scan-dispatch.js +107 -0
- package/dist/lib/cli/scan-dispatch.js.map +1 -0
- package/dist/lib/cli/tools.d.ts +16 -0
- package/dist/lib/cli/tools.d.ts.map +1 -0
- package/dist/lib/cli/tools.js +168 -0
- package/dist/lib/cli/tools.js.map +1 -0
- package/dist/lib/commands/_dashboard-parsers.d.ts +2 -0
- package/dist/lib/commands/_dashboard-parsers.d.ts.map +1 -0
- package/dist/lib/commands/_dashboard-parsers.js +192 -0
- package/dist/lib/commands/_dashboard-parsers.js.map +1 -0
- package/dist/lib/commands/analysis.d.ts +2 -0
- package/dist/lib/commands/analysis.d.ts.map +1 -0
- package/dist/lib/commands/analysis.js +1418 -0
- package/dist/lib/commands/analysis.js.map +1 -0
- package/dist/lib/commands/assumptions.d.ts +2 -0
- package/dist/lib/commands/assumptions.d.ts.map +1 -0
- package/dist/lib/commands/assumptions.js +166 -0
- package/dist/lib/commands/assumptions.js.map +1 -0
- package/dist/lib/commands/blame.d.ts +2 -0
- package/dist/lib/commands/blame.d.ts.map +1 -0
- package/dist/lib/commands/blame.js +133 -0
- package/dist/lib/commands/blame.js.map +1 -0
- package/dist/lib/commands/budget.d.ts +2 -0
- package/dist/lib/commands/budget.d.ts.map +1 -0
- package/dist/lib/commands/budget.js +100 -0
- package/dist/lib/commands/budget.js.map +1 -0
- package/dist/lib/commands/check-plans.d.ts +2 -0
- package/dist/lib/commands/check-plans.d.ts.map +1 -0
- package/dist/lib/commands/check-plans.js +190 -0
- package/dist/lib/commands/check-plans.js.map +1 -0
- package/dist/lib/commands/config.d.ts +2 -0
- package/dist/lib/commands/config.d.ts.map +1 -0
- package/dist/lib/commands/config.js +188 -0
- package/dist/lib/commands/config.js.map +1 -0
- package/dist/lib/commands/dashboard.d.ts +2 -0
- package/dist/lib/commands/dashboard.d.ts.map +1 -0
- package/dist/lib/commands/dashboard.js +466 -0
- package/dist/lib/commands/dashboard.js.map +1 -0
- package/dist/lib/commands/estimate.d.ts +2 -0
- package/dist/lib/commands/estimate.d.ts.map +1 -0
- package/dist/lib/commands/estimate.js +148 -0
- package/dist/lib/commands/estimate.js.map +1 -0
- package/dist/lib/commands/eval-diff.d.ts +2 -0
- package/dist/lib/commands/eval-diff.d.ts.map +1 -0
- package/dist/lib/commands/eval-diff.js +213 -0
- package/dist/lib/commands/eval-diff.js.map +1 -0
- package/dist/lib/commands/freshness.d.ts +2 -0
- package/dist/lib/commands/freshness.d.ts.map +1 -0
- package/dist/lib/commands/freshness.js +163 -0
- package/dist/lib/commands/freshness.js.map +1 -0
- package/dist/lib/commands/health.d.ts +2 -0
- package/dist/lib/commands/health.d.ts.map +1 -0
- package/dist/lib/commands/health.js +435 -0
- package/dist/lib/commands/health.js.map +1 -0
- package/dist/lib/commands/index.d.ts +2 -0
- package/dist/lib/commands/index.d.ts.map +1 -0
- package/dist/lib/commands/index.js +128 -0
- package/dist/lib/commands/index.js.map +1 -0
- package/dist/lib/commands/install.d.ts +56 -0
- package/dist/lib/commands/install.d.ts.map +1 -0
- package/dist/lib/commands/install.js +214 -0
- package/dist/lib/commands/install.js.map +1 -0
- package/dist/lib/commands/knowhow-aggregator.d.ts +2 -0
- package/dist/lib/commands/knowhow-aggregator.d.ts.map +1 -0
- package/dist/lib/commands/knowhow-aggregator.js +279 -0
- package/dist/lib/commands/knowhow-aggregator.js.map +1 -0
- package/dist/lib/commands/knowledge-search.d.ts +2 -0
- package/dist/lib/commands/knowledge-search.d.ts.map +1 -0
- package/dist/lib/commands/knowledge-search.js +113 -0
- package/dist/lib/commands/knowledge-search.js.map +1 -0
- package/dist/lib/commands/long-term-roadmap.d.ts +2 -0
- package/dist/lib/commands/long-term-roadmap.d.ts.map +1 -0
- package/dist/lib/commands/long-term-roadmap.js +272 -0
- package/dist/lib/commands/long-term-roadmap.js.map +1 -0
- package/dist/lib/commands/patterns.d.ts +91 -0
- package/dist/lib/commands/patterns.d.ts.map +1 -0
- package/dist/lib/commands/patterns.js +391 -0
- package/dist/lib/commands/patterns.js.map +1 -0
- package/dist/lib/commands/phase-info.d.ts +2 -0
- package/dist/lib/commands/phase-info.d.ts.map +1 -0
- package/dist/lib/commands/phase-info.js +509 -0
- package/dist/lib/commands/phase-info.js.map +1 -0
- package/dist/lib/commands/plan-lint.d.ts +56 -0
- package/dist/lib/commands/plan-lint.d.ts.map +1 -0
- package/dist/lib/commands/plan-lint.js +481 -0
- package/dist/lib/commands/plan-lint.js.map +1 -0
- package/dist/lib/commands/plan-phase.d.ts +53 -0
- package/dist/lib/commands/plan-phase.d.ts.map +1 -0
- package/dist/lib/commands/plan-phase.js +288 -0
- package/dist/lib/commands/plan-phase.js.map +1 -0
- package/dist/lib/commands/progress.d.ts +2 -0
- package/dist/lib/commands/progress.d.ts.map +1 -0
- package/dist/lib/commands/progress.js +266 -0
- package/dist/lib/commands/progress.js.map +1 -0
- package/dist/lib/commands/quality.d.ts +2 -0
- package/dist/lib/commands/quality.d.ts.map +1 -0
- package/dist/lib/commands/quality.js +80 -0
- package/dist/lib/commands/quality.js.map +1 -0
- package/dist/lib/commands/rollback.d.ts +2 -0
- package/dist/lib/commands/rollback.d.ts.map +1 -0
- package/dist/lib/commands/rollback.js +145 -0
- package/dist/lib/commands/rollback.js.map +1 -0
- package/dist/lib/commands/scan.d.ts +25 -0
- package/dist/lib/commands/scan.d.ts.map +1 -0
- package/dist/lib/commands/scan.js +28 -0
- package/dist/lib/commands/scan.js.map +1 -0
- package/dist/lib/commands/search.d.ts +2 -0
- package/dist/lib/commands/search.d.ts.map +1 -0
- package/dist/lib/commands/search.js +212 -0
- package/dist/lib/commands/search.js.map +1 -0
- package/dist/lib/commands/select-candidate.d.ts +128 -0
- package/dist/lib/commands/select-candidate.d.ts.map +1 -0
- package/dist/lib/commands/select-candidate.js +518 -0
- package/dist/lib/commands/select-candidate.js.map +1 -0
- package/dist/lib/commands/singularity.d.ts +2 -0
- package/dist/lib/commands/singularity.d.ts.map +1 -0
- package/dist/lib/commands/singularity.js +185 -0
- package/dist/lib/commands/singularity.js.map +1 -0
- package/dist/lib/commands/slug-timestamp.d.ts +2 -0
- package/dist/lib/commands/slug-timestamp.d.ts.map +1 -0
- package/dist/lib/commands/slug-timestamp.js +54 -0
- package/dist/lib/commands/slug-timestamp.js.map +1 -0
- package/dist/lib/commands/tail.d.ts +2 -0
- package/dist/lib/commands/tail.d.ts.map +1 -0
- package/dist/lib/commands/tail.js +100 -0
- package/dist/lib/commands/tail.js.map +1 -0
- package/dist/lib/commands/todo.d.ts +2 -0
- package/dist/lib/commands/todo.d.ts.map +1 -0
- package/dist/lib/commands/todo.js +200 -0
- package/dist/lib/commands/todo.js.map +1 -0
- package/dist/lib/commands/watch.d.ts +2 -0
- package/dist/lib/commands/watch.d.ts.map +1 -0
- package/dist/lib/commands/watch.js +72 -0
- package/dist/lib/commands/watch.js.map +1 -0
- package/dist/lib/complexity.d.ts +55 -0
- package/dist/lib/complexity.d.ts.map +1 -0
- package/dist/lib/complexity.js +80 -0
- package/dist/lib/complexity.js.map +1 -0
- package/dist/lib/context/agents.d.ts +2 -0
- package/dist/lib/context/agents.d.ts.map +1 -0
- package/dist/lib/context/agents.js +344 -0
- package/dist/lib/context/agents.js.map +1 -0
- package/dist/lib/context/base.d.ts +2 -0
- package/dist/lib/context/base.d.ts.map +1 -0
- package/dist/lib/context/base.js +81 -0
- package/dist/lib/context/base.js.map +1 -0
- package/dist/lib/context/execute.d.ts +2 -0
- package/dist/lib/context/execute.d.ts.map +1 -0
- package/dist/lib/context/execute.js +753 -0
- package/dist/lib/context/execute.js.map +1 -0
- package/dist/lib/context/index.d.ts +2 -0
- package/dist/lib/context/index.d.ts.map +1 -0
- package/dist/lib/context/index.js +88 -0
- package/dist/lib/context/index.js.map +1 -0
- package/dist/lib/context/progress.d.ts +2 -0
- package/dist/lib/context/progress.d.ts.map +1 -0
- package/dist/lib/context/progress.js +178 -0
- package/dist/lib/context/progress.js.map +1 -0
- package/dist/lib/context/project.d.ts +2 -0
- package/dist/lib/context/project.d.ts.map +1 -0
- package/dist/lib/context/project.js +413 -0
- package/dist/lib/context/project.js.map +1 -0
- package/dist/lib/context/research.d.ts +2 -0
- package/dist/lib/context/research.d.ts.map +1 -0
- package/dist/lib/context/research.js +466 -0
- package/dist/lib/context/research.js.map +1 -0
- package/dist/lib/dead-ends.d.ts +28 -0
- package/dist/lib/dead-ends.d.ts.map +1 -0
- package/dist/lib/dead-ends.js +451 -0
- package/dist/lib/dead-ends.js.map +1 -0
- package/dist/lib/deps.d.ts +2 -0
- package/dist/lib/deps.d.ts.map +1 -0
- package/dist/lib/deps.js +630 -0
- package/dist/lib/deps.js.map +1 -0
- package/dist/lib/discussion.d.ts +2 -0
- package/dist/lib/discussion.d.ts.map +1 -0
- package/dist/lib/discussion.js +1041 -0
- package/dist/lib/discussion.js.map +1 -0
- package/dist/lib/drift.d.ts +36 -0
- package/dist/lib/drift.d.ts.map +1 -0
- package/dist/lib/drift.js +481 -0
- package/dist/lib/drift.js.map +1 -0
- package/dist/lib/evolve/_dimensions-features.d.ts +2 -0
- package/dist/lib/evolve/_dimensions-features.d.ts.map +1 -0
- package/dist/lib/evolve/_dimensions-features.js +369 -0
- package/dist/lib/evolve/_dimensions-features.js.map +1 -0
- package/dist/lib/evolve/_dimensions.d.ts +2 -0
- package/dist/lib/evolve/_dimensions.d.ts.map +1 -0
- package/dist/lib/evolve/_dimensions.js +358 -0
- package/dist/lib/evolve/_dimensions.js.map +1 -0
- package/dist/lib/evolve/_product-ideation.d.ts +2 -0
- package/dist/lib/evolve/_product-ideation.d.ts.map +1 -0
- package/dist/lib/evolve/_product-ideation.js +281 -0
- package/dist/lib/evolve/_product-ideation.js.map +1 -0
- package/dist/lib/evolve/_prompts.d.ts +2 -0
- package/dist/lib/evolve/_prompts.d.ts.map +1 -0
- package/dist/lib/evolve/_prompts.js +153 -0
- package/dist/lib/evolve/_prompts.js.map +1 -0
- package/dist/lib/evolve/cli.d.ts +2 -0
- package/dist/lib/evolve/cli.d.ts.map +1 -0
- package/dist/lib/evolve/cli.js +224 -0
- package/dist/lib/evolve/cli.js.map +1 -0
- package/dist/lib/evolve/discovery.d.ts +2 -0
- package/dist/lib/evolve/discovery.d.ts.map +1 -0
- package/dist/lib/evolve/discovery.js +391 -0
- package/dist/lib/evolve/discovery.js.map +1 -0
- package/dist/lib/evolve/index.d.ts +2 -0
- package/dist/lib/evolve/index.d.ts.map +1 -0
- package/dist/lib/evolve/index.js +88 -0
- package/dist/lib/evolve/index.js.map +1 -0
- package/dist/lib/evolve/orchestrator.d.ts +2 -0
- package/dist/lib/evolve/orchestrator.d.ts.map +1 -0
- package/dist/lib/evolve/orchestrator.js +851 -0
- package/dist/lib/evolve/orchestrator.js.map +1 -0
- package/dist/lib/evolve/scoring.d.ts +2 -0
- package/dist/lib/evolve/scoring.d.ts.map +1 -0
- package/dist/lib/evolve/scoring.js +118 -0
- package/dist/lib/evolve/scoring.js.map +1 -0
- package/dist/lib/evolve/state.d.ts +2 -0
- package/dist/lib/evolve/state.d.ts.map +1 -0
- package/dist/lib/evolve/state.js +264 -0
- package/dist/lib/evolve/state.js.map +1 -0
- package/dist/lib/evolve/types.d.ts +249 -0
- package/dist/lib/evolve/types.d.ts.map +1 -0
- package/dist/lib/evolve/types.js +3 -0
- package/dist/lib/evolve/types.js.map +1 -0
- package/dist/lib/frontmatter.d.ts +2 -0
- package/dist/lib/frontmatter.d.ts.map +1 -0
- package/dist/lib/frontmatter.js +513 -0
- package/dist/lib/frontmatter.js.map +1 -0
- package/dist/lib/gates.d.ts +2 -0
- package/dist/lib/gates.d.ts.map +1 -0
- package/dist/lib/gates.js +578 -0
- package/dist/lib/gates.js.map +1 -0
- package/dist/lib/genome.d.ts +10 -0
- package/dist/lib/genome.d.ts.map +1 -0
- package/dist/lib/genome.js +368 -0
- package/dist/lib/genome.js.map +1 -0
- package/dist/lib/got.d.ts +2 -0
- package/dist/lib/got.d.ts.map +1 -0
- package/dist/lib/got.js +280 -0
- package/dist/lib/got.js.map +1 -0
- package/dist/lib/invariants.d.ts +2 -0
- package/dist/lib/invariants.d.ts.map +1 -0
- package/dist/lib/invariants.js +298 -0
- package/dist/lib/invariants.js.map +1 -0
- package/dist/lib/knowledge.d.ts +2 -0
- package/dist/lib/knowledge.d.ts.map +1 -0
- package/dist/lib/knowledge.js +658 -0
- package/dist/lib/knowledge.js.map +1 -0
- package/dist/lib/long-term-roadmap.d.ts +2 -0
- package/dist/lib/long-term-roadmap.d.ts.map +1 -0
- package/dist/lib/long-term-roadmap.js +602 -0
- package/dist/lib/long-term-roadmap.js.map +1 -0
- package/dist/lib/markdown-split.d.ts +2 -0
- package/dist/lib/markdown-split.d.ts.map +1 -0
- package/dist/lib/markdown-split.js +199 -0
- package/dist/lib/markdown-split.js.map +1 -0
- package/dist/lib/mcp-server.d.ts +2 -0
- package/dist/lib/mcp-server.d.ts.map +1 -0
- package/dist/lib/mcp-server.js +2424 -0
- package/dist/lib/mcp-server.js.map +1 -0
- package/dist/lib/metrics.d.ts +16 -0
- package/dist/lib/metrics.d.ts.map +1 -0
- package/dist/lib/metrics.js +48 -0
- package/dist/lib/metrics.js.map +1 -0
- package/dist/lib/overstory.d.ts +2 -0
- package/dist/lib/overstory.d.ts.map +1 -0
- package/dist/lib/overstory.js +211 -0
- package/dist/lib/overstory.js.map +1 -0
- package/dist/lib/parallel.d.ts +2 -0
- package/dist/lib/parallel.d.ts.map +1 -0
- package/dist/lib/parallel.js +349 -0
- package/dist/lib/parallel.js.map +1 -0
- package/dist/lib/paths.d.ts +2 -0
- package/dist/lib/paths.d.ts.map +1 -0
- package/dist/lib/paths.js +254 -0
- package/dist/lib/paths.js.map +1 -0
- package/dist/lib/phase-complete-llm.d.ts +22 -0
- package/dist/lib/phase-complete-llm.d.ts.map +1 -0
- package/dist/lib/phase-complete-llm.js +331 -0
- package/dist/lib/phase-complete-llm.js.map +1 -0
- package/dist/lib/phase-complete.d.ts +46 -0
- package/dist/lib/phase-complete.d.ts.map +1 -0
- package/dist/lib/phase-complete.js +278 -0
- package/dist/lib/phase-complete.js.map +1 -0
- package/dist/lib/phase-io.d.ts +2 -0
- package/dist/lib/phase-io.d.ts.map +1 -0
- package/dist/lib/phase-io.js +126 -0
- package/dist/lib/phase-io.js.map +1 -0
- package/dist/lib/phase.d.ts +2 -0
- package/dist/lib/phase.d.ts.map +1 -0
- package/dist/lib/phase.js +1344 -0
- package/dist/lib/phase.js.map +1 -0
- package/dist/lib/plan-tournament.d.ts +63 -0
- package/dist/lib/plan-tournament.d.ts.map +1 -0
- package/dist/lib/plan-tournament.js +353 -0
- package/dist/lib/plan-tournament.js.map +1 -0
- package/dist/lib/refinement.d.ts +74 -0
- package/dist/lib/refinement.d.ts.map +1 -0
- package/dist/lib/refinement.js +283 -0
- package/dist/lib/refinement.js.map +1 -0
- package/dist/lib/requirements.d.ts +2 -0
- package/dist/lib/requirements.d.ts.map +1 -0
- package/dist/lib/requirements.js +355 -0
- package/dist/lib/requirements.js.map +1 -0
- package/dist/lib/research-bundle.d.ts +2 -0
- package/dist/lib/research-bundle.d.ts.map +1 -0
- package/dist/lib/research-bundle.js +246 -0
- package/dist/lib/research-bundle.js.map +1 -0
- package/dist/lib/roadmap.d.ts +2 -0
- package/dist/lib/roadmap.d.ts.map +1 -0
- package/dist/lib/roadmap.js +541 -0
- package/dist/lib/roadmap.js.map +1 -0
- package/dist/lib/sample.d.ts +16 -0
- package/dist/lib/sample.d.ts.map +1 -0
- package/dist/lib/sample.js +20 -0
- package/dist/lib/sample.js.map +1 -0
- package/dist/lib/scaffold.d.ts +2 -0
- package/dist/lib/scaffold.d.ts.map +1 -0
- package/dist/lib/scaffold.js +355 -0
- package/dist/lib/scaffold.js.map +1 -0
- package/dist/lib/scan/_utils.d.ts +11 -0
- package/dist/lib/scan/_utils.d.ts.map +1 -0
- package/dist/lib/scan/_utils.js +36 -0
- package/dist/lib/scan/_utils.js.map +1 -0
- package/dist/lib/scan/base64.d.ts +15 -0
- package/dist/lib/scan/base64.d.ts.map +1 -0
- package/dist/lib/scan/base64.js +66 -0
- package/dist/lib/scan/base64.js.map +1 -0
- package/dist/lib/scan/ignorefile.d.ts +30 -0
- package/dist/lib/scan/ignorefile.d.ts.map +1 -0
- package/dist/lib/scan/ignorefile.js +101 -0
- package/dist/lib/scan/ignorefile.js.map +1 -0
- package/dist/lib/scan/injection.d.ts +14 -0
- package/dist/lib/scan/injection.d.ts.map +1 -0
- package/dist/lib/scan/injection.js +39 -0
- package/dist/lib/scan/injection.js.map +1 -0
- package/dist/lib/scan/patterns.d.ts +17 -0
- package/dist/lib/scan/patterns.d.ts.map +1 -0
- package/dist/lib/scan/patterns.js +123 -0
- package/dist/lib/scan/patterns.js.map +1 -0
- package/dist/lib/scan/strip-markdown.d.ts +7 -0
- package/dist/lib/scan/strip-markdown.d.ts.map +1 -0
- package/dist/lib/scan/strip-markdown.js +38 -0
- package/dist/lib/scan/strip-markdown.js.map +1 -0
- package/dist/lib/scan/types.d.ts +23 -0
- package/dist/lib/scan/types.d.ts.map +1 -0
- package/dist/lib/scan/types.js +3 -0
- package/dist/lib/scan/types.js.map +1 -0
- package/dist/lib/scheduler-wait.d.ts +2 -0
- package/dist/lib/scheduler-wait.d.ts.map +1 -0
- package/dist/lib/scheduler-wait.js +59 -0
- package/dist/lib/scheduler-wait.js.map +1 -0
- package/dist/lib/scheduler.d.ts +254 -0
- package/dist/lib/scheduler.d.ts.map +1 -0
- package/dist/lib/scheduler.js +1147 -0
- package/dist/lib/scheduler.js.map +1 -0
- package/dist/lib/state.d.ts +2 -0
- package/dist/lib/state.d.ts.map +1 -0
- package/dist/lib/state.js +744 -0
- package/dist/lib/state.js.map +1 -0
- package/dist/lib/think.d.ts +18 -0
- package/dist/lib/think.d.ts.map +1 -0
- package/dist/lib/think.js +317 -0
- package/dist/lib/think.js.map +1 -0
- package/dist/lib/tracker.d.ts +2 -0
- package/dist/lib/tracker.d.ts.map +1 -0
- package/dist/lib/tracker.js +1121 -0
- package/dist/lib/tracker.js.map +1 -0
- package/dist/lib/types.d.ts +1514 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +4 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +1363 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/lib/verify.d.ts +2 -0
- package/dist/lib/verify.d.ts.map +1 -0
- package/dist/lib/verify.js +1153 -0
- package/dist/lib/verify.js.map +1 -0
- package/dist/lib/wireup/autofix.d.ts +2 -0
- package/dist/lib/wireup/autofix.d.ts.map +1 -0
- package/dist/lib/wireup/autofix.js +188 -0
- package/dist/lib/wireup/autofix.js.map +1 -0
- package/dist/lib/wireup/cli.d.ts +2 -0
- package/dist/lib/wireup/cli.d.ts.map +1 -0
- package/dist/lib/wireup/cli.js +194 -0
- package/dist/lib/wireup/cli.js.map +1 -0
- package/dist/lib/wireup/detection.d.ts +47 -0
- package/dist/lib/wireup/detection.d.ts.map +1 -0
- package/dist/lib/wireup/detection.js +410 -0
- package/dist/lib/wireup/detection.js.map +1 -0
- package/dist/lib/wireup/discovery.d.ts +2 -0
- package/dist/lib/wireup/discovery.d.ts.map +1 -0
- package/dist/lib/wireup/discovery.js +934 -0
- package/dist/lib/wireup/discovery.js.map +1 -0
- package/dist/lib/wireup/execution.d.ts +2 -0
- package/dist/lib/wireup/execution.d.ts.map +1 -0
- package/dist/lib/wireup/execution.js +573 -0
- package/dist/lib/wireup/execution.js.map +1 -0
- package/dist/lib/wireup/index.d.ts +2 -0
- package/dist/lib/wireup/index.d.ts.map +1 -0
- package/dist/lib/wireup/index.js +85 -0
- package/dist/lib/wireup/index.js.map +1 -0
- package/dist/lib/wireup/orchestrator.d.ts +2 -0
- package/dist/lib/wireup/orchestrator.d.ts.map +1 -0
- package/dist/lib/wireup/orchestrator.js +366 -0
- package/dist/lib/wireup/orchestrator.js.map +1 -0
- package/dist/lib/wireup/report.d.ts +47 -0
- package/dist/lib/wireup/report.d.ts.map +1 -0
- package/dist/lib/wireup/report.js +201 -0
- package/dist/lib/wireup/report.js.map +1 -0
- package/dist/lib/wireup/scenarios.d.ts +2 -0
- package/dist/lib/wireup/scenarios.d.ts.map +1 -0
- package/dist/lib/wireup/scenarios.js +516 -0
- package/dist/lib/wireup/scenarios.js.map +1 -0
- package/dist/lib/wireup/state.d.ts +2 -0
- package/dist/lib/wireup/state.d.ts.map +1 -0
- package/dist/lib/wireup/state.js +102 -0
- package/dist/lib/wireup/state.js.map +1 -0
- package/dist/lib/wireup/types.d.ts +376 -0
- package/dist/lib/wireup/types.d.ts.map +1 -0
- package/dist/lib/wireup/types.js +3 -0
- package/dist/lib/wireup/types.js.map +1 -0
- package/dist/lib/worktree.d.ts +2 -0
- package/dist/lib/worktree.d.ts.map +1 -0
- package/dist/lib/worktree.js +999 -0
- package/dist/lib/worktree.js.map +1 -0
- package/lib/autopilot-milestone.ts +136 -0
- package/lib/autopilot-pipeline.ts +1179 -0
- package/lib/autopilot-waves.ts +361 -0
- package/lib/autopilot.ts +1874 -0
- package/lib/autoplan.ts +280 -0
- package/lib/autoresearch.js +4 -0
- package/lib/autoresearch.ts +886 -0
- package/lib/backend.ts +1252 -0
- package/lib/benchmark.ts +341 -0
- package/lib/citations.ts +760 -0
- package/lib/cleanup.ts +1588 -0
- package/lib/cli/adapters.ts +41 -0
- package/lib/cli/agent.ts +83 -0
- package/lib/cli/index.ts +273 -0
- package/lib/cli/output.ts +33 -0
- package/lib/cli/scan-dispatch.ts +130 -0
- package/lib/cli/tools.ts +198 -0
- package/lib/commands/_dashboard-parsers.ts +275 -0
- package/lib/commands/analysis.ts +1851 -0
- package/lib/commands/assumptions.ts +232 -0
- package/lib/commands/blame.ts +174 -0
- package/lib/commands/budget.ts +148 -0
- package/lib/commands/check-plans.ts +233 -0
- package/lib/commands/config.ts +287 -0
- package/lib/commands/dashboard.ts +680 -0
- package/lib/commands/estimate.ts +204 -0
- package/lib/commands/eval-diff.ts +252 -0
- package/lib/commands/freshness.ts +213 -0
- package/lib/commands/health.ts +607 -0
- package/lib/commands/index.ts +266 -0
- package/lib/commands/install.ts +307 -0
- package/lib/commands/knowhow-aggregator.ts +345 -0
- package/lib/commands/knowledge-search.ts +153 -0
- package/lib/commands/long-term-roadmap.ts +390 -0
- package/lib/commands/patterns.ts +465 -0
- package/lib/commands/phase-info.ts +698 -0
- package/lib/commands/plan-lint.ts +546 -0
- package/lib/commands/plan-phase.ts +375 -0
- package/lib/commands/progress.ts +319 -0
- package/lib/commands/quality.ts +138 -0
- package/lib/commands/rollback.ts +195 -0
- package/lib/commands/scan.ts +72 -0
- package/lib/commands/search.ts +300 -0
- package/lib/commands/select-candidate.ts +687 -0
- package/lib/commands/singularity.ts +222 -0
- package/lib/commands/slug-timestamp.ts +74 -0
- package/lib/commands/tail.ts +129 -0
- package/lib/commands/todo.ts +273 -0
- package/lib/commands/watch.ts +80 -0
- package/lib/complexity.ts +117 -0
- package/lib/context/agents.ts +505 -0
- package/lib/context/base.ts +123 -0
- package/lib/context/execute.ts +977 -0
- package/lib/context/index.ts +110 -0
- package/lib/context/progress.ts +278 -0
- package/lib/context/project.ts +531 -0
- package/lib/context/research.ts +646 -0
- package/lib/dead-ends.ts +506 -0
- package/lib/deps.ts +773 -0
- package/lib/discussion.ts +1275 -0
- package/lib/drift.ts +519 -0
- package/lib/evolve/_dimensions-features.ts +525 -0
- package/lib/evolve/_dimensions.ts +511 -0
- package/lib/evolve/_product-ideation.ts +405 -0
- package/lib/evolve/_prompts.ts +178 -0
- package/lib/evolve/cli.ts +330 -0
- package/lib/evolve/discovery.ts +571 -0
- package/lib/evolve/index.ts +105 -0
- package/lib/evolve/orchestrator.ts +1139 -0
- package/lib/evolve/scoring.ts +167 -0
- package/lib/evolve/state.ts +330 -0
- package/lib/evolve/types.ts +290 -0
- package/lib/frontmatter.ts +615 -0
- package/lib/gates.ts +695 -0
- package/lib/genome.ts +402 -0
- package/lib/got.js +4 -0
- package/lib/got.ts +361 -0
- package/lib/invariants.ts +378 -0
- package/lib/knowledge.ts +768 -0
- package/lib/long-term-roadmap.ts +806 -0
- package/lib/markdown-split.ts +273 -0
- package/lib/mcp-server.ts +3292 -0
- package/lib/metrics.ts +49 -0
- package/lib/overstory.ts +270 -0
- package/lib/parallel.ts +570 -0
- package/lib/paths.ts +293 -0
- package/lib/phase-complete-llm.ts +376 -0
- package/lib/phase-complete.ts +366 -0
- package/lib/phase-io.ts +101 -0
- package/lib/phase.ts +1981 -0
- package/lib/plan-tournament.ts +426 -0
- package/lib/refinement.ts +349 -0
- package/lib/requirements.ts +469 -0
- package/lib/research-bundle.ts +300 -0
- package/lib/roadmap.ts +775 -0
- package/lib/scaffold.ts +480 -0
- package/lib/scan/_utils.ts +37 -0
- package/lib/scan/base64.ts +90 -0
- package/lib/scan/ignorefile.ts +109 -0
- package/lib/scan/injection.ts +67 -0
- package/lib/scan/patterns.ts +139 -0
- package/lib/scan/strip-markdown.ts +39 -0
- package/lib/scan/types.ts +28 -0
- package/lib/scheduler-wait.ts +58 -0
- package/lib/scheduler.ts +1370 -0
- package/lib/state.ts +1000 -0
- package/lib/think.ts +365 -0
- package/lib/tracker.ts +1591 -0
- package/lib/types.ts +1663 -0
- package/lib/utils.ts +1479 -0
- package/lib/verify.ts +1434 -0
- package/lib/wireup/autofix.ts +241 -0
- package/lib/wireup/cli.ts +278 -0
- package/lib/wireup/detection.ts +542 -0
- package/lib/wireup/discovery.ts +1063 -0
- package/lib/wireup/execution.ts +686 -0
- package/lib/wireup/index.ts +117 -0
- package/lib/wireup/orchestrator.ts +519 -0
- package/lib/wireup/report.ts +286 -0
- package/lib/wireup/scenarios.ts +616 -0
- package/lib/wireup/state.ts +139 -0
- package/lib/wireup/types.ts +436 -0
- package/lib/worktree.ts +1309 -0
- package/package.json +67 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* GRD Commands/Singularity — what % of the codebase came from `gd evolve`.
|
|
5
|
+
*
|
|
6
|
+
* Inspired by Aider's "Singularity %" metric (% of the last release written
|
|
7
|
+
* by Aider itself). For GRD, we measure across multiple windows:
|
|
8
|
+
*
|
|
9
|
+
* - `--since=<ref>` : LOC added in commits between <ref>..HEAD whose
|
|
10
|
+
* commit message matches an evolve signature, divided
|
|
11
|
+
* by total LOC added in that range.
|
|
12
|
+
* - `--all` : entire git history.
|
|
13
|
+
* - default : the most recent release tag → HEAD.
|
|
14
|
+
*
|
|
15
|
+
* Evolve signature is any of:
|
|
16
|
+
* - subject line begins with `feat(evolve` or `fix(evolve`
|
|
17
|
+
* - body contains `gd evolve` reference or Iteration <N> tag
|
|
18
|
+
* - body contains `runInfiniteEvolve` cycle reference
|
|
19
|
+
*
|
|
20
|
+
* Output (default JSON, --raw markdown):
|
|
21
|
+
* {
|
|
22
|
+
* "window": "v0.3.24..HEAD",
|
|
23
|
+
* "evolve_commits": 18,
|
|
24
|
+
* "total_commits": 51,
|
|
25
|
+
* "evolve_loc_added": 8421,
|
|
26
|
+
* "total_loc_added": 11203,
|
|
27
|
+
* "singularity_pct": 75.2
|
|
28
|
+
* }
|
|
29
|
+
*
|
|
30
|
+
* Data source: parsed from `git log --numstat --pretty=format:%H|%s|%b`. No
|
|
31
|
+
* LLM ran. Deterministic and reproducible.
|
|
32
|
+
*
|
|
33
|
+
* Codex r48 sibling-of-paper-section: this is the metric we promised in
|
|
34
|
+
* docs/ouroboros-loop.md §8.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
const cp = require('child_process') as typeof import('child_process');
|
|
38
|
+
|
|
39
|
+
const {
|
|
40
|
+
output,
|
|
41
|
+
error,
|
|
42
|
+
}: {
|
|
43
|
+
output: (result: unknown, raw: boolean, rawValue?: unknown) => never;
|
|
44
|
+
error: (message: string) => never;
|
|
45
|
+
} = require('../utils');
|
|
46
|
+
|
|
47
|
+
interface SingularityReport {
|
|
48
|
+
window: string;
|
|
49
|
+
evolve_commits: number;
|
|
50
|
+
total_commits: number;
|
|
51
|
+
evolve_loc_added: number;
|
|
52
|
+
evolve_loc_removed: number;
|
|
53
|
+
total_loc_added: number;
|
|
54
|
+
total_loc_removed: number;
|
|
55
|
+
singularity_pct: number;
|
|
56
|
+
by_iteration?: Record<string, { commits: number; loc_added: number }>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const EVOLVE_SUBJECT_RE = /^(?:feat|fix|refactor|chore|docs|test)\(evolve(?:-[a-z0-9]+)?\)/i;
|
|
60
|
+
const EVOLVE_BODY_RE = /\b(?:gd evolve|runInfiniteEvolve|Iteration\s+\d+|evolve-iter|evolve\s+iteration)\b/i;
|
|
61
|
+
const ITERATION_RE = /\b(?:iter(?:ation)?|round)\s+(\d+)\b/i;
|
|
62
|
+
|
|
63
|
+
function _runGit(args: string[]): string {
|
|
64
|
+
try {
|
|
65
|
+
const r = cp.spawnSync('git', args, {
|
|
66
|
+
encoding: 'utf-8',
|
|
67
|
+
maxBuffer: 128 * 1024 * 1024,
|
|
68
|
+
});
|
|
69
|
+
if (r.status !== 0) return '';
|
|
70
|
+
return (r.stdout ?? '') as string;
|
|
71
|
+
} catch {
|
|
72
|
+
return '';
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function _resolveWindow(since: string | null, all: boolean): string {
|
|
77
|
+
if (all) return ''; // empty = full history
|
|
78
|
+
if (since) return `${since}..HEAD`;
|
|
79
|
+
// default: most recent tag
|
|
80
|
+
const tag = _runGit(['describe', '--tags', '--abbrev=0']).trim();
|
|
81
|
+
return tag ? `${tag}..HEAD` : '';
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
interface ParsedCommit {
|
|
85
|
+
sha: string;
|
|
86
|
+
subject: string;
|
|
87
|
+
body: string;
|
|
88
|
+
filesAdded: number;
|
|
89
|
+
filesRemoved: number;
|
|
90
|
+
isEvolve: boolean;
|
|
91
|
+
iteration: number | null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function _parseCommits(range: string): ParsedCommit[] {
|
|
95
|
+
// Use a unique record separator unlikely to appear in commit messages.
|
|
96
|
+
const SEP = '\x1eCOMMIT\x1e';
|
|
97
|
+
const FIELD_SEP = '\x1fFIELD\x1f';
|
|
98
|
+
const formatted = `${SEP}%H${FIELD_SEP}%s${FIELD_SEP}%b${FIELD_SEP}`;
|
|
99
|
+
const args = ['log', '--numstat', `--pretty=format:${formatted}`];
|
|
100
|
+
if (range) args.push(range);
|
|
101
|
+
const out = _runGit(args);
|
|
102
|
+
const commits: ParsedCommit[] = [];
|
|
103
|
+
for (const rec of out.split(SEP).filter((r) => r.trim().length > 0)) {
|
|
104
|
+
// The format string ends with a trailing FIELD_SEP, so the record is:
|
|
105
|
+
// <hash><FIELD_SEP><subject><FIELD_SEP><body><FIELD_SEP><newline><numstat>
|
|
106
|
+
// Split on FIELD_SEP into 4 parts; the 4th is everything after the
|
|
107
|
+
// final FIELD_SEP (newline + numstat lines).
|
|
108
|
+
const parts = rec.split(FIELD_SEP);
|
|
109
|
+
const sha = parts[0]?.trim() ?? '';
|
|
110
|
+
const subject = parts[1] ?? '';
|
|
111
|
+
const body = parts[2] ?? '';
|
|
112
|
+
const numstat = parts[3] ?? '';
|
|
113
|
+
if (!sha) continue;
|
|
114
|
+
let added = 0;
|
|
115
|
+
let removed = 0;
|
|
116
|
+
if (numstat) {
|
|
117
|
+
for (const line of numstat.split('\n')) {
|
|
118
|
+
const m = line.match(/^(\d+|-)\s+(\d+|-)\s+(.+)$/);
|
|
119
|
+
if (!m) continue;
|
|
120
|
+
const aRaw = m[1];
|
|
121
|
+
const rRaw = m[2];
|
|
122
|
+
if (aRaw === '-' || rRaw === '-') continue; // binary file
|
|
123
|
+
added += parseInt(aRaw, 10) || 0;
|
|
124
|
+
removed += parseInt(rRaw, 10) || 0;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const isEvolve = EVOLVE_SUBJECT_RE.test(subject) || EVOLVE_BODY_RE.test(body);
|
|
128
|
+
const iterMatch = (subject + ' ' + body).match(ITERATION_RE);
|
|
129
|
+
const iteration = iterMatch ? parseInt(iterMatch[1], 10) : null;
|
|
130
|
+
commits.push({ sha, subject, body, filesAdded: added, filesRemoved: removed, isEvolve, iteration });
|
|
131
|
+
}
|
|
132
|
+
return commits;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function _computeReport(window: string, commits: ParsedCommit[], byIter: boolean): SingularityReport {
|
|
136
|
+
let evolveCommits = 0;
|
|
137
|
+
let evolveAdded = 0;
|
|
138
|
+
let evolveRemoved = 0;
|
|
139
|
+
let totalAdded = 0;
|
|
140
|
+
let totalRemoved = 0;
|
|
141
|
+
const byIteration: Record<string, { commits: number; loc_added: number }> = {};
|
|
142
|
+
for (const c of commits) {
|
|
143
|
+
totalAdded += c.filesAdded;
|
|
144
|
+
totalRemoved += c.filesRemoved;
|
|
145
|
+
if (c.isEvolve) {
|
|
146
|
+
evolveCommits++;
|
|
147
|
+
evolveAdded += c.filesAdded;
|
|
148
|
+
evolveRemoved += c.filesRemoved;
|
|
149
|
+
if (byIter && c.iteration !== null) {
|
|
150
|
+
const key = String(c.iteration);
|
|
151
|
+
if (!byIteration[key]) byIteration[key] = { commits: 0, loc_added: 0 };
|
|
152
|
+
byIteration[key].commits++;
|
|
153
|
+
byIteration[key].loc_added += c.filesAdded;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
const pct = totalAdded === 0 ? 0 : Math.round((evolveAdded / totalAdded) * 1000) / 10;
|
|
158
|
+
const report: SingularityReport = {
|
|
159
|
+
window: window || '(all-history)',
|
|
160
|
+
evolve_commits: evolveCommits,
|
|
161
|
+
total_commits: commits.length,
|
|
162
|
+
evolve_loc_added: evolveAdded,
|
|
163
|
+
evolve_loc_removed: evolveRemoved,
|
|
164
|
+
total_loc_added: totalAdded,
|
|
165
|
+
total_loc_removed: totalRemoved,
|
|
166
|
+
singularity_pct: pct,
|
|
167
|
+
};
|
|
168
|
+
if (byIter) report.by_iteration = byIteration;
|
|
169
|
+
return report;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function _renderMarkdown(r: SingularityReport): string {
|
|
173
|
+
const lines: string[] = [];
|
|
174
|
+
lines.push(`# Singularity Report`);
|
|
175
|
+
lines.push('');
|
|
176
|
+
lines.push(`**Window:** \`${r.window}\``);
|
|
177
|
+
lines.push('');
|
|
178
|
+
lines.push(`**Singularity:** ${r.singularity_pct.toFixed(1)}%`);
|
|
179
|
+
lines.push('');
|
|
180
|
+
lines.push('| Source | Commits | LOC added | LOC removed |');
|
|
181
|
+
lines.push('|---|---:|---:|---:|');
|
|
182
|
+
lines.push(
|
|
183
|
+
`| gd evolve | ${r.evolve_commits} | ${r.evolve_loc_added.toLocaleString()} | ${r.evolve_loc_removed.toLocaleString()} |`
|
|
184
|
+
);
|
|
185
|
+
lines.push(
|
|
186
|
+
`| total | ${r.total_commits} | ${r.total_loc_added.toLocaleString()} | ${r.total_loc_removed.toLocaleString()} |`
|
|
187
|
+
);
|
|
188
|
+
if (r.by_iteration && Object.keys(r.by_iteration).length > 0) {
|
|
189
|
+
lines.push('');
|
|
190
|
+
lines.push('## By iteration');
|
|
191
|
+
lines.push('');
|
|
192
|
+
lines.push('| Iteration | Commits | LOC added |');
|
|
193
|
+
lines.push('|---:|---:|---:|');
|
|
194
|
+
const keys = Object.keys(r.by_iteration).sort((a, b) => parseInt(a, 10) - parseInt(b, 10));
|
|
195
|
+
for (const k of keys) {
|
|
196
|
+
const { commits, loc_added } = r.by_iteration[k];
|
|
197
|
+
lines.push(`| ${k} | ${commits} | ${loc_added.toLocaleString()} |`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
lines.push('');
|
|
201
|
+
lines.push(
|
|
202
|
+
'_Computed deterministically from git log. Evolve signature: commit subject starts with `feat(evolve` / `fix(evolve` etc., or body mentions `gd evolve` / `runInfiniteEvolve` / iteration markers._'
|
|
203
|
+
);
|
|
204
|
+
return lines.join('\n');
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function cmdSingularity(
|
|
208
|
+
cwd: string,
|
|
209
|
+
options: { since?: string | null; all?: boolean; byIteration?: boolean },
|
|
210
|
+
raw: boolean
|
|
211
|
+
): void {
|
|
212
|
+
void cwd;
|
|
213
|
+
if (!_runGit(['rev-parse', '--git-dir']).trim()) {
|
|
214
|
+
error('Not a git repository');
|
|
215
|
+
}
|
|
216
|
+
const window = _resolveWindow(options.since ?? null, options.all === true);
|
|
217
|
+
const commits = _parseCommits(window);
|
|
218
|
+
const report = _computeReport(window, commits, options.byIteration === true);
|
|
219
|
+
output(report, raw, _renderMarkdown(report));
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
module.exports = { cmdSingularity, _computeReport, _parseCommits };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/** GRD Commands/SlugTimestamp -- Slug generation and timestamp formatting utilities */
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
output,
|
|
8
|
+
error,
|
|
9
|
+
}: {
|
|
10
|
+
output: (result: unknown, raw: boolean, rawValue?: unknown) => never;
|
|
11
|
+
error: (message: string) => never;
|
|
12
|
+
} = require('../utils');
|
|
13
|
+
|
|
14
|
+
// ─── Slug Generation ─────────────────────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* CLI command: Generate a kebab-case slug from input text.
|
|
18
|
+
* @param text - Input text to convert to slug
|
|
19
|
+
* @param raw - Output raw slug string instead of JSON
|
|
20
|
+
*/
|
|
21
|
+
function cmdGenerateSlug(text: string, raw: boolean): void {
|
|
22
|
+
if (!text) {
|
|
23
|
+
error(
|
|
24
|
+
'text required for slug generation. Usage: generate-slug <text>. Provide a text string, e.g.: generate-slug "my phase name"'
|
|
25
|
+
);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let slug: string = text
|
|
30
|
+
.toLowerCase()
|
|
31
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
32
|
+
.replace(/^-+|-+$/g, '');
|
|
33
|
+
|
|
34
|
+
if (slug.length > 60) {
|
|
35
|
+
slug = slug.slice(0, 60).replace(/-+$/, '');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const result = { slug };
|
|
39
|
+
output(result, raw, slug);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ─── Timestamp Formatting ────────────────────────────────────────────────────
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* CLI command: Output the current timestamp in the specified format.
|
|
46
|
+
* @param format - Timestamp format: 'date' (YYYY-MM-DD), 'filename' (ISO without colons), or 'full' (ISO)
|
|
47
|
+
* @param raw - Output raw timestamp string instead of JSON
|
|
48
|
+
*/
|
|
49
|
+
function cmdCurrentTimestamp(format: string, raw: boolean): void {
|
|
50
|
+
const now = new Date();
|
|
51
|
+
let result: string;
|
|
52
|
+
|
|
53
|
+
switch (format) {
|
|
54
|
+
case 'date':
|
|
55
|
+
result = now.toISOString().split('T')[0];
|
|
56
|
+
break;
|
|
57
|
+
case 'filename':
|
|
58
|
+
result = now.toISOString().replace(/:/g, '-').replace(/\..+/, '');
|
|
59
|
+
break;
|
|
60
|
+
case 'full':
|
|
61
|
+
default:
|
|
62
|
+
result = now.toISOString();
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
output({ timestamp: result }, raw, result);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ─── Exports ─────────────────────────────────────────────────────────────────
|
|
70
|
+
|
|
71
|
+
module.exports = {
|
|
72
|
+
cmdGenerateSlug,
|
|
73
|
+
cmdCurrentTimestamp,
|
|
74
|
+
};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/** GRD Commands/Tail -- Live tail of autopilot.log with GRD-aware formatting */
|
|
4
|
+
|
|
5
|
+
const fs = require('fs') as typeof import('fs');
|
|
6
|
+
const path = require('path') as typeof import('path');
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
output,
|
|
10
|
+
}: {
|
|
11
|
+
output: (result: unknown, raw: boolean, rawValue?: unknown) => never;
|
|
12
|
+
} = require('../utils');
|
|
13
|
+
|
|
14
|
+
const POLL_INTERVAL_MS = 500;
|
|
15
|
+
const LOG_RELATIVE = path.join('.planning', 'autopilot', 'autopilot.log');
|
|
16
|
+
|
|
17
|
+
interface TailLine {
|
|
18
|
+
timestamp: string;
|
|
19
|
+
message: string;
|
|
20
|
+
type: 'phase_start' | 'plan_complete' | 'error' | 'info';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function _classifyLine(msg: string): TailLine['type'] {
|
|
24
|
+
const lower = msg.toLowerCase();
|
|
25
|
+
if (lower.includes('phase') && (lower.includes('start') || lower.includes('wave'))) return 'phase_start';
|
|
26
|
+
if (lower.includes('complete') || lower.includes('success') || lower.includes('done')) return 'plan_complete';
|
|
27
|
+
if (lower.includes('error') || lower.includes('fail') || lower.includes('abort')) return 'error';
|
|
28
|
+
return 'info';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function _parseLine(raw: string): TailLine | null {
|
|
32
|
+
const m = raw.match(/^\[([^\]]+)\]\s+(.*)/);
|
|
33
|
+
if (!m) return null;
|
|
34
|
+
const msg = m[2].trim();
|
|
35
|
+
return { timestamp: m[1], message: msg, type: _classifyLine(msg) };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function _formatLine(line: TailLine): string {
|
|
39
|
+
const prefix: Record<TailLine['type'], string> = {
|
|
40
|
+
phase_start: '== ',
|
|
41
|
+
plan_complete: '++ ',
|
|
42
|
+
error: '!! ',
|
|
43
|
+
info: ' ',
|
|
44
|
+
};
|
|
45
|
+
return `${line.timestamp.slice(11, 19)} ${prefix[line.type]}${line.message}`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface TailResult {
|
|
49
|
+
log_path: string;
|
|
50
|
+
lines_shown: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* CLI command: Follow autopilot.log in real-time with GRD-aware formatting.
|
|
55
|
+
* In non-follow mode, shows the last N lines.
|
|
56
|
+
*/
|
|
57
|
+
function cmdTail(cwd: string, phaseFilter: string | null, follow: boolean, raw: boolean): void {
|
|
58
|
+
const logPath = path.join(cwd, LOG_RELATIVE);
|
|
59
|
+
|
|
60
|
+
if (!fs.existsSync(logPath)) {
|
|
61
|
+
output(
|
|
62
|
+
{ log_path: path.relative(cwd, logPath), lines_shown: 0, note: 'Log file not found — no autopilot session running' },
|
|
63
|
+
raw,
|
|
64
|
+
'log not found'
|
|
65
|
+
);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const content = fs.readFileSync(logPath, 'utf-8') as string;
|
|
70
|
+
const allLines = content.split('\n').filter((l: string) => l.trim());
|
|
71
|
+
|
|
72
|
+
let lines = allLines.map(_parseLine).filter((l): l is TailLine => l !== null);
|
|
73
|
+
|
|
74
|
+
if (phaseFilter) {
|
|
75
|
+
lines = lines.filter((l) => l.message.includes(`phase ${phaseFilter}`) || l.message.includes(`Phase ${phaseFilter}`));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const lastN = follow ? lines : lines.slice(-50);
|
|
79
|
+
|
|
80
|
+
if (!follow) {
|
|
81
|
+
// Codex r1 P2: do not interleave human-formatted lines before the
|
|
82
|
+
// `output()` call — tool callers parsing JSON from stdout cannot
|
|
83
|
+
// skip the prefix. Pass the formatted block to `output()` so that
|
|
84
|
+
// `--raw` mode emits structured JSON only, and default mode emits
|
|
85
|
+
// the formatted lines via output's human-readable channel.
|
|
86
|
+
const formatted = lastN.map(_formatLine).join('\n');
|
|
87
|
+
const result: TailResult = { log_path: path.relative(cwd, logPath), lines_shown: lastN.length };
|
|
88
|
+
output(result, raw, formatted);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
for (const line of lastN) {
|
|
93
|
+
process.stdout.write(_formatLine(line) + '\n');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Follow mode: poll for new content
|
|
97
|
+
let fileSize = fs.statSync(logPath).size;
|
|
98
|
+
const watcher = setInterval(() => {
|
|
99
|
+
try {
|
|
100
|
+
const newSize = fs.statSync(logPath).size;
|
|
101
|
+
if (newSize <= fileSize) return;
|
|
102
|
+
|
|
103
|
+
const fd = fs.openSync(logPath, 'r');
|
|
104
|
+
const diff = newSize - fileSize;
|
|
105
|
+
const buf = Buffer.alloc(diff);
|
|
106
|
+
fs.readSync(fd, buf, 0, diff, fileSize);
|
|
107
|
+
fs.closeSync(fd);
|
|
108
|
+
fileSize = newSize;
|
|
109
|
+
|
|
110
|
+
const newContent = buf.toString('utf-8');
|
|
111
|
+
const newLines = newContent.split('\n').filter((l: string) => l.trim());
|
|
112
|
+
for (const rawLine of newLines) {
|
|
113
|
+
const parsed = _parseLine(rawLine);
|
|
114
|
+
if (!parsed) continue;
|
|
115
|
+
if (phaseFilter && !parsed.message.includes(`phase ${phaseFilter}`) && !parsed.message.includes(`Phase ${phaseFilter}`)) continue;
|
|
116
|
+
process.stdout.write(_formatLine(parsed) + '\n');
|
|
117
|
+
}
|
|
118
|
+
} catch {
|
|
119
|
+
// file may have been rotated
|
|
120
|
+
}
|
|
121
|
+
}, POLL_INTERVAL_MS);
|
|
122
|
+
|
|
123
|
+
process.on('SIGINT', () => {
|
|
124
|
+
clearInterval(watcher);
|
|
125
|
+
process.exit(0);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
module.exports = { cmdTail };
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/** GRD Commands/Todo -- Todo list management and completion operations */
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
const {
|
|
10
|
+
output,
|
|
11
|
+
error,
|
|
12
|
+
}: {
|
|
13
|
+
output: (result: unknown, raw: boolean, rawValue?: unknown) => never;
|
|
14
|
+
error: (message: string) => never;
|
|
15
|
+
} = require('../utils');
|
|
16
|
+
const {
|
|
17
|
+
todosDir: getTodosDirPath,
|
|
18
|
+
currentMilestone,
|
|
19
|
+
}: {
|
|
20
|
+
todosDir: (cwd: string) => string;
|
|
21
|
+
currentMilestone: (cwd: string) => string;
|
|
22
|
+
} = require('../paths');
|
|
23
|
+
|
|
24
|
+
// ─── Domain Types ────────────────────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
/** A single todo item parsed from the pending directory. */
|
|
27
|
+
interface TodoItem {
|
|
28
|
+
file: string;
|
|
29
|
+
created: string;
|
|
30
|
+
title: string;
|
|
31
|
+
area: string;
|
|
32
|
+
path: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Result of listing todos. */
|
|
36
|
+
interface TodoListResult {
|
|
37
|
+
count: number;
|
|
38
|
+
todos: TodoItem[];
|
|
39
|
+
milestone_version: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ─── List Todos ──────────────────────────────────────────────────────────────
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* CLI command: List pending todo files in .planning/todos/ with optional area filter.
|
|
46
|
+
* @param cwd - Project working directory
|
|
47
|
+
* @param area - Area filter (e.g., 'general'), or null for all todos
|
|
48
|
+
* @param raw - Output raw count string instead of JSON
|
|
49
|
+
*/
|
|
50
|
+
function cmdListTodos(cwd: string, area: string | null, raw: boolean): void {
|
|
51
|
+
const pendingDir: string = path.join(getTodosDirPath(cwd), 'pending');
|
|
52
|
+
|
|
53
|
+
let count = 0;
|
|
54
|
+
const todos: TodoItem[] = [];
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
const files: string[] = fs.readdirSync(pendingDir).filter((f: string) => f.endsWith('.md')).sort();
|
|
58
|
+
|
|
59
|
+
for (const file of files) {
|
|
60
|
+
try {
|
|
61
|
+
const content: string = fs.readFileSync(path.join(pendingDir, file), 'utf-8');
|
|
62
|
+
const createdMatch: RegExpMatchArray | null = content.match(/^created:\s*(.+)$/m);
|
|
63
|
+
const titleMatch: RegExpMatchArray | null = content.match(/^title:\s*(.+)$/m);
|
|
64
|
+
const areaMatch: RegExpMatchArray | null = content.match(/^area:\s*(.+)$/m);
|
|
65
|
+
|
|
66
|
+
const todoArea: string = areaMatch ? areaMatch[1].trim() : 'general';
|
|
67
|
+
|
|
68
|
+
// Apply area filter if specified
|
|
69
|
+
if (area && todoArea !== area) continue;
|
|
70
|
+
|
|
71
|
+
count++;
|
|
72
|
+
todos.push({
|
|
73
|
+
file,
|
|
74
|
+
created: createdMatch ? createdMatch[1].trim() : 'unknown',
|
|
75
|
+
title: titleMatch ? titleMatch[1].trim() : 'Untitled',
|
|
76
|
+
area: todoArea,
|
|
77
|
+
path: path.relative(cwd, path.join(pendingDir, file)),
|
|
78
|
+
});
|
|
79
|
+
} catch (readErr: unknown) {
|
|
80
|
+
const err = readErr as { code?: string; message?: string };
|
|
81
|
+
if (err && err.code && err.code !== 'ENOENT') {
|
|
82
|
+
process.stderr.write(`[todos] error reading ${file} (${err.code}): ${err.message}\n`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
} catch {
|
|
87
|
+
// Todos directory may not exist yet; proceed with empty list
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const milestoneVersion: string = currentMilestone(cwd);
|
|
91
|
+
const result: TodoListResult = { count, todos, milestone_version: milestoneVersion };
|
|
92
|
+
output(result, raw, count.toString());
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ─── Complete Todo ───────────────────────────────────────────────────────────
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* CLI command: Mark a todo file as completed by moving it from pending to completed directory.
|
|
99
|
+
* @param cwd - Project working directory
|
|
100
|
+
* @param filename - Name of the todo file to complete
|
|
101
|
+
* @param raw - Output raw 'completed' string instead of JSON
|
|
102
|
+
* @param dryRun - If true, preview changes without writing
|
|
103
|
+
*/
|
|
104
|
+
function cmdTodoComplete(cwd: string, filename: string, raw: boolean, dryRun?: boolean): void {
|
|
105
|
+
if (!filename) {
|
|
106
|
+
error(
|
|
107
|
+
'filename required for todo complete. Usage: todos complete <filename> (run "todos list" to see pending filenames)'
|
|
108
|
+
);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const pendingDir: string = path.join(getTodosDirPath(cwd), 'pending');
|
|
113
|
+
const completedDir: string = path.join(getTodosDirPath(cwd), 'completed');
|
|
114
|
+
const sourcePath: string = path.join(pendingDir, filename);
|
|
115
|
+
|
|
116
|
+
if (!fs.existsSync(sourcePath)) {
|
|
117
|
+
error(`Todo not found: ${filename}`);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const today: string = new Date().toISOString().split('T')[0];
|
|
122
|
+
|
|
123
|
+
if (dryRun) {
|
|
124
|
+
output(
|
|
125
|
+
{
|
|
126
|
+
dry_run: true,
|
|
127
|
+
would_complete: filename,
|
|
128
|
+
source: path.relative(cwd, sourcePath),
|
|
129
|
+
destination: path.relative(cwd, path.join(completedDir, filename)),
|
|
130
|
+
date: today,
|
|
131
|
+
},
|
|
132
|
+
raw,
|
|
133
|
+
`dry-run: would complete ${filename}`
|
|
134
|
+
);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Ensure completed directory exists
|
|
139
|
+
fs.mkdirSync(completedDir, { recursive: true });
|
|
140
|
+
|
|
141
|
+
const destPath = path.join(completedDir, filename);
|
|
142
|
+
|
|
143
|
+
const content: string = fs.readFileSync(sourcePath, 'utf-8');
|
|
144
|
+
// Write to dest first so source is untouched if the write fails
|
|
145
|
+
fs.writeFileSync(destPath, `completed: ${today}\n` + content, 'utf-8');
|
|
146
|
+
fs.unlinkSync(sourcePath);
|
|
147
|
+
|
|
148
|
+
output({ completed: true, file: filename, date: today }, raw, 'completed');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// ─── Rank Todos ──────────────────────────────────────────────────────────────
|
|
152
|
+
|
|
153
|
+
/** A scored todo item for ranked output. */
|
|
154
|
+
interface RankedTodo {
|
|
155
|
+
rank: number;
|
|
156
|
+
score: number;
|
|
157
|
+
file: string;
|
|
158
|
+
title: string;
|
|
159
|
+
area: string;
|
|
160
|
+
milestone: string;
|
|
161
|
+
signals: string[];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** High-value keyword signals (security, perf, user-facing score highest). */
|
|
165
|
+
// Codex r10 P3: needs the `g` flag so .match() returns ALL hits, not
|
|
166
|
+
// just the first. Without it, the unique-dedupe step is fed at most
|
|
167
|
+
// one keyword and multi-signal todos score too low.
|
|
168
|
+
const HIGH_VALUE_KEYWORDS = /\b(security|auth|perf|performance|user.facing|critical|export|import|diagnos|audit|rank|visual|bundle|research)\b/gi;
|
|
169
|
+
const MED_VALUE_KEYWORDS = /\b(test|fix|bug|error|fail|slow|memory|cache|refactor)\b/gi;
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* CLI command: Rank pending todos by keyword signal, title quality, and milestone age.
|
|
173
|
+
*
|
|
174
|
+
* Scans all .planning/milestones/{milestone}/todos/pending/ directories.
|
|
175
|
+
* Scores each todo by:
|
|
176
|
+
* - High-value keywords: +3 per match (security, perf, user-facing, etc.)
|
|
177
|
+
* - Medium-value keywords: +1 per match (fix, bug, error, etc.)
|
|
178
|
+
* - Title clarity (longer than 10 chars): +1
|
|
179
|
+
* - Problem/Solution sections present: +1 each
|
|
180
|
+
*
|
|
181
|
+
* @param cwd - Project working directory
|
|
182
|
+
* @param raw - Output raw text instead of JSON
|
|
183
|
+
* @param topN - How many results to return (default 20, 0 = all)
|
|
184
|
+
*/
|
|
185
|
+
function cmdTodosRank(cwd: string, raw: boolean, topN?: number): void {
|
|
186
|
+
const limit = topN !== undefined ? topN : 20;
|
|
187
|
+
const milestonesBase = path.join(cwd, '.planning', 'milestones');
|
|
188
|
+
const ranked: RankedTodo[] = [];
|
|
189
|
+
|
|
190
|
+
let msDirs: string[] = [];
|
|
191
|
+
try {
|
|
192
|
+
msDirs = (fs.readdirSync(milestonesBase) as string[]).filter((d) => {
|
|
193
|
+
try {
|
|
194
|
+
return fs.statSync(path.join(milestonesBase, d)).isDirectory();
|
|
195
|
+
} catch {
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
} catch {
|
|
200
|
+
// milestones dir doesn't exist
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
for (const ms of msDirs) {
|
|
204
|
+
const pendingDir = path.join(milestonesBase, ms, 'todos', 'pending');
|
|
205
|
+
let files: string[];
|
|
206
|
+
try {
|
|
207
|
+
files = (fs.readdirSync(pendingDir) as string[]).filter((f: string) => f.endsWith('.md'));
|
|
208
|
+
} catch {
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
for (const file of files) {
|
|
213
|
+
try {
|
|
214
|
+
const content: string = fs.readFileSync(path.join(pendingDir, file), 'utf-8');
|
|
215
|
+
const titleMatch = content.match(/^title:\s*(.+)$/m);
|
|
216
|
+
const areaMatch = content.match(/^area:\s*(.+)$/m);
|
|
217
|
+
const title = titleMatch ? titleMatch[1].trim() : file;
|
|
218
|
+
const area = areaMatch ? areaMatch[1].trim() : 'general';
|
|
219
|
+
|
|
220
|
+
const searchText = `${title} ${content}`;
|
|
221
|
+
const signals: string[] = [];
|
|
222
|
+
let score = 0;
|
|
223
|
+
|
|
224
|
+
// Keyword scoring
|
|
225
|
+
const highMatches = searchText.match(HIGH_VALUE_KEYWORDS);
|
|
226
|
+
if (highMatches) {
|
|
227
|
+
const unique = [...new Set(highMatches.map((m) => m.toLowerCase()))];
|
|
228
|
+
score += unique.length * 3;
|
|
229
|
+
signals.push(...unique.map((k) => `+3 (${k})`));
|
|
230
|
+
}
|
|
231
|
+
const medMatches = searchText.match(MED_VALUE_KEYWORDS);
|
|
232
|
+
if (medMatches) {
|
|
233
|
+
const unique = [...new Set(medMatches.map((m) => m.toLowerCase()))];
|
|
234
|
+
score += unique.length;
|
|
235
|
+
signals.push(...unique.map((k) => `+1 (${k})`));
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Title clarity
|
|
239
|
+
if (title.length > 10) { score += 1; signals.push('+1 (clear title)'); }
|
|
240
|
+
|
|
241
|
+
// Sections present
|
|
242
|
+
if (/^##\s+Problem/m.test(content)) { score += 1; signals.push('+1 (has Problem)'); }
|
|
243
|
+
if (/^##\s+Solution/m.test(content)) { score += 1; signals.push('+1 (has Solution)'); }
|
|
244
|
+
|
|
245
|
+
ranked.push({ rank: 0, score, file, title, area, milestone: ms, signals });
|
|
246
|
+
} catch {
|
|
247
|
+
// skip unreadable files
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Sort descending by score
|
|
253
|
+
ranked.sort((a, b) => b.score - a.score || a.title.localeCompare(b.title));
|
|
254
|
+
|
|
255
|
+
const results = (limit > 0 ? ranked.slice(0, limit) : ranked).map((t, i) => ({
|
|
256
|
+
...t,
|
|
257
|
+
rank: i + 1,
|
|
258
|
+
}));
|
|
259
|
+
|
|
260
|
+
output(
|
|
261
|
+
{ total_scanned: ranked.length, returned: results.length, todos: results },
|
|
262
|
+
raw,
|
|
263
|
+
`${results.length} of ${ranked.length} todos ranked`
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// ─── Exports ─────────────────────────────────────────────────────────────────
|
|
268
|
+
|
|
269
|
+
module.exports = {
|
|
270
|
+
cmdListTodos,
|
|
271
|
+
cmdTodoComplete,
|
|
272
|
+
cmdTodosRank,
|
|
273
|
+
};
|