@event4u/agent-config 14.23.0 → 16.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 +144 -152
- 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 +1 -1
- 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 +4 -3
- package/dist/agent-src/commands/roadmap/materialize.md +2 -2
- package/dist/agent-src/commands/roadmap/next.md +1 -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 +51 -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 +1 -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 +2 -2
- 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/rules/user-interaction.md +31 -30
- 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-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/error-handling-patterns/SKILL.md +9 -0
- 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/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 +11 -5
- 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-delegate/check_update_banner.js +12 -1
- package/dist/cli-delegate/{chunk-NLP54U3J.js → chunk-2XY7ILBT.js} +13 -1
- package/dist/cli-delegate/{chunk-IAI3XL43.js → chunk-3FKR64R5.js} +22 -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-KCNTUSPI.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-H32DGUJH.js} +15 -84
- package/dist/cli-delegate/{chunk-6RJA2F5A.js → chunk-IVBPRCQO.js} +1 -1
- package/dist/cli-delegate/chunk-NUHLI2RX.js +80 -0
- package/dist/cli-delegate/{chunk-TYSY33MD.js → chunk-QJWAUMJW.js} +12 -2
- package/dist/cli-delegate/{chunk-2KKXJW25.js → chunk-S3VFXMTM.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 +834 -275
- package/dist/cli-delegate/cmd_doctor.js +3 -3
- package/dist/cli-delegate/cmd_explain.js +5 -3
- package/dist/cli-delegate/cmd_export.js +4 -4
- package/dist/cli-delegate/cmd_handoff.js +6 -6
- 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 +3 -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 +3 -3
- 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 +54 -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 +25 -78
- 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 +9684 -9304
- package/dist/install/install.mjs +36 -8
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +2147 -1470
- 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/installed_lock.js +1 -1
- package/dist/scripts/condense.js +2 -5
- package/dist/server/io/yamlIO.js +175 -17
- package/dist/server/schemas/settings.js +18 -4
- package/dist/shared/settingsSurface.js +6 -1
- package/docs/contracts/settings-classes.md +18 -9
- 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/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/package.json +7 -3
- package/src/config/agent-settings.template.yml +55 -8
- package/src/config/ci-local-parity.yml +34 -0
- package/src/config/continuity-surface.json +11 -32
- 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 +1 -1
- package/src/config/host-injection-effect.json +2 -2
- package/src/config/pack-size-budget.json +55 -4
- package/src/config/platform-anchor.json +47 -0
- package/src/config/preamble-payload-budget.json +12 -8
- package/src/config/preamble-payload-exceptions.json +28 -0
- package/src/config/publish-surface.json +4 -2
- package/src/config/ratification-policy.json +7 -0
- package/src/config/rule-stub-ceilings.json +16 -9
- package/src/scripts/_cli/cmd_settings_get.ts +22 -7
- package/src/scripts/_dispatch.bash +3 -1
- 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/base_ref_payload.ts +315 -0
- package/src/scripts/_lib/conformance_report.ts +403 -0
- package/src/scripts/_lib/continuity_writer.ts +72 -13
- package/src/scripts/_lib/design_system_import.ts +20 -0
- package/src/scripts/_lib/design_tolerance.ts +281 -0
- package/src/scripts/_lib/dropped_decision.ts +142 -0
- package/src/scripts/_lib/guidelines_lane.ts +164 -0
- package/src/scripts/_lib/installed_lock.ts +1 -1
- package/src/scripts/_lib/measured_payload_ceiling.ts +424 -0
- package/src/scripts/_lib/obligation_frequency.ts +2 -3
- package/src/scripts/_lib/payload_catalogue_completeness.ts +211 -0
- package/src/scripts/_lib/platform_anchor.ts +1053 -0
- package/src/scripts/_lib/ratification_artifact.ts +278 -0
- package/src/scripts/_lib/release_findings_ingest.ts +324 -0
- package/src/scripts/_lib/release_tag_dispatch.ts +63 -0
- package/src/scripts/_lib/review_baseline.ts +254 -0
- package/src/scripts/_lib/review_skipped_record.ts +61 -1
- package/src/scripts/_lib/security_lint.ts +23 -2
- package/src/scripts/_lib/self_repair.ts +21 -0
- package/src/scripts/_lib/session_index_trust.ts +42 -1
- package/src/scripts/_lib/standing_bound_ratchet.ts +267 -88
- package/src/scripts/_lib/tolerance_shadow.ts +177 -0
- package/src/scripts/_lib/turn_end_refusals.ts +51 -4
- package/src/scripts/ai_council/redact_low_impact_entry.ts +8 -0
- package/src/scripts/autonomy_friction_traffic.ts +379 -0
- package/src/scripts/check_beta_review_markers.ts +35 -4
- package/src/scripts/check_finding_dispositions.ts +167 -16
- package/src/scripts/check_held_object_arrivals.ts +381 -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 +672 -107
- package/src/scripts/check_projected_rule_routes.ts +395 -0
- package/src/scripts/check_release_published.ts +1 -1
- package/src/scripts/check_reply_consistency.ts +86 -17
- package/src/scripts/code_graph/cli.ts +6 -0
- package/src/scripts/condense.ts +2 -6
- package/src/scripts/generate_host_cost_table.ts +354 -0
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +74 -30
- package/src/scripts/hooks/block_kernel_rule_writes.ts +12 -2
- package/src/scripts/hooks/category_a.ts +1 -1
- package/src/scripts/hooks/chain_nudge_hook.ts +311 -25
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/end_review_nudge_hook.ts +101 -21
- package/src/scripts/hooks/review_baseline_hook.ts +130 -0
- package/src/scripts/hooks/session_eol_hook.ts +68 -154
- package/src/scripts/hooks/source_first_gate_hook.ts +12 -0
- package/src/scripts/hooks/turn_end_gate_hook.ts +232 -14
- package/src/scripts/hooks/ui_route_nudge_hook.ts +52 -15
- package/src/scripts/hooks_doctor.ts +4 -1
- package/src/scripts/hot_context_hook.ts +41 -401
- package/src/scripts/install.ts +1 -1
- package/src/scripts/interruption_report.ts +8 -2
- package/src/scripts/janitor.ts +8 -1
- package/src/scripts/lint_evidence_artifacts.ts +1 -0
- package/src/scripts/lint_knowledge_scale.ts +0 -26
- package/src/scripts/measure_turn_end_gate.ts +302 -5
- package/src/scripts/memory_lookup.ts +9 -9
- package/src/scripts/release.ts +52 -64
- package/src/scripts/release_drill.ts +193 -14
- package/src/scripts/release_env.ts +1 -1
- package/src/scripts/release_publication.ts +1 -1
- package/src/scripts/report_held_object_arrivals.ts +456 -0
- package/src/scripts/report_standing_payload_by_host.ts +7 -7
- package/src/scripts/session_memory_index.ts +5 -0
- package/src/scripts/sync_agent_settings.ts +394 -12
- package/src/server/io/yamlIO.ts +175 -17
- package/src/server/schemas/settings.ts +25 -5
- package/src/shared/settingsSurface.ts +13 -2
- package/src/templates/compact-instructions.md +8 -3
- package/dist/agent-src/commands/chat-history/import.md +0 -170
- package/dist/agent-src/commands/chat-history.md +0 -63
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* is deliberately not another reminder. It is a check at the point of
|
|
10
10
|
* delivery that can say no.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
12
|
+
* FIVE detectors ride on one guard, because building the unsafe part twice
|
|
13
13
|
* is how a second detector becomes a second outage:
|
|
14
14
|
*
|
|
15
15
|
* A — promissory closing (FC-5, 20 measured occurrences)
|
|
@@ -22,11 +22,18 @@
|
|
|
22
22
|
* only, so tool activity is invisible to A and B.)
|
|
23
23
|
* D — completion claim (a claim of done carrying no fresh evidence; landed
|
|
24
24
|
* under conformance round 7 § Phase 1.)
|
|
25
|
+
* E — pending decision (an earlier reply in the SAME user turn put numbered
|
|
26
|
+
* options to the user and the closing reply carries
|
|
27
|
+
* none — the turn asked and then dropped the ask.
|
|
28
|
+
* Read off `assistantTurnTexts`, which is why that
|
|
29
|
+
* field exists: every other detector reads
|
|
30
|
+
* `lastAssistant` alone and therefore cannot see a
|
|
31
|
+
* question that was asked one reply earlier.)
|
|
25
32
|
*
|
|
26
|
-
* TWO of the
|
|
33
|
+
* TWO of the five are CONDITIONAL, and saying "unconditional" here would be the
|
|
27
34
|
* same stale-header defect this block corrects below. A and D are the
|
|
28
35
|
* completion-adjacent pair an open subagent dispatch excuses, so `main()` runs
|
|
29
|
-
* them only when `dispatchOpen` is false; B and
|
|
36
|
+
* them only when `dispatchOpen` is false; B, C and E run on every turn-end. That
|
|
30
37
|
* narrowing is deliberate (Phase 3 Step 2, narrowed again by R2 round 2) and is
|
|
31
38
|
* the third allow path, alongside the two re-entrancy layers — see the
|
|
32
39
|
* per-detector list in `main()`.
|
|
@@ -35,7 +42,7 @@
|
|
|
35
42
|
* below has carried four since round 7. `DETECTOR_IDS` in
|
|
36
43
|
* `_lib/turn_end_refusals.ts` is read off that union rather than off this
|
|
37
44
|
* comment for exactly that reason, and the count is corrected here rather than
|
|
38
|
-
* left as a stale header the next reader has to disbelieve.
|
|
45
|
+
* left as a stale header the next reader has to disbelieve. E made it five.
|
|
39
46
|
*
|
|
40
47
|
* ## Removal condition
|
|
41
48
|
*
|
|
@@ -157,6 +164,23 @@ import {
|
|
|
157
164
|
// agreement invisible when the producer's layout moved. A builder makes the move
|
|
158
165
|
// a type error.
|
|
159
166
|
import { statePathFor as ciStatePathFor } from '../before_complete_hook.js';
|
|
167
|
+
// The spec-backed options-block reading, imported rather than re-derived:
|
|
168
|
+
// `user-interaction` Iron Law 1's definition of an ask — a block PLUS its
|
|
169
|
+
// recommendation line — lives in exactly one place and detector E reads it from
|
|
170
|
+
// there.
|
|
171
|
+
//
|
|
172
|
+
// WHAT KEEPS IT FROM RUNNING ON IMPORT, stated precisely because the obvious
|
|
173
|
+
// answer is wrong: that module is `_isCliEntry`-guarded, but WITHOUT the
|
|
174
|
+
// `__AGENT_CONFIG_BUNDLE__` early-out this file carries. Inside
|
|
175
|
+
// `dist/hooks/dispatch.js` every module shares one `import.meta.url`, so the
|
|
176
|
+
// guard alone would not settle it; what does is the `.__direct__` argv rewrite
|
|
177
|
+
// in the `build:hooks` banner. Named here so a future change to that banner
|
|
178
|
+
// does not silently start running a lint's `main()` on every hook dispatch.
|
|
179
|
+
// Detector E, extracted to `_lib` where its prose costs no ratchet debt.
|
|
180
|
+
// Re-exported so every existing importer of this module is unchanged.
|
|
181
|
+
import { detectDroppedDecision } from '../_lib/dropped_decision.js';
|
|
182
|
+
|
|
183
|
+
export { detectDroppedDecision };
|
|
160
184
|
import { isSafeTranscriptPath } from './end_review_nudge_hook.js';
|
|
161
185
|
import { unwrap, type JsonObject, type JsonValue } from './envelope.js';
|
|
162
186
|
import { readHookStdin } from './hook_stdin.js';
|
|
@@ -190,7 +214,13 @@ const EXIT_ALLOW = 0;
|
|
|
190
214
|
export const TRANSCRIPT_READ_MAX_BYTES = 8 * 1024 * 1024; // 8 MB
|
|
191
215
|
|
|
192
216
|
/** Detector identity, used in the state marker and the refusal text. */
|
|
193
|
-
export type DetectorId =
|
|
217
|
+
export type DetectorId =
|
|
218
|
+
| 'promissory'
|
|
219
|
+
| 'language'
|
|
220
|
+
| 'verification'
|
|
221
|
+
| 'completion'
|
|
222
|
+
| 'pending-decision'
|
|
223
|
+
| 'untested';
|
|
194
224
|
|
|
195
225
|
export interface Finding {
|
|
196
226
|
detector: DetectorId;
|
|
@@ -723,6 +753,110 @@ export function detectUnverifiedEdit(toolCalls: readonly ToolCall[]): Finding |
|
|
|
723
753
|
};
|
|
724
754
|
}
|
|
725
755
|
|
|
756
|
+
// ---------------------------------------------------------------------------
|
|
757
|
+
// Detector F — a completion claim over production code no test accompanies
|
|
758
|
+
// ---------------------------------------------------------------------------
|
|
759
|
+
|
|
760
|
+
/**
|
|
761
|
+
* WHY THIS EXISTS, and why detector C did not already cover it.
|
|
762
|
+
*
|
|
763
|
+
* Detector C asks "did ANY verification command run after the last edit". It is
|
|
764
|
+
* satisfied by `eslint`. That is deliberate — see `isVerificationCommand`, which
|
|
765
|
+
* is narrow about what counts as a command and says nothing about what the
|
|
766
|
+
* command COVERS. So a turn can write four hundred lines of feature code, run
|
|
767
|
+
* the linter, claim done, and pass every guard in this file.
|
|
768
|
+
*
|
|
769
|
+
* Measured consequence, reported by the maintainer 2026-09-11 about a consumer
|
|
770
|
+
* project: a feature shipped whose detail view crashed on open, whose flyouts
|
|
771
|
+
* were broken, and for which the maintainer then had to hand-enumerate what
|
|
772
|
+
* should have been exercised — every view, every CRUD path, drag-and-drop,
|
|
773
|
+
* mobile, filters. Their words: *"Solche Fehler können nur auftreten, weil Du
|
|
774
|
+
* nicht TDD gearbeitet ... hast."* Nothing in the suite refused that turn,
|
|
775
|
+
* because nothing in the suite asks whether the change is TESTED — only whether
|
|
776
|
+
* something ran.
|
|
777
|
+
*
|
|
778
|
+
* THE SIGNAL, and why it is this one. "Is the change covered" is undecidable
|
|
779
|
+
* from a transcript: coverage lives in the consumer's tooling, which this hook
|
|
780
|
+
* cannot run. What IS decidable is the cheapest possible proxy, and it happens
|
|
781
|
+
* to be the exact shape of the reported failure — **production source changed,
|
|
782
|
+
* no test file touched, done claimed**. A proxy is worth shipping here precisely
|
|
783
|
+
* because the population it flags is small and the failure it catches is total:
|
|
784
|
+
* a feature with zero new test lines is not under-tested, it is untested.
|
|
785
|
+
*
|
|
786
|
+
* WHY IT IS GATED ON THE CLAIM rather than on the edit. Firing on every edit
|
|
787
|
+
* would refuse the first turn of every red-green-refactor cycle — the discipline
|
|
788
|
+
* it exists to encourage — and a guard that fires on the majority of turns is a
|
|
789
|
+
* guard that gets switched off. The obligation belongs to the CLAIM, which is
|
|
790
|
+
* also where `verify-before-complete` puts it and where detector D already sits.
|
|
791
|
+
*
|
|
792
|
+
* WHAT IT CANNOT DO. It cannot tell a good test from a token one: a turn that
|
|
793
|
+
* touches any test file clears it. That is a deliberate floor rather than an
|
|
794
|
+
* oversight — `testing-anti-patterns` owns assertion quality, and a guard that
|
|
795
|
+
* tried to judge it from a path would be judging something it cannot see. The
|
|
796
|
+
* honest claim is narrow: this refuses the case where the agent wrote NO test at
|
|
797
|
+
* all and said it was finished.
|
|
798
|
+
*/
|
|
799
|
+
|
|
800
|
+
/** Extensions that carry behaviour a test can be owed for. */
|
|
801
|
+
const _SOURCE_RE = /\.(?:ts|tsx|js|jsx|mjs|cjs|vue|svelte|php|py|rb|go|rs|java|kt|swift|cs|scala|ex|exs)$/i;
|
|
802
|
+
|
|
803
|
+
/**
|
|
804
|
+
* Paths that ARE tests, across the conventions this suite's stacks use.
|
|
805
|
+
*
|
|
806
|
+
* Deliberately generous: a false NEGATIVE here (calling a test file a test) only
|
|
807
|
+
* silences the detector, while a false positive would refuse a turn that did
|
|
808
|
+
* write its tests — the direction that gets a guard disabled.
|
|
809
|
+
*/
|
|
810
|
+
const _TEST_PATH_RE =
|
|
811
|
+
/(?:^|\/)(?:tests?|specs?|__tests__|__specs__|e2e|cypress|playwright|features)\//i;
|
|
812
|
+
const _TEST_FILE_RE =
|
|
813
|
+
/(?:\.(?:test|spec)\.[a-z]+$)|(?:_test\.[a-z]+$)|(?:(?:^|\/)test_[^/]+$)|(?:Test\.php$)|(?:Spec\.php$)|(?:\.feature$)/i;
|
|
814
|
+
|
|
815
|
+
function _isTestPath(p: string): boolean {
|
|
816
|
+
return _TEST_PATH_RE.test(p) || _TEST_FILE_RE.test(p);
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
function _isProductionSource(p: string): boolean {
|
|
820
|
+
return _SOURCE_RE.test(p) && !_isTestPath(p);
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Fire when the turn changed production code, touched no test, and said done.
|
|
825
|
+
*
|
|
826
|
+
* All three conditions are load-bearing. Drop the first and it fires on a docs
|
|
827
|
+
* turn; drop the second and it fires on a turn that did its job; drop the third
|
|
828
|
+
* and it fires mid-cycle on the red step of red-green-refactor.
|
|
829
|
+
*/
|
|
830
|
+
export function detectUntestedChange(reply: string, toolCalls: readonly ToolCall[]): Finding | null {
|
|
831
|
+
const edited = toolCalls
|
|
832
|
+
.filter((c) => _EDIT_TOOLS.has(c.name) && c.path !== undefined)
|
|
833
|
+
.map((c) => c.path as string);
|
|
834
|
+
const source = edited.filter(_isProductionSource);
|
|
835
|
+
if (source.length === 0) return null;
|
|
836
|
+
if (edited.some(_isTestPath)) return null;
|
|
837
|
+
|
|
838
|
+
// The claim gate, reusing detector D's pair rather than a second dialect of
|
|
839
|
+
// "done" — two lists of completion phrasings would drift, and the negation
|
|
840
|
+
// check is what keeps an honest "noch nicht fertig" from being refused.
|
|
841
|
+
const prose = visibleProse(reply);
|
|
842
|
+
const m = _COMPLETION_RE.exec(prose);
|
|
843
|
+
if (!m) return null;
|
|
844
|
+
if (_NEGATED_CLAIM_RE.test(_lineAround(prose, m.index))) return null;
|
|
845
|
+
|
|
846
|
+
const shown = source.slice(0, 3).join(', ');
|
|
847
|
+
return {
|
|
848
|
+
detector: 'untested',
|
|
849
|
+
evidence: shown + (source.length > 3 ? ` (+${String(source.length - 3)} more)` : ''),
|
|
850
|
+
reason:
|
|
851
|
+
'a completion claim over production code this turn changed, with NO test file ' +
|
|
852
|
+
'touched anywhere in the turn — running a linter is not evidence the change ' +
|
|
853
|
+
'works. Write the test that would have caught the failure, and enumerate the ' +
|
|
854
|
+
'states the change actually has (every view, every CRUD path, the empty and ' +
|
|
855
|
+
'error states) rather than the happy one. If a test genuinely does not belong ' +
|
|
856
|
+
'here, say which file carries the coverage instead',
|
|
857
|
+
};
|
|
858
|
+
}
|
|
859
|
+
|
|
726
860
|
// ---------------------------------------------------------------------------
|
|
727
861
|
// Re-entrancy — the guard, keyed on the turn, not on the reply
|
|
728
862
|
// ---------------------------------------------------------------------------
|
|
@@ -811,6 +945,7 @@ function markRefusedTurn(
|
|
|
811
945
|
sessionKey: string,
|
|
812
946
|
turnOrdinal: number,
|
|
813
947
|
detectors: readonly DetectorId[],
|
|
948
|
+
promptId: string,
|
|
814
949
|
): void {
|
|
815
950
|
if (is_replay_mode()) return;
|
|
816
951
|
const file = sessionStateFile(workspaceRoot, sessionKey);
|
|
@@ -835,6 +970,7 @@ function markRefusedTurn(
|
|
|
835
970
|
turnOrdinal,
|
|
836
971
|
at: new Date().toISOString(),
|
|
837
972
|
version,
|
|
973
|
+
promptId,
|
|
838
974
|
}) as unknown as Record<string, unknown>,
|
|
839
975
|
);
|
|
840
976
|
} catch {
|
|
@@ -868,6 +1004,20 @@ export interface ToolCall {
|
|
|
868
1004
|
|
|
869
1005
|
export interface TranscriptTail {
|
|
870
1006
|
lastAssistant: string;
|
|
1007
|
+
/**
|
|
1008
|
+
* Every assistant text of the CURRENT turn, in order — reset at each genuine
|
|
1009
|
+
* user prompt exactly like `toolCalls`, and for the same reason: a question
|
|
1010
|
+
* asked three turns ago was answered, a question asked earlier in THIS turn
|
|
1011
|
+
* was not. Detector E reads it; the other four read `lastAssistant`, which is
|
|
1012
|
+
* always the last element when this is non-empty.
|
|
1013
|
+
*
|
|
1014
|
+
* A tool-only assistant entry contributes NOTHING here. `_messageText`
|
|
1015
|
+
* returns null for it and the collector skips it, so the ordinary shape of a
|
|
1016
|
+
* working turn — prose, tool call, prose — produces two elements and not
|
|
1017
|
+
* three. That is the whole false-positive surface of detector E, and it is
|
|
1018
|
+
* closed here rather than in the detector.
|
|
1019
|
+
*/
|
|
1020
|
+
assistantTurnTexts: string[];
|
|
871
1021
|
/**
|
|
872
1022
|
* How many GENUINE user prompts the transcript carries — harness-injected
|
|
873
1023
|
* user-role entries excluded via `isSyntheticPrompt`. This is the turn's
|
|
@@ -899,7 +1049,12 @@ export function readTranscriptTail(
|
|
|
899
1049
|
transcriptPath: string,
|
|
900
1050
|
opts: { homeDir?: string; maxBytes?: number } = {},
|
|
901
1051
|
): TranscriptTail {
|
|
902
|
-
const empty: TranscriptTail = {
|
|
1052
|
+
const empty: TranscriptTail = {
|
|
1053
|
+
lastAssistant: '',
|
|
1054
|
+
turnOrdinal: 0,
|
|
1055
|
+
toolCalls: [],
|
|
1056
|
+
assistantTurnTexts: [],
|
|
1057
|
+
};
|
|
903
1058
|
if (!transcriptPath || !isSafeTranscriptPath(transcriptPath, opts)) return empty;
|
|
904
1059
|
let lines: string[];
|
|
905
1060
|
try {
|
|
@@ -919,6 +1074,7 @@ export function readTranscriptTail(
|
|
|
919
1074
|
let lastAssistant = '';
|
|
920
1075
|
let turnOrdinal = 0;
|
|
921
1076
|
let toolCalls: ToolCall[] = [];
|
|
1077
|
+
let assistantTurnTexts: string[] = [];
|
|
922
1078
|
for (const rawLine of lines) {
|
|
923
1079
|
const line = rawLine.trim();
|
|
924
1080
|
if (!line) continue;
|
|
@@ -944,12 +1100,13 @@ export function readTranscriptTail(
|
|
|
944
1100
|
// only a tool_use block has no text at all, so `continue`-ing on a null
|
|
945
1101
|
// text would drop exactly the entries this detector exists to see.
|
|
946
1102
|
if (role === 'assistant') {
|
|
947
|
-
toolCalls.push(...
|
|
1103
|
+
toolCalls.push(...extractToolCalls(content));
|
|
948
1104
|
}
|
|
949
1105
|
const text = _messageText(content);
|
|
950
1106
|
if (text === null) continue;
|
|
951
1107
|
if (role === 'assistant') {
|
|
952
1108
|
lastAssistant = text;
|
|
1109
|
+
assistantTurnTexts.push(text);
|
|
953
1110
|
} else if (!isSyntheticPrompt(text)) {
|
|
954
1111
|
turnOrdinal += 1;
|
|
955
1112
|
// A genuine user prompt starts a new turn, so the previous turn's
|
|
@@ -957,17 +1114,34 @@ export function readTranscriptTail(
|
|
|
957
1114
|
// run three turns ago would vouch for an edit made now — the
|
|
958
1115
|
// "fresh" in edit-without-FRESH-verification is this line.
|
|
959
1116
|
toolCalls = [];
|
|
1117
|
+
// Same boundary, same reason, for detector E: an options block the
|
|
1118
|
+
// user has since replied to is answered, not dropped. Resetting on
|
|
1119
|
+
// the identical line is what makes "in the SAME user turn" true of
|
|
1120
|
+
// the array rather than merely intended.
|
|
1121
|
+
assistantTurnTexts = [];
|
|
960
1122
|
}
|
|
961
1123
|
}
|
|
962
|
-
return {
|
|
1124
|
+
return {
|
|
1125
|
+
lastAssistant: lastAssistant.trim(),
|
|
1126
|
+
turnOrdinal,
|
|
1127
|
+
toolCalls,
|
|
1128
|
+
assistantTurnTexts,
|
|
1129
|
+
};
|
|
963
1130
|
}
|
|
964
1131
|
|
|
965
1132
|
/**
|
|
966
1133
|
* Extract this entry's tool calls, keeping only name, shell command and target
|
|
967
1134
|
* path. A tool input can hold a whole file body; nothing but those three fields
|
|
968
1135
|
* is carried forward.
|
|
1136
|
+
*
|
|
1137
|
+
* Exported because `measure_turn_end_gate` scores detectors C and E over a real
|
|
1138
|
+
* transcript corpus and therefore has to rebuild the same `ToolCall[]` the gate
|
|
1139
|
+
* sees. A second extractor there would be a second dialect of "what the turn
|
|
1140
|
+
* did", and the measurement would then be of that dialect rather than of the
|
|
1141
|
+
* shipped gate — the exact population-parity defect that script's own header
|
|
1142
|
+
* documents twice.
|
|
969
1143
|
*/
|
|
970
|
-
function
|
|
1144
|
+
export function extractToolCalls(content: unknown): ToolCall[] {
|
|
971
1145
|
if (!Array.isArray(content)) return [];
|
|
972
1146
|
const out: ToolCall[] = [];
|
|
973
1147
|
for (const blk of content) {
|
|
@@ -1074,11 +1248,30 @@ export function main(): number {
|
|
|
1074
1248
|
// in production while its comment claimed it was enforced — the same
|
|
1075
1249
|
// fixed-the-definition-not-the-caller shape as two other findings in that
|
|
1076
1250
|
// round, which is why this line exists rather than a default parameter.
|
|
1077
|
-
const { lastAssistant, turnOrdinal, toolCalls } = readTranscriptTail(
|
|
1078
|
-
|
|
1079
|
-
|
|
1251
|
+
const { lastAssistant, turnOrdinal, toolCalls, assistantTurnTexts } = readTranscriptTail(
|
|
1252
|
+
transcriptPath,
|
|
1253
|
+
{ maxBytes: TRANSCRIPT_READ_MAX_BYTES },
|
|
1254
|
+
);
|
|
1080
1255
|
if (!lastAssistant) return EXIT_ALLOW;
|
|
1081
1256
|
|
|
1257
|
+
// The closing reply comes from the field the host hands us when it supplies
|
|
1258
|
+
// one, not only from a file the host writes asynchronously. The transcript
|
|
1259
|
+
// may lag the in-memory conversation, and a tail that is one assistant entry
|
|
1260
|
+
// short is silence for `detectDroppedDecision`, whose early return needs two
|
|
1261
|
+
// texts — i.e. the detector goes quiet in exactly the shape it exists for.
|
|
1262
|
+
// `suggestion_capture_hook.ts` reads the same field for the same reason.
|
|
1263
|
+
// Appended, never substituted: `lastAssistant` and the four other detectors
|
|
1264
|
+
// are untouched, and a host that supplies no such field is unchanged.
|
|
1265
|
+
const payloadClosing = str(
|
|
1266
|
+
(payload['last_assistant_message'] ?? payload['lastAssistantMessage']) as
|
|
1267
|
+
| JsonValue
|
|
1268
|
+
| undefined,
|
|
1269
|
+
);
|
|
1270
|
+
const closingFromPayload = payloadClosing !== '' && !assistantTurnTexts.includes(payloadClosing);
|
|
1271
|
+
const turnTexts = closingFromPayload
|
|
1272
|
+
? [...assistantTurnTexts, payloadClosing]
|
|
1273
|
+
: assistantTurnTexts;
|
|
1274
|
+
|
|
1082
1275
|
// Layer 2 — keyed on the turn's ORDINAL, never on the prompt's text.
|
|
1083
1276
|
// A host that sends no `session_id` shares one bucket AND one small-integer
|
|
1084
1277
|
// ordinal namespace, so an unrelated session whose ordinal matches a stored
|
|
@@ -1092,6 +1285,13 @@ export function main(): number {
|
|
|
1092
1285
|
// producer keys that on the raw `session_id`. Passing `sessionKey` here would
|
|
1093
1286
|
// read a path nothing writes — the same shape as the STATE_FILE break this
|
|
1094
1287
|
// parameter exists to close.
|
|
1288
|
+
// The host's own id for the prompt being processed. Read here and recorded
|
|
1289
|
+
// beside the ordinal in the refusal marker — never used as the guard key.
|
|
1290
|
+
// The ordinal's drift is what both re-entrancy layers exist for, so a later
|
|
1291
|
+
// reading needs the pair to tell a drifted ordinal from a second prompt.
|
|
1292
|
+
const promptId = str(
|
|
1293
|
+
(payload['prompt_id'] ?? payload['promptId']) as JsonValue | undefined,
|
|
1294
|
+
);
|
|
1095
1295
|
const rawSessionId = str(envelope['session_id'] as JsonValue | undefined) || '';
|
|
1096
1296
|
const sessionKey = deriveSessionKey(rawSessionId || 'unknown-session');
|
|
1097
1297
|
if (alreadyRefusedTurn(workspaceRoot, sessionKey, turnOrdinal)) return EXIT_ALLOW;
|
|
@@ -1129,6 +1329,22 @@ export function main(): number {
|
|
|
1129
1329
|
dispatchOpen
|
|
1130
1330
|
? null
|
|
1131
1331
|
: detectCompletionClaim(lastAssistant, readCiSettled(workspaceRoot, rawSessionId)),
|
|
1332
|
+
// Detector E is UNCONDITIONAL, and that is the opposite choice from A
|
|
1333
|
+
// and D one line above rather than an oversight. An open dispatch
|
|
1334
|
+
// excuses a promissory closing because the work is genuinely still
|
|
1335
|
+
// running; it excuses nothing about a question the user was already
|
|
1336
|
+
// asked. Worse: a dispatch — or the `end-review-nudge` stop concern
|
|
1337
|
+
// that produced the measured failure — IS the continuation that drops
|
|
1338
|
+
// the decision, so narrowing E the same way would silence it in exactly
|
|
1339
|
+
// the case it exists for.
|
|
1340
|
+
detectDroppedDecision(turnTexts, closingFromPayload),
|
|
1341
|
+
// Detector F takes the OTHER side of that same question, and the two
|
|
1342
|
+
// sitting adjacent is the clearest place to say why. E fires on a
|
|
1343
|
+
// question already asked, which an open dispatch cannot excuse. F fires
|
|
1344
|
+
// on a completion CLAIM, and a turn waiting on a subagent has not
|
|
1345
|
+
// finished — so its closing is not the claim F is about. Same slot,
|
|
1346
|
+
// opposite trigger, opposite treatment of `dispatchOpen`.
|
|
1347
|
+
dispatchOpen ? null : detectUntestedChange(lastAssistant, toolCalls),
|
|
1132
1348
|
]) {
|
|
1133
1349
|
if (f) findings.push(f);
|
|
1134
1350
|
}
|
|
@@ -1139,6 +1355,7 @@ export function main(): number {
|
|
|
1139
1355
|
sessionKey,
|
|
1140
1356
|
turnOrdinal,
|
|
1141
1357
|
findings.map((f) => f.detector),
|
|
1358
|
+
promptId,
|
|
1142
1359
|
);
|
|
1143
1360
|
|
|
1144
1361
|
const lines = findings.map(
|
|
@@ -1147,8 +1364,9 @@ export function main(): number {
|
|
|
1147
1364
|
process.stderr.write(
|
|
1148
1365
|
`turn-end-gate: REFUSED — this turn is not finished.\n${lines.join('\n')}\n` +
|
|
1149
1366
|
' Do the promised work now, correct the language, run the ' +
|
|
1150
|
-
'verification the edit needs,
|
|
1151
|
-
'it — then end
|
|
1367
|
+
'verification the edit needs, read the CI verdict before claiming ' +
|
|
1368
|
+
'it, or re-present the options block this turn dropped — then end ' +
|
|
1369
|
+
'the turn.\n' +
|
|
1152
1370
|
' This turn will not be refused a second time.\n',
|
|
1153
1371
|
);
|
|
1154
1372
|
return EXIT_BLOCK;
|
|
@@ -132,12 +132,17 @@ export function isUiWrite(event: ToolEvent): boolean {
|
|
|
132
132
|
* `path_prefix: .claude/design-system/`. Reading one is the agent reaching
|
|
133
133
|
* rung 1 of the data-basis ladder before it writes.
|
|
134
134
|
*
|
|
135
|
-
* A SHARED PREDICATE, NOT A DECISION INPUT
|
|
136
|
-
* it
|
|
137
|
-
* that
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
* and
|
|
135
|
+
* A SHARED PREDICATE, AND A RECORDED ONE — NOT A DECISION INPUT. `decide`
|
|
136
|
+
* evaluates it on every event and latches the result into `SessionState`, but
|
|
137
|
+
* no branch reads that latch: every `warn` value is what it was before, so the
|
|
138
|
+
* nudge's behaviour is unchanged and the phase's `nothing behavioural` still
|
|
139
|
+
* holds. Recording it closes the gap the predicate shipped with — it was
|
|
140
|
+
* exported here and consumed only by `report_consultation_rate`, so a live
|
|
141
|
+
* session's own state said nothing about whether the artifact had been read.
|
|
142
|
+
* The concern is default-OFF, so this changes nothing for a consumer and makes
|
|
143
|
+
* the shadow record honest (`road-to-design-intent-conformance` 2.6). Keeping
|
|
144
|
+
* the predicate beside `isUiWrite` / `isConsultation` is what stops the
|
|
145
|
+
* analyzer and the nudge from classifying the same event differently.
|
|
141
146
|
*
|
|
142
147
|
* THIS IS A COPY OF THE RULE'S TRIGGERS, NOT A READ OF THEM — same honesty
|
|
143
148
|
* boundary the header states for `ui_surface.ts`: nothing here parses
|
|
@@ -162,12 +167,27 @@ export function isUiWrite(event: ToolEvent): boolean {
|
|
|
162
167
|
export function isArtifactRead(event: ToolEvent): boolean {
|
|
163
168
|
if (event.isWrite || !event.file) return false;
|
|
164
169
|
const normalized = event.file.replace(/\\/g, '/').toLowerCase();
|
|
165
|
-
return
|
|
170
|
+
return (
|
|
171
|
+
normalized.endsWith('design.html') ||
|
|
172
|
+
// The Claude Design canvas artboard. NOT covered by the line above:
|
|
173
|
+
// `ToDo.dc.html` does not end in `design.html`, which is exactly why
|
|
174
|
+
// the rule needed a second file pattern (2.5) and why the drift guard
|
|
175
|
+
// below reds when one is added here without the other.
|
|
176
|
+
normalized.endsWith('.dc.html') ||
|
|
177
|
+
normalized.includes('.claude/design-system/')
|
|
178
|
+
);
|
|
166
179
|
}
|
|
167
180
|
|
|
168
181
|
export interface SessionState {
|
|
169
182
|
consulted: boolean;
|
|
170
183
|
nudges: number;
|
|
184
|
+
/**
|
|
185
|
+
* Latched once a provided design artifact has been READ this session.
|
|
186
|
+
* Shadow-only: nothing branches on it. It exists so the session's own
|
|
187
|
+
* record can answer "did this agent open the handover before writing UI",
|
|
188
|
+
* which until 2.6 only a transcript analyzer could answer after the fact.
|
|
189
|
+
*/
|
|
190
|
+
artifactRead: boolean;
|
|
171
191
|
}
|
|
172
192
|
|
|
173
193
|
function stateFile(root: string): string {
|
|
@@ -182,12 +202,17 @@ export function readState(root: string, session: string): SessionState {
|
|
|
182
202
|
>;
|
|
183
203
|
const entry = all[session];
|
|
184
204
|
if (entry && typeof entry.consulted === 'boolean' && typeof entry.nudges === 'number') {
|
|
185
|
-
|
|
205
|
+
// `artifactRead` arrived after the file shape did, so a state file
|
|
206
|
+
// written by an older build carries the two older fields and not
|
|
207
|
+
// this one. Default it rather than rejecting the entry: dropping a
|
|
208
|
+
// valid latch to gain a boolean would lose the `consulted` flag and
|
|
209
|
+
// re-nudge a session that had already consulted.
|
|
210
|
+
return { ...entry, artifactRead: entry.artifactRead === true };
|
|
186
211
|
}
|
|
187
212
|
} catch {
|
|
188
213
|
/* fresh session */
|
|
189
214
|
}
|
|
190
|
-
return { consulted: false, nudges: 0 };
|
|
215
|
+
return { consulted: false, nudges: 0, artifactRead: false };
|
|
191
216
|
}
|
|
192
217
|
|
|
193
218
|
/** Sessions retained in the state file; oldest entries drop past this. */
|
|
@@ -236,13 +261,21 @@ export function decide(
|
|
|
236
261
|
event: ToolEvent,
|
|
237
262
|
state: SessionState,
|
|
238
263
|
): { state: SessionState; warn: boolean } {
|
|
264
|
+
// Evaluated FIRST and independently of every branch below, because
|
|
265
|
+
// `isArtifactRead` and `isConsultation` are NOT disjoint — a read of
|
|
266
|
+
// `src/skills/design-review/references/design.html` satisfies both. Folding
|
|
267
|
+
// it into one of the branches would silently drop such an event from
|
|
268
|
+
// whichever classification lost the race, which is the failure
|
|
269
|
+
// `isArtifactRead`'s own header warns callers about. Latching, never
|
|
270
|
+
// clearing: the question is "was it read at any point this session".
|
|
271
|
+
const artifactRead = state.artifactRead || isArtifactRead(event);
|
|
239
272
|
if (isConsultation(event)) {
|
|
240
|
-
return { state: { ...state, consulted: true }, warn: false };
|
|
273
|
+
return { state: { ...state, artifactRead, consulted: true }, warn: false };
|
|
241
274
|
}
|
|
242
|
-
if (!isUiWrite(event)) return { state, warn: false };
|
|
243
|
-
if (state.consulted) return { state, warn: false };
|
|
244
|
-
if (state.nudges >= MAX_NUDGES) return { state, warn: false };
|
|
245
|
-
return { state: { ...state, nudges: state.nudges + 1 }, warn: true };
|
|
275
|
+
if (!isUiWrite(event)) return { state: { ...state, artifactRead }, warn: false };
|
|
276
|
+
if (state.consulted) return { state: { ...state, artifactRead }, warn: false };
|
|
277
|
+
if (state.nudges >= MAX_NUDGES) return { state: { ...state, artifactRead }, warn: false };
|
|
278
|
+
return { state: { ...state, artifactRead, nudges: state.nudges + 1 }, warn: true };
|
|
246
279
|
}
|
|
247
280
|
|
|
248
281
|
/**
|
|
@@ -256,7 +289,11 @@ export function decide(
|
|
|
256
289
|
* but the guard stays enumerated and this note stays with it.
|
|
257
290
|
*/
|
|
258
291
|
export function stateChanged(before: SessionState, after: SessionState): boolean {
|
|
259
|
-
return
|
|
292
|
+
return (
|
|
293
|
+
before.consulted !== after.consulted ||
|
|
294
|
+
before.nudges !== after.nudges ||
|
|
295
|
+
before.artifactRead !== after.artifactRead
|
|
296
|
+
);
|
|
260
297
|
}
|
|
261
298
|
|
|
262
299
|
export function nudgeReason(file: string): string {
|
|
@@ -40,6 +40,7 @@ import * as hooks_status from "./hooks_status.js";
|
|
|
40
40
|
import {
|
|
41
41
|
DETECTOR_IDS,
|
|
42
42
|
collectRefusalStats,
|
|
43
|
+
emptyCounts,
|
|
43
44
|
readInstallBoundary,
|
|
44
45
|
type InstallBoundary,
|
|
45
46
|
type RefusalStats,
|
|
@@ -268,7 +269,9 @@ export function collect(
|
|
|
268
269
|
turn_end_refusals = {
|
|
269
270
|
sessionsWithRefusals: 0,
|
|
270
271
|
total: 0,
|
|
271
|
-
|
|
272
|
+
// Derived, never a literal: a fifth detector made the old four-key object
|
|
273
|
+
// a type error here and a silent `NaN` in the aggregator it mirrors.
|
|
274
|
+
byDetector: emptyCounts(),
|
|
272
275
|
byPeriod: [],
|
|
273
276
|
legacyRecords: 0,
|
|
274
277
|
unversionedRecords: 0,
|