@event4u/agent-config 14.22.0 → 15.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +333 -356
- package/README.md +1 -1
- package/dist/agent-src/commands/agent-handoff.md +8 -7
- package/dist/agent-src/commands/agents/init.md +1 -1
- package/dist/agent-src/commands/agents/user/accept.md +4 -4
- package/dist/agent-src/commands/agents/user/delete.md +2 -2
- package/dist/agent-src/commands/agents/user/init.md +3 -3
- package/dist/agent-src/commands/agents/user/review.md +3 -3
- package/dist/agent-src/commands/agents/user/show.md +3 -3
- package/dist/agent-src/commands/agents/user/update.md +2 -2
- package/dist/agent-src/commands/agents/user.md +6 -6
- package/dist/agent-src/commands/analytics/prune.md +1 -1
- package/dist/agent-src/commands/analytics/show.md +2 -2
- package/dist/agent-src/commands/analyze/decision.md +2 -2
- package/dist/agent-src/commands/analyze/inbox.md +5 -5
- package/dist/agent-src/commands/analyze/incident.md +3 -3
- package/dist/agent-src/commands/analyze/near-miss.md +3 -3
- package/dist/agent-src/commands/analyze/postmortem.md +4 -4
- package/dist/agent-src/commands/analyze/premortem.md +2 -2
- package/dist/agent-src/commands/analyze.md +2 -2
- package/dist/agent-src/commands/bug/fix.md +1 -1
- package/dist/agent-src/commands/bug/investigate.md +2 -2
- package/dist/agent-src/commands/cost/profile.md +3 -3
- package/dist/agent-src/commands/design.md +1 -1
- package/dist/agent-src/commands/feature/explore.md +1 -1
- package/dist/agent-src/commands/feature/plan.md +2 -2
- package/dist/agent-src/commands/feature/roadmap.md +2 -2
- package/dist/agent-src/commands/ghostwriter/fetch.md +4 -4
- package/dist/agent-src/commands/ghostwriter/list.md +1 -1
- package/dist/agent-src/commands/ghostwriter/show.md +1 -1
- package/dist/agent-src/commands/ghostwriter/write.md +9 -9
- package/dist/agent-src/commands/humanize.md +6 -6
- package/dist/agent-src/commands/jira-ticket.md +1 -1
- package/dist/agent-src/commands/judge/solo.md +1 -1
- package/dist/agent-src/commands/judge.md +1 -1
- package/dist/agent-src/commands/knowledge/cross-repo.md +1 -1
- package/dist/agent-src/commands/knowledge/forget.md +1 -1
- package/dist/agent-src/commands/knowledge/ingest.md +2 -2
- package/dist/agent-src/commands/knowledge/list.md +1 -1
- package/dist/agent-src/commands/memory/add.md +3 -3
- package/dist/agent-src/commands/memory/load.md +4 -4
- package/dist/agent-src/commands/memory/mine-session.md +1 -1
- package/dist/agent-src/commands/memory/promote.md +4 -4
- package/dist/agent-src/commands/memory/propose.md +2 -2
- package/dist/agent-src/commands/mode.md +5 -5
- package/dist/agent-src/commands/post-as/ghostwriter.md +3 -3
- package/dist/agent-src/commands/post-as/me.md +7 -7
- package/dist/agent-src/commands/pr/create.md +1 -1
- package/dist/agent-src/commands/pr/merge.md +48 -39
- package/dist/agent-src/commands/profile/activate.md +1 -1
- package/dist/agent-src/commands/profile/show.md +1 -1
- package/dist/agent-src/commands/research/deep.md +2 -2
- package/dist/agent-src/commands/research/report.md +2 -2
- package/dist/agent-src/commands/review/changes.md +1 -1
- package/dist/agent-src/commands/review/routing.md +1 -1
- package/dist/agent-src/commands/roadmap/create.md +1 -1
- package/dist/agent-src/commands/roadmap/materialize.md +2 -2
- package/dist/agent-src/commands/roadmap/next.md +9 -1
- package/dist/agent-src/commands/roadmap/process-full.md +2 -2
- package/dist/agent-src/commands/security-audit-config.md +3 -3
- package/dist/agent-src/commands/skill/preview.md +1 -1
- package/dist/agent-src/commands/skills/discover.md +1 -1
- package/dist/agent-src/commands/sync/agent-settings.md +2 -2
- package/dist/agent-src/commands/sync/gitignore/fix.md +1 -1
- package/dist/agent-src/commands/tests/create.md +1 -1
- package/dist/agent-src/commands/tests/e2e-heal.md +1 -1
- package/dist/agent-src/commands/tests/e2e-plan.md +1 -1
- package/dist/agent-src/contexts/authority/kernel-rule-edits.md +6 -6
- package/dist/agent-src/contexts/communication/rules-auto/slash-command-routing-policy-mechanics.md +1 -2
- package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +2 -2
- package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +88 -1
- package/dist/agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +1 -1
- package/dist/agent-src/contexts/contracts/frugality-charter.md +1 -1
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +1 -1
- package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +1 -1
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +13 -1
- package/dist/agent-src/contexts/execution/cheap-question-mechanics.md +1 -1
- package/dist/agent-src/contexts/execution/contract-decision-sheet.md +3 -3
- package/dist/agent-src/contexts/execution/mandated-lines.md +1 -1
- package/dist/agent-src/contexts/execution/non-interactive-contract.md +1 -1
- package/dist/agent-src/contexts/execution/orchestration-telemetry.md +1 -1
- package/dist/agent-src/contexts/execution/plan-confidence-gate.md +5 -5
- package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +1 -1
- package/dist/agent-src/contexts/execution/subagent-modes-detail.md +1 -1
- package/dist/agent-src/contexts/execution/subagent-routing.md +2 -2
- package/dist/agent-src/contexts/execution/subagent-spawn-contract.md +1 -1
- package/dist/agent-src/contexts/execution/user-memory-channels.md +3 -3
- package/dist/agent-src/contexts/execution/verification-mechanics.md +1 -1
- package/dist/agent-src/contexts/judges/persona-voice-rubric.md +2 -2
- package/dist/agent-src/guidelines/abstraction-thresholds.md +88 -0
- package/dist/agent-src/guidelines/agent-infra/5w2h-analysis.md +260 -0
- package/dist/agent-src/guidelines/agent-infra/active-remediation-mechanics.md +99 -0
- package/dist/agent-src/guidelines/agent-infra/agent-interaction-and-decision-quality.md +325 -0
- package/dist/agent-src/guidelines/agent-infra/api-cost-levers.md +177 -0
- package/dist/agent-src/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +222 -0
- package/dist/agent-src/guidelines/agent-infra/ask-when-uncertain-demos.md +134 -0
- package/dist/agent-src/guidelines/agent-infra/asking-and-brevity-examples.md +198 -0
- package/dist/agent-src/guidelines/agent-infra/break-glass-usage.md +113 -0
- package/dist/agent-src/guidelines/agent-infra/carve-out-predicates.md +17 -0
- package/dist/agent-src/guidelines/agent-infra/comparison-matrix.md +179 -0
- package/dist/agent-src/guidelines/agent-infra/context-hygiene-mechanics.md +165 -0
- package/dist/agent-src/guidelines/agent-infra/corpus-grounding-authoring.md +91 -0
- package/dist/agent-src/guidelines/agent-infra/critical-thinking.md +156 -0
- package/dist/agent-src/guidelines/agent-infra/cross-source-consistency-mechanics.md +109 -0
- package/dist/agent-src/guidelines/agent-infra/developer-judgment.md +82 -0
- package/dist/agent-src/guidelines/agent-infra/direct-answers-demos.md +142 -0
- package/dist/agent-src/guidelines/agent-infra/domain-adoption-gates.md +112 -0
- package/dist/agent-src/guidelines/agent-infra/domain-eval-anti-pattern.md +53 -0
- package/dist/agent-src/guidelines/agent-infra/domain-pack-architecture.md +56 -0
- package/dist/agent-src/guidelines/agent-infra/downstream-changes-mechanics.md +91 -0
- package/dist/agent-src/guidelines/agent-infra/emphasis-budget.md +45 -0
- package/dist/agent-src/guidelines/agent-infra/engineering-memory-data-format.md +210 -0
- package/dist/agent-src/guidelines/agent-infra/evaluator-independence-mechanics.md +92 -0
- package/dist/agent-src/guidelines/agent-infra/existence-question-verdicts.md +80 -0
- package/dist/agent-src/guidelines/agent-infra/failure-signatures.md +70 -0
- package/dist/agent-src/guidelines/agent-infra/false-green.md +233 -0
- package/dist/agent-src/guidelines/agent-infra/first-principles.md +192 -0
- package/dist/agent-src/guidelines/agent-infra/framework-neutrality-patterns.md +66 -0
- package/dist/agent-src/guidelines/agent-infra/frontier-reasoning-operating-profile.md +169 -0
- package/dist/agent-src/guidelines/agent-infra/gate-authoring.md +177 -0
- package/dist/agent-src/guidelines/agent-infra/guarded-baseline.md +39 -0
- package/dist/agent-src/guidelines/agent-infra/installed-tools-manifest.md +142 -0
- package/dist/agent-src/guidelines/agent-infra/inversion-thinking.md +388 -0
- package/dist/agent-src/guidelines/agent-infra/ios-simulator-guide.md +378 -0
- package/dist/agent-src/guidelines/agent-infra/language-and-tone-examples.md +141 -0
- package/dist/agent-src/guidelines/agent-infra/layered-settings.md +317 -0
- package/dist/agent-src/guidelines/agent-infra/linked-projects-onboarding-gate.md +80 -0
- package/dist/agent-src/guidelines/agent-infra/mcp-request-signing.md +197 -0
- package/dist/agent-src/guidelines/agent-infra/memory-access.md +149 -0
- package/dist/agent-src/guidelines/agent-infra/mental-models.md +314 -0
- package/dist/agent-src/guidelines/agent-infra/minimal-safe-diff-mechanics.md +241 -0
- package/dist/agent-src/guidelines/agent-infra/missing-tool-handling.md +66 -0
- package/dist/agent-src/guidelines/agent-infra/model-recommendation.md +101 -0
- package/dist/agent-src/guidelines/agent-infra/naming.md +69 -0
- package/dist/agent-src/guidelines/agent-infra/notes-horizon-mechanics.md +90 -0
- package/dist/agent-src/guidelines/agent-infra/output-patterns.md +117 -0
- package/dist/agent-src/guidelines/agent-infra/recurring-criticism-mechanics.md +96 -0
- package/dist/agent-src/guidelines/agent-infra/reuse-verdict-mechanics.md +71 -0
- package/dist/agent-src/guidelines/agent-infra/review-routing-data-format.md +143 -0
- package/dist/agent-src/guidelines/agent-infra/roadmap-deferred-resolution-provenance.md +54 -0
- package/dist/agent-src/guidelines/agent-infra/roadmap-progress-mechanics.md +274 -0
- package/dist/agent-src/guidelines/agent-infra/role-contracts.md +209 -0
- package/dist/agent-src/guidelines/agent-infra/role-mode-router.md +89 -0
- package/dist/agent-src/guidelines/agent-infra/rule-body-migration-inventory.md +241 -0
- package/dist/agent-src/guidelines/agent-infra/rule-type-governance.md +73 -0
- package/dist/agent-src/guidelines/agent-infra/runtime-layer.md +89 -0
- package/dist/agent-src/guidelines/agent-infra/scqa-framework.md +526 -0
- package/dist/agent-src/guidelines/agent-infra/security-lint-containment.md +121 -0
- package/dist/agent-src/guidelines/agent-infra/self-improvement-pipeline.md +134 -0
- package/dist/agent-src/guidelines/agent-infra/simplicity-and-goal-demos.md +211 -0
- package/dist/agent-src/guidelines/agent-infra/six-hats.md +353 -0
- package/dist/agent-src/guidelines/agent-infra/size-and-scope.md +229 -0
- package/dist/agent-src/guidelines/agent-infra/skill-quality-checklist.md +157 -0
- package/dist/agent-src/guidelines/agent-infra/source-confidentiality-mechanics.md +109 -0
- package/dist/agent-src/guidelines/agent-infra/symptom-driven-harvest-loop.md +104 -0
- package/dist/agent-src/guidelines/agent-infra/systems-thinking.md +220 -0
- package/dist/agent-src/guidelines/agent-infra/tool-description-as-policy.md +35 -0
- package/dist/agent-src/guidelines/agent-infra/tool-integration.md +73 -0
- package/dist/agent-src/guidelines/agent-infra/traceability-field-mechanics.md +50 -0
- package/dist/agent-src/guidelines/agent-infra/untrusted-input-spotlighting.md +166 -0
- package/dist/agent-src/guidelines/agent-infra/verify-before-complete-demos.md +128 -0
- package/dist/agent-src/guidelines/augment-portability-patterns.md +70 -0
- package/dist/agent-src/guidelines/code-clarity.md +350 -0
- package/dist/agent-src/guidelines/component-oriented-and-oop-development.md +189 -0
- package/dist/agent-src/guidelines/cross-role-handoff.md +127 -0
- package/dist/agent-src/guidelines/design-antipatterns-triggers.json +18 -0
- package/dist/agent-src/guidelines/design-antipatterns.md +327 -0
- package/dist/agent-src/guidelines/design-asset-discipline.md +38 -0
- package/dist/agent-src/guidelines/design-canon.md +63 -0
- package/dist/agent-src/guidelines/design-fidelity-mechanics.md +293 -0
- package/dist/agent-src/guidelines/design-fidelity-routing.md +78 -0
- package/dist/agent-src/guidelines/design-handover-extraction.md +117 -0
- package/dist/agent-src/guidelines/design-modes.md +143 -0
- package/dist/agent-src/guidelines/design-reconciliation.md +172 -0
- package/dist/agent-src/guidelines/docs/readme-size-and-splitting.md +209 -0
- package/dist/agent-src/guidelines/e2e/playwright.md +363 -0
- package/dist/agent-src/guidelines/gtm-handoff.md +114 -0
- package/dist/agent-src/guidelines/monorepo-antipatterns.md +141 -0
- package/dist/agent-src/guidelines/php/api-design.md +115 -0
- package/dist/agent-src/guidelines/php/artisan-commands.md +81 -0
- package/dist/agent-src/guidelines/php/blade-ui.md +78 -0
- package/dist/agent-src/guidelines/php/controllers.md +90 -0
- package/dist/agent-src/guidelines/php/database.md +194 -0
- package/dist/agent-src/guidelines/php/eloquent.md +208 -0
- package/dist/agent-src/guidelines/php/flux.md +80 -0
- package/dist/agent-src/guidelines/php/general.md +207 -0
- package/dist/agent-src/guidelines/php/git.md +164 -0
- package/dist/agent-src/guidelines/php/jobs.md +111 -0
- package/dist/agent-src/guidelines/php/livewire.md +71 -0
- package/dist/agent-src/guidelines/php/logging.md +79 -0
- package/dist/agent-src/guidelines/php/naming.md +89 -0
- package/dist/agent-src/guidelines/php/patterns/dependency-injection.md +57 -0
- package/dist/agent-src/guidelines/php/patterns/dtos.md +199 -0
- package/dist/agent-src/guidelines/php/patterns/events.md +67 -0
- package/dist/agent-src/guidelines/php/patterns/factory.md +53 -0
- package/dist/agent-src/guidelines/php/patterns/pipelines.md +66 -0
- package/dist/agent-src/guidelines/php/patterns/policies.md +66 -0
- package/dist/agent-src/guidelines/php/patterns/repositories.md +122 -0
- package/dist/agent-src/guidelines/php/patterns/service-layer.md +64 -0
- package/dist/agent-src/guidelines/php/patterns/strategy.md +247 -0
- package/dist/agent-src/guidelines/php/patterns.md +28 -0
- package/dist/agent-src/guidelines/php/performance.md +92 -0
- package/dist/agent-src/guidelines/php/php-coding-patterns.md +80 -0
- package/dist/agent-src/guidelines/php/resources.md +100 -0
- package/dist/agent-src/guidelines/php/security.md +110 -0
- package/dist/agent-src/guidelines/php/sql.md +97 -0
- package/dist/agent-src/guidelines/php/validations.md +119 -0
- package/dist/agent-src/guidelines/php/websocket.md +100 -0
- package/dist/agent-src/guidelines/prompt-templates.md +189 -0
- package/dist/agent-src/guidelines/redundancy-taxonomy.md +208 -0
- package/dist/agent-src/guidelines/wing4-handoff.md +127 -0
- package/dist/agent-src/personas/README.md +1 -1
- package/dist/agent-src/personas/_template-specialist/persona.md +1 -1
- package/dist/agent-src/personas/product-owner.md +1 -1
- package/dist/agent-src/rules/active-remediation.md +1 -1
- package/dist/agent-src/rules/architecture.md +2 -2
- package/dist/agent-src/rules/artifact-drafting-protocol.md +1 -1
- package/dist/agent-src/rules/ask-when-uncertain.md +2 -2
- package/dist/agent-src/rules/brand-source-of-truth.md +9 -7
- package/dist/agent-src/rules/code-comment-discipline.md +2 -2
- package/dist/agent-src/rules/code-provenance.md +1 -1
- package/dist/agent-src/rules/content-quoting-floor.md +1 -1
- package/dist/agent-src/rules/context-hygiene.md +5 -5
- package/dist/agent-src/rules/cross-source-consistency.md +1 -1
- package/dist/agent-src/rules/design-fidelity.md +36 -46
- package/dist/agent-src/rules/direct-answers.md +2 -2
- package/dist/agent-src/rules/domain-adoption-policy.md +1 -1
- package/dist/agent-src/rules/evaluator-independence.md +1 -1
- package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +1 -1
- package/dist/agent-src/rules/icon-consistency.md +5 -1
- package/dist/agent-src/rules/improve-before-implement.md +1 -1
- package/dist/agent-src/rules/language-and-tone.md +3 -3
- package/dist/agent-src/rules/minimal-safe-diff.md +1 -1
- package/dist/agent-src/rules/notes-first-reasoning.md +36 -25
- package/dist/agent-src/rules/recurring-criticism.md +1 -1
- package/dist/agent-src/rules/roadmap-progress-sync.md +1 -1
- package/dist/agent-src/rules/role-mode-adherence.md +2 -2
- package/dist/agent-src/rules/security-sensitive-stop.md +1 -1
- package/dist/agent-src/rules/size-enforcement.md +1 -1
- package/dist/agent-src/rules/source-confidentiality.md +2 -2
- package/dist/agent-src/rules/think-before-action.md +1 -1
- package/dist/agent-src/rules/token-efficiency.md +7 -5
- package/dist/agent-src/rules/ui-audit-gate.md +3 -2
- package/dist/agent-src/rules/untrusted-input-defense.md +3 -3
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +106 -4
- package/dist/agent-src/skills/activation-design/SKILL.md +2 -2
- package/dist/agent-src/skills/adr-create/SKILL.md +5 -5
- package/dist/agent-src/skills/ai-council/SKILL.md +1 -1
- package/dist/agent-src/skills/ai-council/references/advanced-modes.md +1 -1
- package/dist/agent-src/skills/blade-ui/SKILL.md +1 -1
- package/dist/agent-src/skills/blast-radius-analyzer/SKILL.md +1 -1
- package/dist/agent-src/skills/brand-to-tokens/SKILL.md +24 -3
- package/dist/agent-src/skills/bug-analyzer/SKILL.md +1 -1
- package/dist/agent-src/skills/build-buy-partner/SKILL.md +1 -1
- package/dist/agent-src/skills/churn-prevention/SKILL.md +2 -2
- package/dist/agent-src/skills/code-intelligence/SKILL.md +57 -1
- package/dist/agent-src/skills/code-refactoring/SKILL.md +3 -3
- package/dist/agent-src/skills/code-review/SKILL.md +3 -3
- package/dist/agent-src/skills/command-writing/SKILL.md +3 -3
- package/dist/agent-src/skills/comp-banding/SKILL.md +1 -1
- package/dist/agent-src/skills/competitive-moat-analysis/SKILL.md +1 -1
- package/dist/agent-src/skills/competitive-positioning/SKILL.md +2 -2
- package/dist/agent-src/skills/complexity-first-planning/SKILL.md +1 -1
- package/dist/agent-src/skills/condense-memory/SKILL.md +1 -1
- package/dist/agent-src/skills/content-funnel-design/SKILL.md +2 -2
- package/dist/agent-src/skills/contracts-cognition/SKILL.md +1 -1
- package/dist/agent-src/skills/copilot-agents-optimization/SKILL.md +2 -2
- package/dist/agent-src/skills/corpus-grounding/SKILL.md +2 -2
- package/dist/agent-src/skills/customer-research/SKILL.md +2 -2
- package/dist/agent-src/skills/dashboard-design/SKILL.md +1 -1
- package/dist/agent-src/skills/data-handling-judgment/SKILL.md +1 -1
- package/dist/agent-src/skills/deal-qualification-meddic/SKILL.md +2 -2
- package/dist/agent-src/skills/decision-record/SKILL.md +3 -3
- package/dist/agent-src/skills/decision-review/SKILL.md +8 -8
- package/dist/agent-src/skills/deep-reading-analyst/SKILL.md +22 -22
- package/dist/agent-src/skills/design-intelligence/SKILL.md +4 -4
- package/dist/agent-src/skills/design-intelligence/references/context-and-registers.md +2 -2
- package/dist/agent-src/skills/design-review/SKILL.md +4 -4
- package/dist/agent-src/skills/design-system-capture/references/design-system-json.md +20 -1
- package/dist/agent-src/skills/design-tokens/SKILL.md +17 -2
- package/dist/agent-src/skills/design-variations/SKILL.md +2 -2
- package/dist/agent-src/skills/developer-like-execution/SKILL.md +2 -2
- package/dist/agent-src/skills/discovery-interview/SKILL.md +2 -2
- package/dist/agent-src/skills/doc-coauthoring/SKILL.md +3 -3
- package/dist/agent-src/skills/editorial-calendar/SKILL.md +2 -2
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +44 -1
- package/dist/agent-src/skills/existing-ui-audit/references/anti-slop-cross-reference.md +2 -2
- package/dist/agent-src/skills/expansion-playbook/SKILL.md +2 -2
- package/dist/agent-src/skills/experiment-loop/SKILL.md +1 -1
- package/dist/agent-src/skills/experiment-loop/references/protocol.md +1 -1
- package/dist/agent-src/skills/fe-design/SKILL.md +3 -3
- package/dist/agent-src/skills/fe-design/references/design-patterns.md +1 -1
- package/dist/agent-src/skills/fe-design/references/design-read-and-memory.md +3 -3
- package/dist/agent-src/skills/fe-design/references/source-led-port.md +1 -1
- package/dist/agent-src/skills/feature-planning/SKILL.md +1 -1
- package/dist/agent-src/skills/flux/SKILL.md +1 -1
- package/dist/agent-src/skills/forecast-accuracy/SKILL.md +2 -2
- package/dist/agent-src/skills/forecasting/SKILL.md +2 -2
- package/dist/agent-src/skills/fundraising-narrative/SKILL.md +2 -2
- package/dist/agent-src/skills/funnel-analysis/SKILL.md +2 -2
- package/dist/agent-src/skills/git-workflow/references/push-closes-its-loop.md +9 -0
- package/dist/agent-src/skills/gtm-launch/SKILL.md +2 -2
- package/dist/agent-src/skills/hiring-loop-design/SKILL.md +1 -1
- package/dist/agent-src/skills/html-deck/SKILL.md +5 -5
- package/dist/agent-src/skills/humanizer/SKILL.md +1 -1
- package/dist/agent-src/skills/humanizer/data/patterns.md +1 -1
- package/dist/agent-src/skills/iconography/SKILL.md +3 -3
- package/dist/agent-src/skills/judge-synthesis/SKILL.md +1 -1
- package/dist/agent-src/skills/laravel-api-endpoint/SKILL.md +2 -2
- package/dist/agent-src/skills/launch-readiness/SKILL.md +3 -3
- package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +6 -6
- package/dist/agent-src/skills/livewire/SKILL.md +1 -1
- package/dist/agent-src/skills/market-entry-analysis/SKILL.md +1 -1
- package/dist/agent-src/skills/mcp-builder/SKILL.md +1 -1
- package/dist/agent-src/skills/memory-consolidation/SKILL.md +3 -3
- package/dist/agent-src/skills/messaging-architecture/SKILL.md +2 -2
- package/dist/agent-src/skills/monorepo-workspace/SKILL.md +1 -1
- package/dist/agent-src/skills/onboarding-design/SKILL.md +2 -2
- package/dist/agent-src/skills/onboarding-program/SKILL.md +1 -1
- package/dist/agent-src/skills/one-on-one-cadence/SKILL.md +1 -1
- package/dist/agent-src/skills/org-design/SKILL.md +1 -1
- package/dist/agent-src/skills/overbuild-review-lens/SKILL.md +3 -3
- package/dist/agent-src/skills/override-management/SKILL.md +1 -1
- package/dist/agent-src/skills/perf-feedback-craft/SKILL.md +1 -1
- package/dist/agent-src/skills/persona-writing/SKILL.md +1 -1
- package/dist/agent-src/skills/php-coder/SKILL.md +1 -1
- package/dist/agent-src/skills/pipeline-strategy/SKILL.md +2 -2
- package/dist/agent-src/skills/playwright-testing/SKILL.md +3 -3
- package/dist/agent-src/skills/po-discovery/SKILL.md +1 -1
- package/dist/agent-src/skills/positioning-strategy/SKILL.md +2 -2
- package/dist/agent-src/skills/privacy-review/SKILL.md +1 -1
- package/dist/agent-src/skills/prompt-optimizer/SKILL.md +3 -3
- package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
- package/dist/agent-src/skills/reasoning-orchestrator/SKILL.md +2 -2
- package/dist/agent-src/skills/receiving-code-review/SKILL.md +1 -1
- package/dist/agent-src/skills/refine-ticket/SKILL.md +2 -2
- package/dist/agent-src/skills/release-comms/SKILL.md +2 -2
- package/dist/agent-src/skills/retention-loops/SKILL.md +2 -2
- package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
- package/dist/agent-src/skills/roadmap-management/SKILL.md +1 -1
- package/dist/agent-src/skills/roadmap-management/references/archival.md +1 -1
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +5 -5
- package/dist/agent-src/skills/rule-writing/SKILL.md +6 -6
- package/dist/agent-src/skills/runway-cognition/SKILL.md +2 -2
- package/dist/agent-src/skills/scenario-modeling/SKILL.md +2 -2
- package/dist/agent-src/skills/skill-writing/SKILL.md +2 -2
- package/dist/agent-src/skills/skill-writing/references/procedure.md +1 -1
- package/dist/agent-src/skills/skill-writing/references/section-patterns.md +3 -3
- package/dist/agent-src/skills/spreadsheet-authoring/SKILL.md +1 -1
- package/dist/agent-src/skills/stakeholder-tradeoff/SKILL.md +3 -3
- package/dist/agent-src/skills/subagent-orchestration/SKILL.md +1 -1
- package/dist/agent-src/skills/supply-chain-intake/SKILL.md +1 -1
- package/dist/agent-src/skills/systematic-debugging/SKILL.md +2 -2
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +60 -4
- package/dist/agent-src/skills/throughput-vs-morale-tradeoff/SKILL.md +1 -1
- package/dist/agent-src/skills/token-optimizer/SKILL.md +1 -1
- package/dist/agent-src/skills/typography-system/SKILL.md +2 -2
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +28 -8
- package/dist/agent-src/skills/unit-economics-modeling/SKILL.md +2 -2
- package/dist/agent-src/skills/upstream-contribute/SKILL.md +1 -1
- package/dist/agent-src/skills/validate-feature-fit/SKILL.md +2 -2
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +2 -2
- package/dist/agent-src/skills/vision-articulation/SKILL.md +1 -1
- package/dist/agent-src/skills/voc-extract/SKILL.md +2 -2
- package/dist/agent-src/skills/voice-and-tone-design/SKILL.md +2 -2
- package/dist/agent-src/skills/wireframe/SKILL.md +1 -1
- package/dist/agent-src/skills/workspace-link/SKILL.md +1 -1
- package/dist/agent-src/templates/agent-settings.md +6 -6
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/contexts/knowledge-pages.md +2 -3
- package/dist/agent-src/templates/copilot-instructions.md +1 -1
- package/dist/agent-src/templates/roadmaps.md +1 -1
- package/dist/agent-src/templates/scripts/README.md +2 -2
- package/dist/agent-src/user-types/_template/user-type.md +1 -1
- package/dist/cli/registry.js +1 -1
- package/dist/cli-delegate/archive_completed_roadmaps.js +52 -4
- package/dist/cli-delegate/check_update_banner.js +12 -1
- package/dist/cli-delegate/{chunk-TGIPZBCW.js → chunk-2KKXJW25.js} +22 -8
- package/dist/cli-delegate/{chunk-NLP54U3J.js → chunk-2XY7ILBT.js} +13 -1
- package/dist/cli-delegate/{chunk-4FS4WRXP.js → chunk-3FKR64R5.js} +34 -6
- package/dist/cli-delegate/{chunk-J3RFNKG4.js → chunk-55ACLDUE.js} +2 -2
- package/dist/cli-delegate/{chunk-PKOBQADP.js → chunk-57PN4GYJ.js} +1 -1
- package/dist/cli-delegate/{chunk-BIXEDQPZ.js → chunk-AK6HODNQ.js} +4 -4
- package/dist/cli-delegate/{chunk-2FTMENJL.js → chunk-GYC3VRYN.js} +1 -1
- package/dist/cli-delegate/{chunk-LWTYTX6F.js → chunk-HZ52BRGG.js} +24 -18
- package/dist/cli-delegate/{chunk-6RJA2F5A.js → chunk-IVBPRCQO.js} +1 -1
- package/dist/cli-delegate/{chunk-I6RHFQEG.js → chunk-YUM5KURG.js} +17 -1
- package/dist/cli-delegate/cmd_analyze_session.js +1 -1
- package/dist/cli-delegate/cmd_brand_status.js +1 -1
- package/dist/cli-delegate/cmd_conformance.js +3 -3
- package/dist/cli-delegate/cmd_doctor.js +3 -3
- package/dist/cli-delegate/cmd_explain.js +2 -2
- package/dist/cli-delegate/cmd_export.js +4 -4
- package/dist/cli-delegate/cmd_handoff.js +24 -16
- package/dist/cli-delegate/cmd_mcp_available.js +1 -1
- package/dist/cli-delegate/cmd_memory_get.js +1 -1
- package/dist/cli-delegate/cmd_migrate.js +2 -2
- package/dist/cli-delegate/cmd_packs_active.js +2 -2
- package/dist/cli-delegate/cmd_prune.js +4 -4
- package/dist/cli-delegate/cmd_route_audit.js +3 -3
- package/dist/cli-delegate/cmd_route_explain.js +1 -1
- package/dist/cli-delegate/cmd_session_recycle.js +4 -14
- package/dist/cli-delegate/cmd_settings_get.js +15 -9
- package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
- package/dist/cli-delegate/cmd_settings_set.js +41 -11
- package/dist/cli-delegate/cmd_sync.js +4 -4
- package/dist/cli-delegate/cmd_uninstall.js +4 -4
- package/dist/cli-delegate/cmd_update.js +1 -1
- package/dist/cli-delegate/cmd_upgrade.js +1 -1
- package/dist/cli-delegate/cmd_validate.js +4 -4
- package/dist/cli-delegate/cmd_versions.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +27 -80
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +5 -7
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +4 -6
- package/dist/hooks/dispatch.js +9249 -8981
- package/dist/install/install.mjs +47 -8
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +5496 -2400
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_settings.js +73 -0
- package/dist/scripts/_lib/agent_src.js +20 -0
- package/dist/scripts/_lib/guidelines_lane.js +158 -0
- package/dist/scripts/_lib/lean_projection_mode.js +108 -0
- package/dist/scripts/_lib/router_match.js +243 -0
- package/dist/scripts/_lib/rule_injection.js +216 -0
- package/dist/scripts/condense.js +22 -25
- package/dist/scripts/project_thin_rules.js +139 -19
- package/dist/server/io/yamlIO.js +125 -17
- package/dist/server/schemas/settings.js +32 -5
- package/dist/shared/settingsSurface.js +6 -1
- package/docs/MIGRATION.md +56 -0
- package/docs/contracts/settings-classes.md +48 -7
- package/docs/guidelines/abstraction-thresholds.md +35 -0
- package/docs/guidelines/agent-infra/active-remediation-mechanics.md +3 -3
- package/docs/guidelines/agent-infra/false-green.md +2 -2
- package/docs/guidelines/agent-infra/notes-horizon-mechanics.md +90 -0
- package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
- package/docs/guidelines/agent-infra/skill-quality-checklist.md +1 -1
- package/docs/guidelines/design-fidelity-mechanics.md +4 -0
- package/docs/guidelines/design-fidelity-routing.md +78 -0
- package/docs/guidelines/design-reconciliation.md +172 -0
- package/docs/guidelines/gtm-handoff.md +2 -2
- package/docs/guidelines/wing4-handoff.md +2 -2
- package/llms.txt +1 -1
- package/package.json +7 -3
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +106 -4
- package/src/config/agent-settings.template.yml +94 -1
- package/src/config/ci-local-parity.yml +34 -0
- package/src/config/continuity-surface.json +8 -29
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +31 -8
- package/src/config/gate-reachability-exemptions.json +1 -0
- package/src/config/gate-violation-baselines.json +3 -3
- package/src/config/hook-token-budget.json +8 -7
- package/src/config/host-injection-effect.json +2 -2
- package/src/config/pack-size-budget.json +55 -4
- package/src/config/packed-binary-manifest.json +1 -1
- package/src/config/platform-anchor.json +47 -0
- package/src/config/preamble-payload-budget.json +2 -3
- package/src/config/publish-surface.json +4 -2
- package/src/config/ratification-policy.json +7 -0
- package/src/config/routing-coverage-seed.json +9 -2
- package/src/config/rule-stub-ceilings.json +16 -9
- package/src/scripts/_cli/cmd_session_recycle.ts +2 -25
- package/src/scripts/_cli/cmd_settings_get.ts +22 -7
- package/src/scripts/_cli/handoff_sessions.ts +14 -44
- package/src/scripts/_lib/agent_settings.ts +85 -0
- package/src/scripts/_lib/agent_src.ts +21 -0
- package/src/scripts/_lib/artifact_maturity.ts +242 -0
- package/src/scripts/_lib/conformance_report.ts +403 -0
- package/src/scripts/_lib/continuity_slot.ts +295 -0
- package/src/scripts/_lib/continuity_writer.ts +312 -0
- package/src/scripts/_lib/design_system_import.ts +20 -0
- package/src/scripts/_lib/design_tolerance.ts +281 -0
- package/src/scripts/_lib/guidelines_lane.ts +164 -0
- package/src/scripts/_lib/hook_settings.ts +85 -0
- package/src/scripts/_lib/lean_projection_mode.ts +127 -0
- package/src/scripts/_lib/obligation_frequency.ts +2 -3
- package/src/scripts/_lib/packed_binary_predicate.ts +37 -0
- package/src/scripts/_lib/platform_anchor.ts +1053 -0
- package/src/scripts/_lib/ratification_artifact.ts +278 -0
- package/src/scripts/_lib/recycle_envelope_paths.ts +109 -21
- package/src/scripts/_lib/regression_neighbourhood.ts +159 -22
- package/src/scripts/_lib/security_lint.ts +23 -2
- package/src/scripts/_lib/self_repair.ts +21 -0
- package/src/scripts/_lib/session_eol.ts +44 -0
- package/src/scripts/_lib/session_index_trust.ts +387 -0
- package/src/scripts/_lib/standing_bound_ratchet.ts +220 -0
- package/src/scripts/_lib/tolerance_shadow.ts +177 -0
- package/src/scripts/_lib/vendored_grammar_upstream.ts +280 -0
- package/src/scripts/ai_council/redact_low_impact_entry.ts +8 -0
- package/src/scripts/audit_mcp_tools.ts +69 -25
- package/src/scripts/autonomy_friction_traffic.ts +379 -0
- package/src/scripts/build_mcp_catalog.ts +24 -1
- package/src/scripts/check_host_tree_parity.ts +291 -0
- package/src/scripts/check_kernel_edit_ratified.ts +462 -0
- package/src/scripts/check_loss_class_declared.ts +793 -46
- package/src/scripts/check_platform_anchor.ts +390 -0
- package/src/scripts/check_preamble_payload_budget.ts +424 -7
- package/src/scripts/check_projected_rule_routes.ts +395 -0
- package/src/scripts/check_rule_projection_integrity.ts +102 -2
- package/src/scripts/ci_settle.ts +205 -5
- package/src/scripts/code_graph/build.ts +79 -0
- package/src/scripts/code_graph/cli.ts +264 -7
- package/src/scripts/code_graph/detect.ts +38 -0
- package/src/scripts/code_graph/query.ts +25 -2
- package/src/scripts/code_graph/sqlite_store.ts +16 -1
- package/src/scripts/code_graph/types.ts +52 -3
- package/src/scripts/code_graph/validate.ts +3 -1
- package/src/scripts/code_graph/verbs.ts +590 -0
- package/src/scripts/condense.ts +22 -26
- package/src/scripts/generate_host_cost_table.ts +354 -0
- package/src/scripts/handoff_context_hook.ts +39 -1
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +59 -28
- package/src/scripts/hooks/block_speaking_inbox_dir.ts +182 -16
- package/src/scripts/hooks/category_a.ts +1 -1
- package/src/scripts/hooks/chain_nudge_hook.ts +311 -25
- package/src/scripts/hooks/code_graph_context_hook.ts +7 -18
- package/src/scripts/hooks/push_settle_hook.ts +3 -2
- package/src/scripts/hooks/rule_inject_hook.ts +107 -20
- package/src/scripts/hooks/session_eol_hook.ts +177 -145
- package/src/scripts/hooks/source_first_gate_hook.ts +12 -0
- package/src/scripts/hooks/ui_route_nudge_hook.ts +52 -15
- package/src/scripts/hot_context_hook.ts +103 -408
- package/src/scripts/lint_evidence_artifacts.ts +1 -0
- package/src/scripts/lint_knowledge_scale.ts +0 -26
- package/src/scripts/lint_roadmap_blockers.ts +164 -1
- package/src/scripts/mcp_server/consumer_tool_catalog.json +152 -2
- package/src/scripts/mcp_server/graph_tools.ts +294 -0
- package/src/scripts/mcp_server/path_util.ts +31 -0
- package/src/scripts/mcp_server/tool_catalog_source.ts +7 -1
- package/src/scripts/mcp_server/tools.ts +3 -13
- package/src/scripts/memory_lookup.ts +9 -9
- package/src/scripts/model_rule_injection.ts +61 -4
- package/src/scripts/project_thin_rules.ts +149 -16
- package/src/scripts/report_standing_payload_by_host.ts +650 -0
- package/src/scripts/schemas/agent-settings.schema.json +7 -1
- package/src/scripts/session_memory_index.ts +86 -8
- package/src/scripts/sync_agent_settings.ts +270 -10
- package/src/server/io/yamlIO.ts +127 -17
- package/src/server/schemas/settings.ts +45 -6
- package/src/shared/settingsSurface.ts +13 -2
- package/src/templates/compact-instructions.md +8 -3
- package/src/vendor/grammars/README.md +27 -2
- package/dist/agent-src/commands/chat-history/import.md +0 -170
- package/dist/agent-src/commands/chat-history.md +0 -63
package/src/scripts/ci_settle.ts
CHANGED
|
@@ -18,10 +18,20 @@
|
|
|
18
18
|
* every agent's head: `not settled` and `settled` are different from `could not
|
|
19
19
|
* read`, and only the first two may end a wait.
|
|
20
20
|
*
|
|
21
|
-
*
|
|
21
|
+
* A verdict also has to be ABOUT SOMETHING, which is the second half of the
|
|
22
|
+
* same rule and was missing until 2026-09-08: the rollup answers about the head
|
|
23
|
+
* the PR *record* carries, and that head stops tracking the branch when the PR
|
|
24
|
+
* is merged or when the record lags a push. Both then look like a healthy
|
|
25
|
+
* green. {@link classifyTarget} refuses those, before the wait and again at
|
|
26
|
+
* verdict time. Measured cost of not having it: a `SETTLED GREEN — 40 check(s)`
|
|
27
|
+
* for a head with literally zero check runs.
|
|
28
|
+
*
|
|
29
|
+
* Exit codes: 0 = settled green, and the head it is about is named ·
|
|
22
30
|
* 1 = settled, at least one check failed ·
|
|
23
|
-
* 2 = did not settle within the budget,
|
|
24
|
-
*
|
|
31
|
+
* 2 = did not settle within the budget, the API could not be read,
|
|
32
|
+
* or the target is not a PR a verdict can be about (merged,
|
|
33
|
+
* closed, or head-diverged) — NEVER a verdict, and the reason
|
|
34
|
+
* is printed.
|
|
25
35
|
*
|
|
26
36
|
* Usage: ./scripts-run src/scripts/ci_settle <pr> [--timeout-min N] [--interval-sec N]
|
|
27
37
|
*
|
|
@@ -57,6 +67,121 @@ export type PollState =
|
|
|
57
67
|
| { kind: 'pending'; total: number; done: number }
|
|
58
68
|
| { kind: 'settled'; failing: string[]; total: number };
|
|
59
69
|
|
|
70
|
+
/**
|
|
71
|
+
* What `git ls-remote` said about the PR branch's tip.
|
|
72
|
+
*
|
|
73
|
+
* `absent` and `unreadable` are different answers and must not collapse: a
|
|
74
|
+
* cross-repo fork PR legitimately has no ref under this `origin`, while a
|
|
75
|
+
* transport failure means nobody knows. Collapsing them either disables the
|
|
76
|
+
* divergence check for forks silently, or blocks every fork PR forever.
|
|
77
|
+
*/
|
|
78
|
+
export type RemoteTip =
|
|
79
|
+
| { kind: 'found'; sha: string }
|
|
80
|
+
| { kind: 'absent' }
|
|
81
|
+
| { kind: 'unreadable'; reason: string };
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Whether the PR this wait is about still decides anything.
|
|
85
|
+
*
|
|
86
|
+
* `refuse` is NOT a verdict — it exits 2 like every other non-verdict, because
|
|
87
|
+
* the wait produced no readable statement about the head that matters.
|
|
88
|
+
*/
|
|
89
|
+
export type TargetState =
|
|
90
|
+
| { kind: 'open'; head: string; ref: string; divergenceChecked: boolean }
|
|
91
|
+
| { kind: 'unreadable'; reason: string }
|
|
92
|
+
| { kind: 'refuse'; reason: string };
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Decide whether a green from {@link classifyPoll} may be reported at all.
|
|
96
|
+
*
|
|
97
|
+
* WHY THIS EXISTS, measured 2026-09-08 on PR #1949 and paid for twice in one
|
|
98
|
+
* session. `gh pr view --json statusCheckRollup` answers about the head the PR
|
|
99
|
+
* *record* carries, and that head stops tracking the branch in two situations
|
|
100
|
+
* this script previously could not tell apart from a healthy wait:
|
|
101
|
+
*
|
|
102
|
+
* 1. **The PR is already merged or closed.** A push to its branch fires no
|
|
103
|
+
* `pull_request` event, so no checks are created for the new commits and the
|
|
104
|
+
* rollup keeps returning the merge-time head's checks. The script reported
|
|
105
|
+
* `SETTLED GREEN — 40 check(s)` for a head that had stopped mattering, and
|
|
106
|
+
* the only thing that exposed it was a hand-written
|
|
107
|
+
* `/commits/<sha>/check-runs` query answering `0`. Reported at face value
|
|
108
|
+
* that green authorises a merge of content nobody checked.
|
|
109
|
+
* 2. **The PR record lags the branch ref.** Same shape, different cause
|
|
110
|
+
* (recorded on PR #710): `git ls-remote` shows the new SHA while the record
|
|
111
|
+
* keeps the old one, and merging then lands the PR WITHOUT the newer
|
|
112
|
+
* commits — silently, which is what makes it worse than a red.
|
|
113
|
+
*
|
|
114
|
+
* Both are answered by the same two facts, which is why one function decides
|
|
115
|
+
* them: the PR's `state`, and whether its head equals the branch tip. Pure, so
|
|
116
|
+
* the failure is testable without a network — feed it a merged PR and it must
|
|
117
|
+
* answer `refuse`, never `open`.
|
|
118
|
+
*/
|
|
119
|
+
export function classifyTarget(
|
|
120
|
+
stdout: string,
|
|
121
|
+
stderr: string,
|
|
122
|
+
status: number | null,
|
|
123
|
+
tip: RemoteTip,
|
|
124
|
+
): TargetState {
|
|
125
|
+
const combined = `${stdout}\n${stderr}`.toLowerCase();
|
|
126
|
+
for (const marker of _UNREADABLE_MARKERS) {
|
|
127
|
+
if (combined.includes(marker.toLowerCase())) {
|
|
128
|
+
return { kind: 'unreadable', reason: marker };
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (status !== 0) {
|
|
132
|
+
return { kind: 'unreadable', reason: `gh exited ${String(status)}` };
|
|
133
|
+
}
|
|
134
|
+
let state: string;
|
|
135
|
+
let head: string;
|
|
136
|
+
let ref: string;
|
|
137
|
+
try {
|
|
138
|
+
const parsed = JSON.parse(stdout) as {
|
|
139
|
+
state?: unknown;
|
|
140
|
+
headRefOid?: unknown;
|
|
141
|
+
headRefName?: unknown;
|
|
142
|
+
};
|
|
143
|
+
if (
|
|
144
|
+
typeof parsed.state !== 'string' ||
|
|
145
|
+
typeof parsed.headRefOid !== 'string' ||
|
|
146
|
+
typeof parsed.headRefName !== 'string'
|
|
147
|
+
) {
|
|
148
|
+
return { kind: 'unreadable', reason: 'no state / headRefOid / headRefName in response' };
|
|
149
|
+
}
|
|
150
|
+
state = parsed.state.toUpperCase();
|
|
151
|
+
head = parsed.headRefOid;
|
|
152
|
+
ref = parsed.headRefName;
|
|
153
|
+
} catch {
|
|
154
|
+
return { kind: 'unreadable', reason: 'unparseable JSON' };
|
|
155
|
+
}
|
|
156
|
+
if (state !== 'OPEN') {
|
|
157
|
+
return {
|
|
158
|
+
kind: 'refuse',
|
|
159
|
+
reason:
|
|
160
|
+
`the PR is ${state}, not OPEN. Its rollup describes head ${head.slice(0, 9)} as of ` +
|
|
161
|
+
'that transition; pushes after it create no checks, so a green here would be about ' +
|
|
162
|
+
'a head that no longer decides anything',
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
if (tip.kind === 'unreadable') {
|
|
166
|
+
return { kind: 'unreadable', reason: `branch tip: ${tip.reason}` };
|
|
167
|
+
}
|
|
168
|
+
if (tip.kind === 'absent') {
|
|
169
|
+
// A fork PR's ref is not under this origin. Say the check did not apply
|
|
170
|
+
// rather than pretending it passed.
|
|
171
|
+
return { kind: 'open', head, ref, divergenceChecked: false };
|
|
172
|
+
}
|
|
173
|
+
if (tip.sha !== head) {
|
|
174
|
+
return {
|
|
175
|
+
kind: 'refuse',
|
|
176
|
+
reason:
|
|
177
|
+
`the PR record is at head ${head.slice(0, 9)} but origin/${ref} is at ` +
|
|
178
|
+
`${tip.sha.slice(0, 9)}. Merging in this state lands the PR WITHOUT the newer ` +
|
|
179
|
+
'commits (recorded on PR #710), and any verdict here is about the wrong head',
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
return { kind: 'open', head, ref, divergenceChecked: true };
|
|
183
|
+
}
|
|
184
|
+
|
|
60
185
|
/** Markers that mean the API did not answer — not that nothing is pending. */
|
|
61
186
|
const _UNREADABLE_MARKERS = [
|
|
62
187
|
'error connecting to',
|
|
@@ -126,6 +251,41 @@ function poll(pr: string): PollState {
|
|
|
126
251
|
return classifyPoll(r.stdout ?? '', r.stderr ?? '', r.status);
|
|
127
252
|
}
|
|
128
253
|
|
|
254
|
+
/**
|
|
255
|
+
* Read the branch tip from the remote, not from a local ref.
|
|
256
|
+
*
|
|
257
|
+
* A local `origin/<ref>` is only as fresh as the last fetch, and the divergence
|
|
258
|
+
* this guards against is created by somebody else's push — so a stale local ref
|
|
259
|
+
* would report agreement exactly when it matters most.
|
|
260
|
+
*/
|
|
261
|
+
function readTip(ref: string): RemoteTip {
|
|
262
|
+
const r = spawnSync('git', ['ls-remote', 'origin', `refs/heads/${ref}`], {
|
|
263
|
+
encoding: 'utf-8',
|
|
264
|
+
timeout: 60_000,
|
|
265
|
+
});
|
|
266
|
+
if (r.status !== 0) {
|
|
267
|
+
const why = (r.stderr ?? '').trim().split('\n')[0] ?? `git exited ${String(r.status)}`;
|
|
268
|
+
return { kind: 'unreadable', reason: why };
|
|
269
|
+
}
|
|
270
|
+
const line = (r.stdout ?? '').trim();
|
|
271
|
+
if (line === '') return { kind: 'absent' };
|
|
272
|
+
const sha = line.split(/\s+/)[0] ?? '';
|
|
273
|
+
return sha === '' ? { kind: 'unreadable', reason: 'empty sha in ls-remote output' } : { kind: 'found', sha };
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function readTarget(pr: string): TargetState {
|
|
277
|
+
const r = spawnSync('gh', ['pr', 'view', pr, '--json', 'state,headRefOid,headRefName'], {
|
|
278
|
+
encoding: 'utf-8',
|
|
279
|
+
timeout: 60_000,
|
|
280
|
+
});
|
|
281
|
+
// The ref name comes from the same read, so the tip lookup needs it first;
|
|
282
|
+
// classifyTarget is called twice rather than plumbing a callback through a
|
|
283
|
+
// pure function.
|
|
284
|
+
const shape = classifyTarget(r.stdout ?? '', r.stderr ?? '', r.status, { kind: 'absent' });
|
|
285
|
+
if (shape.kind !== 'open') return shape;
|
|
286
|
+
return classifyTarget(r.stdout ?? '', r.stderr ?? '', r.status, readTip(shape.ref));
|
|
287
|
+
}
|
|
288
|
+
|
|
129
289
|
function sleepSync(seconds: number): void {
|
|
130
290
|
// Deliberately synchronous: this is a CLI whose whole job is to block.
|
|
131
291
|
spawnSync(process.execPath, ['-e', `setTimeout(()=>{}, ${String(seconds * 1000)})`], {
|
|
@@ -164,18 +324,58 @@ export function main(argv: readonly string[]): number {
|
|
|
164
324
|
}
|
|
165
325
|
const intervalSec = num('--interval-sec', 60);
|
|
166
326
|
|
|
327
|
+
// Up front, because waiting nine minutes to learn the PR was merged before
|
|
328
|
+
// the wait began is the expensive way to find out.
|
|
329
|
+
const before = readTarget(pr);
|
|
330
|
+
if (before.kind === 'refuse') {
|
|
331
|
+
process.stdout.write(`ci_settle: REFUSING TO WAIT — ${before.reason}. No verdict is claimed.\n`);
|
|
332
|
+
return 2;
|
|
333
|
+
}
|
|
334
|
+
if (before.kind === 'unreadable') {
|
|
335
|
+
process.stdout.write(
|
|
336
|
+
`ci_settle: could not read the PR's target state (${before.reason}) — NOT a verdict, waiting anyway; ` +
|
|
337
|
+
'the pre-verdict re-check below still applies.\n',
|
|
338
|
+
);
|
|
339
|
+
} else if (!before.divergenceChecked) {
|
|
340
|
+
process.stdout.write(
|
|
341
|
+
`ci_settle: origin carries no refs/heads/${before.ref} (a fork PR) — the head-divergence check does not apply here.\n`,
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
|
|
167
345
|
const deadline = Date.now() + timeoutMin * 60_000;
|
|
168
346
|
let unreadableStreak = 0;
|
|
169
347
|
|
|
170
348
|
for (;;) {
|
|
171
349
|
const state = poll(pr);
|
|
172
350
|
if (state.kind === 'settled') {
|
|
351
|
+
// The rollup is about the record's head. Re-read that head at
|
|
352
|
+
// VERDICT time, not only at start: a push or a merge during the
|
|
353
|
+
// wait makes the rollup describe something the caller is not about
|
|
354
|
+
// to act on, and this is the last moment a wrong verdict is still
|
|
355
|
+
// preventable.
|
|
356
|
+
const at = readTarget(pr);
|
|
357
|
+
if (at.kind === 'refuse') {
|
|
358
|
+
process.stdout.write(
|
|
359
|
+
`ci_settle: WITHHOLDING A VERDICT — ${at.reason}. The checks that settled are not about ` +
|
|
360
|
+
'the head that matters now.\n',
|
|
361
|
+
);
|
|
362
|
+
return 2;
|
|
363
|
+
}
|
|
364
|
+
if (at.kind === 'unreadable') {
|
|
365
|
+
process.stdout.write(
|
|
366
|
+
`ci_settle: WITHHOLDING A VERDICT — could not confirm the target head (${at.reason}). ` +
|
|
367
|
+
'A verdict needs to name the head it is about.\n',
|
|
368
|
+
);
|
|
369
|
+
return 2;
|
|
370
|
+
}
|
|
173
371
|
if (state.failing.length === 0) {
|
|
174
|
-
process.stdout.write(
|
|
372
|
+
process.stdout.write(
|
|
373
|
+
`ci_settle: SETTLED GREEN — ${String(state.total)} check(s) on ${at.head.slice(0, 9)}\n`,
|
|
374
|
+
);
|
|
175
375
|
return 0;
|
|
176
376
|
}
|
|
177
377
|
process.stdout.write(
|
|
178
|
-
`ci_settle: SETTLED RED — ${String(state.failing.length)} of ${String(state.total)} failing:\n` +
|
|
378
|
+
`ci_settle: SETTLED RED — ${String(state.failing.length)} of ${String(state.total)} failing on ${at.head.slice(0, 9)}:\n` +
|
|
179
379
|
state.failing.map((f) => ` ${f}\n`).join(''),
|
|
180
380
|
);
|
|
181
381
|
return 1;
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
type EdgeConfidence,
|
|
35
35
|
EXPECTED_GRAMMAR_ABI,
|
|
36
36
|
EXT_LANG,
|
|
37
|
+
isStatedResolution,
|
|
37
38
|
type Lang,
|
|
38
39
|
type ResolvedVia,
|
|
39
40
|
SCHEMA_VERSION,
|
|
@@ -612,6 +613,52 @@ export function buildGraph(
|
|
|
612
613
|
});
|
|
613
614
|
}
|
|
614
615
|
|
|
616
|
+
// DERIVED `tests` edges (3.2).
|
|
617
|
+
//
|
|
618
|
+
// A test file that imports an in-repo symbol from a NON-test file is
|
|
619
|
+
// asserted to test it. Derived here rather than extracted because the
|
|
620
|
+
// predicate is a property of the two PATHS, which no grammar can see, and
|
|
621
|
+
// because `buildGraph` already holds every `imports` edge plus the node
|
|
622
|
+
// table needed to reject cross-test and out-of-repo targets.
|
|
623
|
+
//
|
|
624
|
+
// Three exclusions, each of which would otherwise manufacture a false
|
|
625
|
+
// `tests` edge:
|
|
626
|
+
// · target outside the repository (`external:*` / `symbol:*`) — there is
|
|
627
|
+
// no subject to test;
|
|
628
|
+
// · target in another TEST file — a shared test helper is not a subject;
|
|
629
|
+
// · target is the subject FILE node rather than a symbol in it, which is
|
|
630
|
+
// kept: a test that imports a module tests that module, and the file
|
|
631
|
+
// node is the only handle a caller has for a module with no exported
|
|
632
|
+
// symbol the extractor named;
|
|
633
|
+
// · THE SOURCE IMPORT IS ITSELF A GUESS. Added after an independent review
|
|
634
|
+
// demonstrated the laundering: a PHP `use Two\Mailer` with no
|
|
635
|
+
// `composer.json` binds by BASE NAME, so the `imports` edge is
|
|
636
|
+
// `name-lookup` and can point at `One\Mailer` — and a `tests` edge
|
|
637
|
+
// derived from it, stamped `test-import`, made that wrong target
|
|
638
|
+
// TRUSTWORTHY to every consumer of the accepted-edge filter. Measured
|
|
639
|
+
// consequences on a two-namespace fixture: `tests-for One\Mailer`
|
|
640
|
+
// named a test that does not test it, `tests-for Two\Mailer` reported
|
|
641
|
+
// none, `untested` inverted the pair, and `dead` called the tested class
|
|
642
|
+
// dead. A derived edge may never be more trustworthy than the edge it
|
|
643
|
+
// was derived from.
|
|
644
|
+
const nodeSourceFile = new Map(nodes.map((n) => [n.id, n.source_file]));
|
|
645
|
+
for (const e of [...edges]) {
|
|
646
|
+
if (e.relation !== 'imports') continue;
|
|
647
|
+
if (!isStatedResolution(e.resolved_via)) continue;
|
|
648
|
+
const from = nodeSourceFile.get(e.source);
|
|
649
|
+
if (from === undefined || !isTestFile(from)) continue;
|
|
650
|
+
const to = nodeSourceFile.get(e.target);
|
|
651
|
+
if (to === undefined || isTestFile(to)) continue;
|
|
652
|
+
emit({
|
|
653
|
+
source: e.source,
|
|
654
|
+
target: e.target,
|
|
655
|
+
relation: 'tests',
|
|
656
|
+
confidence: 'INFERRED',
|
|
657
|
+
resolved_via: 'test-import',
|
|
658
|
+
provider: 'native',
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
|
|
615
662
|
// deterministic ordering
|
|
616
663
|
nodes.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
617
664
|
edges.sort((a, b) => {
|
|
@@ -677,6 +724,38 @@ function ambiguousTarget(candidates: readonly string[], targetName: string): str
|
|
|
677
724
|
return `symbol:${targetName}`;
|
|
678
725
|
}
|
|
679
726
|
|
|
727
|
+
/**
|
|
728
|
+
* Is `relPath` a test file?
|
|
729
|
+
*
|
|
730
|
+
* A deterministic PATH predicate — no content read, no heuristic on the file's
|
|
731
|
+
* body. It is the input to the derived `tests` relation (3.2), so it has to be
|
|
732
|
+
* conservative in one direction only: a subject wrongly classified as a test
|
|
733
|
+
* silently loses its `tests` edges, while a test wrongly classified as a
|
|
734
|
+
* subject would make a test file look like a tested surface. Both are wrong;
|
|
735
|
+
* the second is worse, because `untested` would then report a real subject as
|
|
736
|
+
* covered.
|
|
737
|
+
*
|
|
738
|
+
* The four conventions are the ones this launch set actually uses, and each is
|
|
739
|
+
* anchored rather than substring-matched so a directory called
|
|
740
|
+
* `src/latest/thing.ts` is not a test:
|
|
741
|
+
*
|
|
742
|
+
* · a `tests/` or `test/` path segment (this repository's own layout);
|
|
743
|
+
* · a `__tests__/` segment (the JS convention);
|
|
744
|
+
* · a `.test.` / `.spec.` filename infix (Vitest / Jest / Pest-JS);
|
|
745
|
+
* · a `Test.php` / `test.php` filename suffix, or a `_test.php` infix
|
|
746
|
+
* (PHPUnit's `*Test.php` and Go-style `_test` both appear in PHP trees).
|
|
747
|
+
*/
|
|
748
|
+
export function isTestFile(relPath: string): boolean {
|
|
749
|
+
const p = relPath.split(path.sep).join('/');
|
|
750
|
+
const segments = p.split('/');
|
|
751
|
+
if (segments.some((seg) => seg === 'tests' || seg === 'test' || seg === '__tests__')) return true;
|
|
752
|
+
const base = segments[segments.length - 1] ?? '';
|
|
753
|
+
if (/\.(test|spec)\./i.test(base)) return true;
|
|
754
|
+
if (/(^|[._-])test\.php$/i.test(base)) return true;
|
|
755
|
+
if (/Test\.php$/.test(base)) return true;
|
|
756
|
+
return false;
|
|
757
|
+
}
|
|
758
|
+
|
|
680
759
|
export function serializeGraph(g: CodeGraph): string {
|
|
681
760
|
const key_order: (keyof CodeGraph)[] = [
|
|
682
761
|
'schema_version',
|
|
@@ -28,6 +28,20 @@
|
|
|
28
28
|
* `agents/runtime/state/code-graph-v1.json`) is local-only and disposable —
|
|
29
29
|
* gitignored, rebuildable from source at any time; never a source of truth.
|
|
30
30
|
*
|
|
31
|
+
* impact --diff <rev> [--depth N] callers/dependents/test files
|
|
32
|
+
* reachable from the changed
|
|
33
|
+
* symbols over ACCEPTED edges
|
|
34
|
+
* tests-for <symbol> test files importing the symbol
|
|
35
|
+
* untested --diff <rev> changed symbols no test imports
|
|
36
|
+
* dead [--entry-points F] zero accepted in-edges, minus
|
|
37
|
+
* [--accept-missing-exports] declared entry points; REFUSES
|
|
38
|
+
* when a source is unavailable
|
|
39
|
+
*
|
|
40
|
+
* The four gate verbs (3.1–3.3) each print the `resolved_via` histogram of the
|
|
41
|
+
* edges they accepted AND of the edges they refused to walk, plus the graph's
|
|
42
|
+
* three-state staleness — so a caller can tell "no callers" from "no callers I
|
|
43
|
+
* would trust", and "dead" from "dead as of a graph 40 commits behind".
|
|
44
|
+
*
|
|
31
45
|
* Query subcommands (query/path/explain/affected) are added by the Phase-3
|
|
32
46
|
* query tier. Deterministic, LLM-free, no network. Exit codes:
|
|
33
47
|
* 0 ok · 1 not-found / validation-failed / refresh-budget-exceeded ·
|
|
@@ -49,8 +63,8 @@ import process from 'node:process';
|
|
|
49
63
|
import { fileURLToPath } from 'node:url';
|
|
50
64
|
|
|
51
65
|
import { hardenedSpawnEnv } from '../_lib/spawn_env.js';
|
|
52
|
-
import { buildFromRepo, sidecarPath } from './build.js';
|
|
53
|
-
import { computeVerdict, detectSources, pickSource } from './detect.js';
|
|
66
|
+
import { buildFromRepo, isTestFile, sidecarPath } from './build.js';
|
|
67
|
+
import { computeVerdict, detectSources, type GraphState, graphState, pickSource } from './detect.js';
|
|
54
68
|
import { suggestVerb } from './intent.js';
|
|
55
69
|
import {
|
|
56
70
|
affected,
|
|
@@ -65,6 +79,18 @@ import {
|
|
|
65
79
|
import { openGraphIndex, sqliteTwinPath } from './sqlite_store.js';
|
|
66
80
|
import type { CodeGraph } from './types.js';
|
|
67
81
|
import { validateGraph } from './validate.js';
|
|
82
|
+
import {
|
|
83
|
+
dead,
|
|
84
|
+
type DeadResult,
|
|
85
|
+
entryPointsFromFile,
|
|
86
|
+
impact,
|
|
87
|
+
type ImpactResult,
|
|
88
|
+
repoEntryPoints,
|
|
89
|
+
testsFor,
|
|
90
|
+
type TestsForResult,
|
|
91
|
+
untested,
|
|
92
|
+
type UntestedResult,
|
|
93
|
+
} from './verbs.js';
|
|
68
94
|
|
|
69
95
|
const _HERE = fileURLToPath(import.meta.url);
|
|
70
96
|
export const REPO_ROOT = path.resolve(path.dirname(_HERE), '..', '..', '..');
|
|
@@ -258,10 +284,24 @@ function budgetOf(argv: string[]): number {
|
|
|
258
284
|
return Number.isFinite(b) && b > 0 ? b : 1500;
|
|
259
285
|
}
|
|
260
286
|
|
|
261
|
-
|
|
262
|
-
|
|
287
|
+
/**
|
|
288
|
+
* Files changed between `ref` and `HEAD`, repo-relative.
|
|
289
|
+
*
|
|
290
|
+
* Extracted from `changedNodeSeeds` so the Phase-3 verbs seed from the same
|
|
291
|
+
* diff reading as `affected --since`. `null` distinguishes "git refused" (a bad
|
|
292
|
+
* rev, not a repository) from "nothing changed" — a verb that reports an empty
|
|
293
|
+
* impact set for a rev git could not resolve is asserting something it never
|
|
294
|
+
* measured.
|
|
295
|
+
*/
|
|
296
|
+
export function changedFiles(root: string, ref: string): string[] | null {
|
|
297
|
+
// `execFileSync` takes an argv array, so there is no shell and `$(...)` in a
|
|
298
|
+
// rev is inert. What the `${ref}..HEAD` concatenation does NOT stop is
|
|
299
|
+
// OPTION injection: `--output=/tmp/x` becomes `--output=/tmp/x..HEAD`, a
|
|
300
|
+
// well-formed option whose value is a filename, and the file is written with
|
|
301
|
+
// exit 0 (probed 2026-09-09). A rev never begins with `-`.
|
|
302
|
+
if (ref.startsWith('-')) return null;
|
|
263
303
|
try {
|
|
264
|
-
|
|
304
|
+
return execFileSync('git', ['-C', root, 'diff', '--name-only', `${ref}..HEAD`], {
|
|
265
305
|
env: hardenedSpawnEnv(),
|
|
266
306
|
encoding: 'utf-8',
|
|
267
307
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
@@ -270,8 +310,13 @@ function changedNodeSeeds(g: LoadedGraph, root: string, ref: string): string[] {
|
|
|
270
310
|
.map((s) => s.trim())
|
|
271
311
|
.filter(Boolean);
|
|
272
312
|
} catch {
|
|
273
|
-
return
|
|
313
|
+
return null;
|
|
274
314
|
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function changedNodeSeeds(g: LoadedGraph, root: string, ref: string): string[] {
|
|
318
|
+
const files = changedFiles(root, ref);
|
|
319
|
+
if (files === null) return [];
|
|
275
320
|
// Served by the `nodes_source_file` index on the SQLite path, so a wide
|
|
276
321
|
// diff does not force the whole node table into memory to answer it.
|
|
277
322
|
return g.idsInFiles(files);
|
|
@@ -322,6 +367,213 @@ function isFlagValue(argv: string[], token: string): boolean {
|
|
|
322
367
|
return i > 0 && (argv[i - 1] as string).startsWith('--');
|
|
323
368
|
}
|
|
324
369
|
|
|
370
|
+
// Phase-3 gate verbs (3.1-3.3).
|
|
371
|
+
|
|
372
|
+
/** The staleness token every gate verb prints, per step 3.1–3.3's shared
|
|
373
|
+
* verify: "each prints `resolved_via` counts and the staleness state". */
|
|
374
|
+
/**
|
|
375
|
+
* The staleness of the graph the verb is ACTUALLY reading.
|
|
376
|
+
*
|
|
377
|
+
* `answeredBy` is `resolveGraph`'s own picked path when it has one. Without it
|
|
378
|
+
* the two disagreed on the case `resolveRoot`'s docstring exists for: with
|
|
379
|
+
* `--root <other repo>` the verb answers from `DEFAULT_CACHE` (anchored to the
|
|
380
|
+
* package tree) while `graphState` looked under the OTHER root, so the printed
|
|
381
|
+
* staleness described a cache the answer never came from. An independent review
|
|
382
|
+
* found the `--graph` half fixed and this half open.
|
|
383
|
+
*/
|
|
384
|
+
function stateOf(argv: string[], answeredBy?: string): GraphState {
|
|
385
|
+
const explicit = flag(argv, '--graph');
|
|
386
|
+
return graphState(resolveRoot(argv), explicit ?? answeredBy);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/** The two histogram lines + the staleness line, in one place so the four
|
|
390
|
+
* verbs cannot drift apart in how they report their own filtering. */
|
|
391
|
+
function renderEnvelope(r: { source: string; state: GraphState; accepted_via: string; rejected_via: string }): void {
|
|
392
|
+
process.stdout.write(`source: ${r.source}\nstaleness: ${r.state}\n`);
|
|
393
|
+
process.stdout.write(`accepted resolved_via: ${r.accepted_via}\n`);
|
|
394
|
+
process.stdout.write(`rejected resolved_via: ${r.rejected_via}\n`);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
function renderReads(reads: readonly { path: string; lines: [number, number] | null }[]): void {
|
|
398
|
+
if (!reads.length) return;
|
|
399
|
+
process.stdout.write('minimal read set:\n');
|
|
400
|
+
for (const r of reads) process.stdout.write(` ${r.path}${r.lines ? `:${r.lines[0]}-${r.lines[1]}` : ''}\n`);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* `impact --diff <rev>` (3.1) — callers, dependents and test files reachable
|
|
405
|
+
* from the changed symbols over ACCEPTED edges, plus the producing edges and a
|
|
406
|
+
* minimal read set.
|
|
407
|
+
*/
|
|
408
|
+
function cmdImpact(argv: string[]): number {
|
|
409
|
+
const ref = flag(argv, '--diff');
|
|
410
|
+
if (ref === null) {
|
|
411
|
+
process.stderr.write('usage: code_graph/cli.ts impact --diff <rev> [--graph P] [--depth N]\n');
|
|
412
|
+
return 2;
|
|
413
|
+
}
|
|
414
|
+
const root = resolveRoot(argv);
|
|
415
|
+
const files = changedFiles(root, ref);
|
|
416
|
+
if (files === null) {
|
|
417
|
+
process.stderr.write(`code-graph: cannot resolve rev '${ref}' in ${root}\n`);
|
|
418
|
+
return 1;
|
|
419
|
+
}
|
|
420
|
+
const r = resolveGraph(argv);
|
|
421
|
+
if ('err' in r) {
|
|
422
|
+
process.stderr.write(`code-graph: ${r.err}\n`);
|
|
423
|
+
return 1;
|
|
424
|
+
}
|
|
425
|
+
try {
|
|
426
|
+
const depth = Number(flag(argv, '--depth'));
|
|
427
|
+
const res: ImpactResult = impact(
|
|
428
|
+
r.g,
|
|
429
|
+
files,
|
|
430
|
+
stateOf(argv, r.g.answeredBy),
|
|
431
|
+
Number.isFinite(depth) && depth > 0 ? depth : 2,
|
|
432
|
+
isTestFile,
|
|
433
|
+
);
|
|
434
|
+
renderEnvelope(res);
|
|
435
|
+
process.stdout.write(`changed files: ${files.length} · seeds: ${res.seeds.length}\n`);
|
|
436
|
+
if (res.unresolved_files.length)
|
|
437
|
+
process.stdout.write(`unresolved changed files (no node in the graph): ${res.unresolved_files.join(', ')}\n`);
|
|
438
|
+
process.stdout.write(`dependents (${res.dependents.length}):\n`);
|
|
439
|
+
for (const d of res.dependents) process.stdout.write(` ${d}\n`);
|
|
440
|
+
process.stdout.write(`test files (${res.test_files.length}):\n`);
|
|
441
|
+
for (const t of res.test_files) process.stdout.write(` ${t}\n`);
|
|
442
|
+
process.stdout.write(`producing edges (${res.producing_edges.length}):\n`);
|
|
443
|
+
for (const e of res.producing_edges) process.stdout.write(` ${e}\n`);
|
|
444
|
+
renderReads(res.recommended_reads);
|
|
445
|
+
return 0;
|
|
446
|
+
} finally {
|
|
447
|
+
r.g.close();
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/** `tests-for <symbol>` (3.2) — the test files that import the symbol. */
|
|
452
|
+
function cmdTestsFor(argv: string[]): number {
|
|
453
|
+
const positional = argv.filter((a) => !a.startsWith('--') && !isFlagValue(argv, a));
|
|
454
|
+
const symbol = positional[0];
|
|
455
|
+
if (!symbol) {
|
|
456
|
+
process.stderr.write('usage: code_graph/cli.ts tests-for <symbol> [--graph P]\n');
|
|
457
|
+
return 2;
|
|
458
|
+
}
|
|
459
|
+
const r = resolveGraph(argv);
|
|
460
|
+
if ('err' in r) {
|
|
461
|
+
process.stderr.write(`code-graph: ${r.err}\n`);
|
|
462
|
+
return 1;
|
|
463
|
+
}
|
|
464
|
+
try {
|
|
465
|
+
const res: TestsForResult = testsFor(r.g, symbol, stateOf(argv, r.g.answeredBy));
|
|
466
|
+
renderEnvelope(res);
|
|
467
|
+
process.stdout.write(`seeds: ${res.seeds.join(', ') || '(none)'}\n`);
|
|
468
|
+
process.stdout.write(`tests (${res.tests.length}):\n`);
|
|
469
|
+
for (const t of res.tests) process.stdout.write(` ${t}\n`);
|
|
470
|
+
renderReads(res.recommended_reads);
|
|
471
|
+
return 0;
|
|
472
|
+
} finally {
|
|
473
|
+
r.g.close();
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/** `untested --diff <rev>` (3.2) — changed symbols no test file imports. */
|
|
478
|
+
function cmdUntested(argv: string[]): number {
|
|
479
|
+
const ref = flag(argv, '--diff');
|
|
480
|
+
if (ref === null) {
|
|
481
|
+
process.stderr.write('usage: code_graph/cli.ts untested --diff <rev> [--graph P]\n');
|
|
482
|
+
return 2;
|
|
483
|
+
}
|
|
484
|
+
const root = resolveRoot(argv);
|
|
485
|
+
const files = changedFiles(root, ref);
|
|
486
|
+
if (files === null) {
|
|
487
|
+
process.stderr.write(`code-graph: cannot resolve rev '${ref}' in ${root}\n`);
|
|
488
|
+
return 1;
|
|
489
|
+
}
|
|
490
|
+
const r = resolveGraph(argv);
|
|
491
|
+
if ('err' in r) {
|
|
492
|
+
process.stderr.write(`code-graph: ${r.err}\n`);
|
|
493
|
+
return 1;
|
|
494
|
+
}
|
|
495
|
+
try {
|
|
496
|
+
const res: UntestedResult = untested(r.g, files, stateOf(argv, r.g.answeredBy));
|
|
497
|
+
renderEnvelope(res);
|
|
498
|
+
process.stdout.write(`changed files: ${files.length} · changed symbols: ${res.tested.length + res.untested.length}\n`);
|
|
499
|
+
if (res.unresolved_files.length)
|
|
500
|
+
process.stdout.write(`unresolved changed files (no node in the graph): ${res.unresolved_files.join(', ')}\n`);
|
|
501
|
+
process.stdout.write(`tested (${res.tested.length}) · untested (${res.untested.length}):\n`);
|
|
502
|
+
for (const u of res.untested) process.stdout.write(` ${u}\n`);
|
|
503
|
+
renderReads(res.recommended_reads);
|
|
504
|
+
return 0;
|
|
505
|
+
} finally {
|
|
506
|
+
r.g.close();
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* `dead` (3.3) — symbols with zero accepted in-edges that no declared entry
|
|
512
|
+
* point names. REFUSES by default when an entry-point source is unavailable;
|
|
513
|
+
* see `verbs.ts::dead` for why that refusal is not relaxable by an options bag.
|
|
514
|
+
*/
|
|
515
|
+
function cmdDead(argv: string[]): number {
|
|
516
|
+
const r = resolveGraph(argv);
|
|
517
|
+
if ('err' in r) {
|
|
518
|
+
process.stderr.write(`code-graph: ${r.err}\n`);
|
|
519
|
+
return 1;
|
|
520
|
+
}
|
|
521
|
+
try {
|
|
522
|
+
const root = resolveRoot(argv);
|
|
523
|
+
const sources = repoEntryPoints(root);
|
|
524
|
+
const listFile = flag(argv, '--entry-points');
|
|
525
|
+
if (listFile !== null) {
|
|
526
|
+
if (!fs.existsSync(listFile)) {
|
|
527
|
+
process.stderr.write(`code-graph: entry-point list not found: ${listFile}\n`);
|
|
528
|
+
return 1;
|
|
529
|
+
}
|
|
530
|
+
// An operator-supplied list SUPPLIES the missing source, so the
|
|
531
|
+
// `exports` row stops being a gap rather than being ignored: the
|
|
532
|
+
// caller has stated the entry points the graph could not.
|
|
533
|
+
const supplied = entryPointsFromFile(listFile);
|
|
534
|
+
const patched = sources.map((srcRow) =>
|
|
535
|
+
srcRow.name === 'exports'
|
|
536
|
+
? { ...srcRow, status: 'read' as const, detail: `supplied by ${listFile}`, entries: [] }
|
|
537
|
+
: srcRow,
|
|
538
|
+
);
|
|
539
|
+
patched.push(supplied);
|
|
540
|
+
const res: DeadResult = dead(r.g, patched, stateOf(argv, r.g.answeredBy));
|
|
541
|
+
return renderDead(res);
|
|
542
|
+
}
|
|
543
|
+
const res: DeadResult = dead(r.g, sources, stateOf(argv, r.g.answeredBy), {
|
|
544
|
+
acceptMissingExports: argv.includes('--accept-missing-exports'),
|
|
545
|
+
});
|
|
546
|
+
return renderDead(res);
|
|
547
|
+
} finally {
|
|
548
|
+
r.g.close();
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
function renderDead(res: DeadResult): number {
|
|
553
|
+
// The envelope FIRST, on both branches. It used to print only after the
|
|
554
|
+
// refusal check, so the default invocation in this repository — where
|
|
555
|
+
// `exports` is always unavailable — printed neither histogram nor the
|
|
556
|
+
// staleness line, and 3.1-3.3's shared verify ("each prints `resolved_via`
|
|
557
|
+
// counts and the staleness state") held only on the branch that answers.
|
|
558
|
+
// A reader of a refusal wants the staleness most of all: it says whether
|
|
559
|
+
// re-running after a rebuild could change anything.
|
|
560
|
+
renderEnvelope(res);
|
|
561
|
+
process.stdout.write('entry-point sources consulted:\n');
|
|
562
|
+
for (const srcRow of res.sources)
|
|
563
|
+
process.stdout.write(
|
|
564
|
+
` ${srcRow.name.padEnd(13)} ${srcRow.status}${srcRow.detail ? ` — ${srcRow.detail}` : ''} · ${srcRow.entries.length} entr${srcRow.entries.length === 1 ? 'y' : 'ies'}\n`,
|
|
565
|
+
);
|
|
566
|
+
if (res.refusal !== null) {
|
|
567
|
+
process.stderr.write(`❌ dead refused: ${res.refusal}\n`);
|
|
568
|
+
return 1;
|
|
569
|
+
}
|
|
570
|
+
process.stdout.write(`excluded as declared entry points: ${res.excluded.length}\n`);
|
|
571
|
+
process.stdout.write(`dead (${res.dead.length}):\n`);
|
|
572
|
+
for (const d of res.dead) process.stdout.write(` ${d}\n`);
|
|
573
|
+
renderReads(res.recommended_reads);
|
|
574
|
+
return 0;
|
|
575
|
+
}
|
|
576
|
+
|
|
325
577
|
function cmdDetect(argv: string[]): number {
|
|
326
578
|
const root = resolveRoot(argv);
|
|
327
579
|
if (flag(argv, '--format') === 'json') {
|
|
@@ -462,9 +714,14 @@ export async function main(argv: string[] = process.argv.slice(2)): Promise<numb
|
|
|
462
714
|
if (sub === 'refresh') return cmdRefresh(argv.slice(1));
|
|
463
715
|
if (sub === 'query' || sub === 'explain' || sub === 'affected' || sub === 'path')
|
|
464
716
|
return cmdQuery(sub, argv.slice(1));
|
|
717
|
+
if (sub === 'impact') return cmdImpact(argv.slice(1));
|
|
718
|
+
if (sub === 'tests-for') return cmdTestsFor(argv.slice(1));
|
|
719
|
+
if (sub === 'untested') return cmdUntested(argv.slice(1));
|
|
720
|
+
if (sub === 'dead') return cmdDead(argv.slice(1));
|
|
465
721
|
if (sub === 'suggest-verb') return cmdSuggestVerb(argv.slice(1));
|
|
466
722
|
process.stderr.write(
|
|
467
|
-
'usage: code_graph/cli.ts <build|validate|detect|refresh|query|explain|affected|path|
|
|
723
|
+
'usage: code_graph/cli.ts <build|validate|detect|refresh|query|explain|affected|path|' +
|
|
724
|
+
'impact|tests-for|untested|dead|suggest-verb> [options]\n',
|
|
468
725
|
);
|
|
469
726
|
return 2;
|
|
470
727
|
} catch (e) {
|