@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
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Value reconciliation between a provided design artifact and a project's own
|
|
3
|
+
* tokens — the MEASUREMENT half, shipped; the BEHAVIOURAL half, deliberately
|
|
4
|
+
* not.
|
|
5
|
+
*
|
|
6
|
+
* WHAT THE COUNCIL DECIDED, and why this module is shaped this way.
|
|
7
|
+
*
|
|
8
|
+
* `road-to-design-intent-conformance` put `blocker: approximation-tolerance` to
|
|
9
|
+
* the AI council (anthropic + openai, 2/2, 2026-09-09). Neither member accepted
|
|
10
|
+
* any of the three options as written. Both split step 3.2 the same way: build
|
|
11
|
+
* the metric, the collection and the reporting now; ship **no tolerance
|
|
12
|
+
* constant at all**; defer the behaviour that would let a value change without
|
|
13
|
+
* being asked about.
|
|
14
|
+
*
|
|
15
|
+
* The argument that decided it, and it is the one to re-read before adding a
|
|
16
|
+
* number here: *"a number in a config file, even flagged unmeasured, shapes
|
|
17
|
+
* behaviour and creates path dependency."* Zero of seven design-to-code
|
|
18
|
+
* benchmarks in the evidence set score token conformance, so a shipped
|
|
19
|
+
* threshold would be a guess acquiring the authority of a default. Both
|
|
20
|
+
* `design.tolerance.*` keys therefore ship `null`, and `null` means **preserve
|
|
21
|
+
* and report**, never "reconcile freely".
|
|
22
|
+
*
|
|
23
|
+
* THE METRIC IS A PREREQUISITE the roadmap never named.
|
|
24
|
+
*
|
|
25
|
+
* The council added it: no colour tolerance is meaningful before the distance
|
|
26
|
+
* METHOD is fixed, because RGB Euclidean, ΔE LAB, CIEDE2000 and OKLab/ΔEOK give
|
|
27
|
+
* different numbers for the same pair. `openai` rejected the round's proposed
|
|
28
|
+
* `±5 per RGB channel` on exactly this ground — RGB channel distance is not
|
|
29
|
+
* perceptually uniform, so "likely imperceptible" is an unsupported conclusion.
|
|
30
|
+
*
|
|
31
|
+
* This module fixes the method as **OKLab ΔEOK** (a plain Euclidean distance in
|
|
32
|
+
* OKLab, the metric OKLab was designed to make meaningful) and leaves the
|
|
33
|
+
* threshold empty. Method without threshold is the honest state: the distance
|
|
34
|
+
* on every row is a real, comparable number, and nothing yet says which
|
|
35
|
+
* distances are small enough to act on.
|
|
36
|
+
*
|
|
37
|
+
* LENGTH CARRIES NO SHIPPED NUMBER either.
|
|
38
|
+
*
|
|
39
|
+
* Primer's spacing plugin widens each token's accepted set by ±1px and
|
|
40
|
+
* autofixes. That is the one real measurement in the evidence set and it is
|
|
41
|
+
* recorded as an **externally observed candidate**, not adopted:
|
|
42
|
+
* `OBSERVED_LENGTH_CANDIDATE_PX` exists to be cited, and no code path reads it
|
|
43
|
+
* as a threshold. The round's other proposal, `max(1px, 2%)`, was rejected for
|
|
44
|
+
* growing steadily more permissive at large dimensions with no evidence that
|
|
45
|
+
* this is wanted.
|
|
46
|
+
*
|
|
47
|
+
* EVERY ROW CARRIES ITS DISTANCE, even when the value is preserved.
|
|
48
|
+
*
|
|
49
|
+
* That is the step's own verify clause and it is the property that makes the
|
|
50
|
+
* deferred half decidable later: a shadow window over rows that report
|
|
51
|
+
* distances can produce a distribution, where a window over rows that report
|
|
52
|
+
* only "kept" or "changed" cannot.
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
/** Fixed method. See the header: the threshold is absent, the metric is not. */
|
|
56
|
+
export const COLOR_DISTANCE_METRIC = 'oklab-deltaEOK' as const;
|
|
57
|
+
/** Fixed method for lengths: absolute difference in CSS pixels. */
|
|
58
|
+
export const LENGTH_DISTANCE_METRIC = 'abs-px' as const;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* GitHub Primer's spacing plugin widens each token's accepted set by ±1px.
|
|
62
|
+
* Recorded as an externally observed candidate for a future threshold; **no
|
|
63
|
+
* code path reads this as one**, and a test pins that it never becomes the
|
|
64
|
+
* shipped default without a decision.
|
|
65
|
+
*/
|
|
66
|
+
export const OBSERVED_LENGTH_CANDIDATE_PX = 1;
|
|
67
|
+
|
|
68
|
+
export interface ToleranceConfig {
|
|
69
|
+
/** Master switch. Ships `false`; `blocker: fidelity-default-flip` → (a). */
|
|
70
|
+
enabled: boolean;
|
|
71
|
+
/** ΔEOK below which a colour may be reconciled. `null` ships. */
|
|
72
|
+
color: number | null;
|
|
73
|
+
/** Pixels below which a length may be reconciled. `null` ships. */
|
|
74
|
+
length: number | null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** The shipped configuration. Both thresholds absent, mechanism off. */
|
|
78
|
+
export const SHIPPED_TOLERANCE: ToleranceConfig = { enabled: false, color: null, length: null };
|
|
79
|
+
|
|
80
|
+
export type ReconcileOutcome =
|
|
81
|
+
/** Inside tolerance: the project token wins, and the change is reported. */
|
|
82
|
+
| 'reconciled'
|
|
83
|
+
/** Outside tolerance: the artifact's value is preserved, gap reported. */
|
|
84
|
+
| 'preserved-outside-tolerance'
|
|
85
|
+
/** The mechanism is off, or no threshold is configured: preserve, report. */
|
|
86
|
+
| 'preserved-mechanism-off'
|
|
87
|
+
/** No project token to compare against: nothing to reconcile onto. */
|
|
88
|
+
| 'no-candidate';
|
|
89
|
+
|
|
90
|
+
export interface TokenCandidate {
|
|
91
|
+
name: string;
|
|
92
|
+
value: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface ValueRow {
|
|
96
|
+
/** The artifact's own value, verbatim. */
|
|
97
|
+
artifact: string;
|
|
98
|
+
/** Nearest project token, or null when the project has none of this kind. */
|
|
99
|
+
nearest: TokenCandidate | null;
|
|
100
|
+
/** Distance to `nearest` in the metric named below. Null iff no candidate. */
|
|
101
|
+
distance: number | null;
|
|
102
|
+
metric: typeof COLOR_DISTANCE_METRIC | typeof LENGTH_DISTANCE_METRIC | null;
|
|
103
|
+
/** The value actually written. Equals `artifact` unless reconciled. */
|
|
104
|
+
resolved: string;
|
|
105
|
+
outcome: ReconcileOutcome;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// ------------------------------------------------------------------ colour
|
|
109
|
+
|
|
110
|
+
interface Rgb {
|
|
111
|
+
r: number;
|
|
112
|
+
g: number;
|
|
113
|
+
b: number;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* `#rgb` / `#rrggbb` → 0–1 channels, or null when unparseable.
|
|
118
|
+
*
|
|
119
|
+
* An 8-digit `#rrggbbaa` returns NULL rather than its opaque prefix. ΔEOK is a
|
|
120
|
+
* three-channel metric and has nothing to say about alpha, so truncating made
|
|
121
|
+
* `#ff000080` and `#ff0000` measure distance 0 — "identical" for two values a
|
|
122
|
+
* designer chose to differ. Found by a blind review. Null is the honest answer:
|
|
123
|
+
* the row is reported as unmeasured, which is what it is.
|
|
124
|
+
*/
|
|
125
|
+
export function parseHex(value: string): Rgb | null {
|
|
126
|
+
const m = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.exec(value.trim());
|
|
127
|
+
if (!m) return null;
|
|
128
|
+
let hex = m[1] as string;
|
|
129
|
+
if (hex.length === 3) {
|
|
130
|
+
hex = hex
|
|
131
|
+
.split('')
|
|
132
|
+
.map((c) => c + c)
|
|
133
|
+
.join('');
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
r: parseInt(hex.slice(0, 2), 16) / 255,
|
|
137
|
+
g: parseInt(hex.slice(2, 4), 16) / 255,
|
|
138
|
+
b: parseInt(hex.slice(4, 6), 16) / 255,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** sRGB transfer function, inverted — required before the OKLab matrices. */
|
|
143
|
+
function toLinear(c: number): number {
|
|
144
|
+
return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** sRGB → OKLab (Björn Ottosson's published matrices). */
|
|
148
|
+
export function srgbToOklab(rgb: Rgb): { L: number; a: number; b: number } {
|
|
149
|
+
const r = toLinear(rgb.r);
|
|
150
|
+
const g = toLinear(rgb.g);
|
|
151
|
+
const b = toLinear(rgb.b);
|
|
152
|
+
const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
|
|
153
|
+
const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
|
|
154
|
+
const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
|
|
155
|
+
return {
|
|
156
|
+
L: 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,
|
|
157
|
+
a: 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,
|
|
158
|
+
b: 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* ΔEOK — Euclidean distance in OKLab. Null when either value is not a hex
|
|
164
|
+
* colour this module can parse; an unparseable value is reported as unmeasured
|
|
165
|
+
* rather than assigned a distance of zero, which would read as "identical".
|
|
166
|
+
*/
|
|
167
|
+
export function deltaEOK(a: string, b: string): number | null {
|
|
168
|
+
const ra = parseHex(a);
|
|
169
|
+
const rb = parseHex(b);
|
|
170
|
+
if (!ra || !rb) return null;
|
|
171
|
+
const la = srgbToOklab(ra);
|
|
172
|
+
const lb = srgbToOklab(rb);
|
|
173
|
+
return Math.sqrt((la.L - lb.L) ** 2 + (la.a - lb.a) ** 2 + (la.b - lb.b) ** 2);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// ------------------------------------------------------------------ length
|
|
177
|
+
|
|
178
|
+
/** `16px` / `1rem` / `0.5rem` → pixels at a 16px root, or null. */
|
|
179
|
+
export function parseLengthPx(value: string, rootPx = 16): number | null {
|
|
180
|
+
const m = /^(-?\d*\.?\d+)(px|rem|em)$/.exec(value.trim());
|
|
181
|
+
if (!m) return null;
|
|
182
|
+
const n = Number(m[1]);
|
|
183
|
+
if (!Number.isFinite(n)) return null;
|
|
184
|
+
return m[2] === 'px' ? n : n * rootPx;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Absolute pixel difference, or null when either side is unparseable. */
|
|
188
|
+
export function lengthDistancePx(a: string, b: string, rootPx = 16): number | null {
|
|
189
|
+
const pa = parseLengthPx(a, rootPx);
|
|
190
|
+
const pb = parseLengthPx(b, rootPx);
|
|
191
|
+
if (pa === null || pb === null) return null;
|
|
192
|
+
return Math.abs(pa - pb);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// ------------------------------------------------------------- reconcile
|
|
196
|
+
|
|
197
|
+
export type ValueKind = 'color' | 'length';
|
|
198
|
+
|
|
199
|
+
function distanceFor(kind: ValueKind, a: string, b: string): number | null {
|
|
200
|
+
return kind === 'color' ? deltaEOK(a, b) : lengthDistancePx(a, b);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** Nearest candidate by the kind's own metric. Ties break on first-listed. */
|
|
204
|
+
export function nearestToken(
|
|
205
|
+
kind: ValueKind,
|
|
206
|
+
artifact: string,
|
|
207
|
+
candidates: readonly TokenCandidate[],
|
|
208
|
+
): { candidate: TokenCandidate; distance: number } | null {
|
|
209
|
+
let best: { candidate: TokenCandidate; distance: number } | null = null;
|
|
210
|
+
for (const candidate of candidates) {
|
|
211
|
+
const d = distanceFor(kind, artifact, candidate.value);
|
|
212
|
+
if (d === null) continue;
|
|
213
|
+
if (best === null || d < best.distance) best = { candidate, distance: d };
|
|
214
|
+
}
|
|
215
|
+
return best;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Reconcile one artifact value against the project's tokens.
|
|
220
|
+
*
|
|
221
|
+
* **The distance is computed and reported on every path**, including every path
|
|
222
|
+
* that preserves the artifact's value — that is the step's verify clause, and
|
|
223
|
+
* it is what makes a later shadow distribution possible.
|
|
224
|
+
*/
|
|
225
|
+
export function reconcileValue(
|
|
226
|
+
kind: ValueKind,
|
|
227
|
+
artifact: string,
|
|
228
|
+
candidates: readonly TokenCandidate[],
|
|
229
|
+
config: ToleranceConfig = SHIPPED_TOLERANCE,
|
|
230
|
+
): ValueRow {
|
|
231
|
+
const metric = kind === 'color' ? COLOR_DISTANCE_METRIC : LENGTH_DISTANCE_METRIC;
|
|
232
|
+
const best = nearestToken(kind, artifact, candidates);
|
|
233
|
+
|
|
234
|
+
if (best === null) {
|
|
235
|
+
return {
|
|
236
|
+
artifact,
|
|
237
|
+
nearest: null,
|
|
238
|
+
distance: null,
|
|
239
|
+
metric: null,
|
|
240
|
+
resolved: artifact,
|
|
241
|
+
outcome: 'no-candidate',
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const base = {
|
|
246
|
+
artifact,
|
|
247
|
+
nearest: best.candidate,
|
|
248
|
+
distance: best.distance,
|
|
249
|
+
metric,
|
|
250
|
+
} as const;
|
|
251
|
+
|
|
252
|
+
const threshold = kind === 'color' ? config.color : config.length;
|
|
253
|
+
|
|
254
|
+
// Off, or no threshold configured. These are ONE outcome on purpose: a
|
|
255
|
+
// mechanism with no threshold cannot act, so reporting it as anything but
|
|
256
|
+
// "off" would imply a decision nobody made.
|
|
257
|
+
if (!config.enabled || threshold === null) {
|
|
258
|
+
return { ...base, resolved: artifact, outcome: 'preserved-mechanism-off' };
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (best.distance <= threshold) {
|
|
262
|
+
return { ...base, resolved: best.candidate.value, outcome: 'reconciled' };
|
|
263
|
+
}
|
|
264
|
+
return { ...base, resolved: artifact, outcome: 'preserved-outside-tolerance' };
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** One human-readable row. Always names the distance, never only the verdict. */
|
|
268
|
+
export function formatRow(row: ValueRow): string {
|
|
269
|
+
if (row.nearest === null || row.distance === null) {
|
|
270
|
+
return `${row.artifact} → kept (no project token of this kind to compare against)`;
|
|
271
|
+
}
|
|
272
|
+
const d = `${row.metric ?? '?'} ${row.distance.toFixed(4)}`;
|
|
273
|
+
switch (row.outcome) {
|
|
274
|
+
case 'reconciled':
|
|
275
|
+
return `${row.artifact} → ${row.nearest.name} (${row.nearest.value}); reconciled, distance ${d}`;
|
|
276
|
+
case 'preserved-outside-tolerance':
|
|
277
|
+
return `${row.artifact} → kept; nearest ${row.nearest.name} (${row.nearest.value}) is outside tolerance, distance ${d}`;
|
|
278
|
+
default:
|
|
279
|
+
return `${row.artifact} → kept; nearest ${row.nearest.name} (${row.nearest.value}), distance ${d} (reconciliation off)`;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `docs/guidelines/` → `dist/agent-src/guidelines/` projection lane.
|
|
3
|
+
*
|
|
4
|
+
* Why this exists at all: the projected rules declare `routes_to:
|
|
5
|
+
* guideline:<slug>` against **22 distinct targets** and link
|
|
6
|
+
* `../../docs/guidelines/<slug>.md`, and until this lane shipped
|
|
7
|
+
* `dist/agent-src/` carried no `guidelines/` directory — so every one of those
|
|
8
|
+
* routes was declared and dead in a consumer install. (The figure is the gate's own reading. An
|
|
9
|
+
* earlier draft here said "31 rules", which reproduced on nothing: `grep -l`
|
|
10
|
+
* returns 22 in both trees. A blind review checked it; the number is now the
|
|
11
|
+
* one `check_projected_rule_routes` prints.) `AUGMENT_SYMLINK_DIRS`
|
|
12
|
+
* in `condense.ts` has listed `guidelines` since before the lane existed; the
|
|
13
|
+
* symlink simply had nothing to point at.
|
|
14
|
+
*
|
|
15
|
+
* Shape, and why it is a lane rather than a source root: the multi-root
|
|
16
|
+
* resolver in `agent_src.ts` derives an artefact's *identity* from
|
|
17
|
+
* `_root_specs()`, and everything that scans the artefact estate — the
|
|
18
|
+
* discovery manifest, the skill linter, the size and count ratchets — walks
|
|
19
|
+
* that same list. Adding `docs/guidelines` there would reclassify 119
|
|
20
|
+
* guidelines as estate artefacts and move every one of those numbers. So the
|
|
21
|
+
* lane is appended only where the *projection* reads (`iter_all_sources` and
|
|
22
|
+
* `resolve_logical`), exactly as `_iter_domains_commands` already is, and the
|
|
23
|
+
* estate view is left alone.
|
|
24
|
+
*
|
|
25
|
+
* Identity: `docs/guidelines/<subpath>.md` is logical `guidelines/<subpath>.md`
|
|
26
|
+
* — one directory deep in the projection, the same depth as `rules/` and
|
|
27
|
+
* `skills/`, which is what makes the existing `../guidelines/…` rewrite in
|
|
28
|
+
* `condense.ts::_rewrite_body_links` resolve from a projected rule.
|
|
29
|
+
*/
|
|
30
|
+
import * as fs from 'node:fs';
|
|
31
|
+
import * as path from 'node:path';
|
|
32
|
+
|
|
33
|
+
/** Logical-path prefix every guideline is projected under. */
|
|
34
|
+
export const GUIDELINES_LOGICAL_PREFIX = 'guidelines/';
|
|
35
|
+
|
|
36
|
+
/** Physical source directory, relative to the repo root. */
|
|
37
|
+
export const GUIDELINES_SOURCE_REL = path.join('docs', 'guidelines');
|
|
38
|
+
|
|
39
|
+
function _isDir(p: string): boolean {
|
|
40
|
+
try {
|
|
41
|
+
return fs.statSync(p).isDirectory();
|
|
42
|
+
} catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function _isFile(p: string): boolean {
|
|
48
|
+
try {
|
|
49
|
+
return fs.statSync(p).isFile();
|
|
50
|
+
} catch {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Recursive, name-sorted at every level so the walk order is deterministic. */
|
|
56
|
+
function* _walkSorted(dir: string): Generator<string> {
|
|
57
|
+
let entries: string[];
|
|
58
|
+
try {
|
|
59
|
+
entries = fs.readdirSync(dir).sort();
|
|
60
|
+
} catch {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
for (const name of entries) {
|
|
64
|
+
const full = path.join(dir, name);
|
|
65
|
+
if (_isDir(full)) {
|
|
66
|
+
yield* _walkSorted(full);
|
|
67
|
+
} else if (_isFile(full)) {
|
|
68
|
+
yield full;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Yield `[physical_path, logical_relpath]` for every file under
|
|
75
|
+
* `<root>/docs/guidelines/`. Deterministic order; yields nothing when the
|
|
76
|
+
* directory is absent, which is the normal state of a consumer checkout.
|
|
77
|
+
*/
|
|
78
|
+
export function* iter_guidelines(root: string): Generator<[string, string]> {
|
|
79
|
+
const base = path.join(root, GUIDELINES_SOURCE_REL);
|
|
80
|
+
if (!_isDir(base)) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
for (const p of _walkSorted(base)) {
|
|
84
|
+
const rel = path.relative(base, p).split(path.sep).join('/');
|
|
85
|
+
yield [p, GUIDELINES_LOGICAL_PREFIX + rel];
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Physical path backing a logical `guidelines/<subpath>`, or `null` when the
|
|
91
|
+
* logical path is not a guideline or the file does not exist.
|
|
92
|
+
*/
|
|
93
|
+
export function resolve_guideline(root: string, logical_rel: string): string | null {
|
|
94
|
+
const rel = logical_rel.replaceAll('\\', '/').replace(/^\/+/, '');
|
|
95
|
+
if (!rel.startsWith(GUIDELINES_LOGICAL_PREFIX)) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
const suffix = rel.slice(GUIDELINES_LOGICAL_PREFIX.length);
|
|
99
|
+
if (suffix.length === 0 || suffix.split('/').includes('..')) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
const candidate = path.join(root, GUIDELINES_SOURCE_REL, suffix);
|
|
103
|
+
return _isFile(candidate) ? candidate : null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Rewrite a projected body's relative `.md` links onto the projection.
|
|
108
|
+
*
|
|
109
|
+
* Lives here rather than in `condense.ts` for two reasons, and the second is
|
|
110
|
+
* the load-bearing one. It is this lane's own subject: every rule it applies is
|
|
111
|
+
* a statement about which source trees project where, which is what this module
|
|
112
|
+
* exists to know. And `condense.ts` sits ~1,200 lines past the 1,500-line
|
|
113
|
+
* ceiling `check_source_size_budget` ratchets, so every line there costs one
|
|
114
|
+
* unit of excess while every line here costs zero — the doctrine that file's
|
|
115
|
+
* own baseline note prescribes for exactly this case.
|
|
116
|
+
*
|
|
117
|
+
* `prefix` is the caller's depth prefix (`../` per level below
|
|
118
|
+
* `dist/agent-src/`), so a rule at depth 1 and a guideline at depth 2 both
|
|
119
|
+
* resolve.
|
|
120
|
+
*/
|
|
121
|
+
export function rewriteProjectedBodyLinks(body: string, prefix: string): string {
|
|
122
|
+
return body
|
|
123
|
+
.replace(BODY_DOCS_RE, (_m, t: string) => prefix + t.replace(/^docs\/guidelines\//, 'guidelines/'))
|
|
124
|
+
.replace(BODY_SRC_FLAT_RE, (_m, t: string) => prefix + t)
|
|
125
|
+
.replace(BODY_SRC_AGENT_RE, (_m, t: string) => prefix + t);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* `docs/guidelines/` is projected and loses its `docs/` segment;
|
|
130
|
+
* `docs/contracts/` is NOT projected and keeps its path unchanged.
|
|
131
|
+
*
|
|
132
|
+
* One-or-more `../` rather than a literal `../../`: the dominant convention in
|
|
133
|
+
* `src/rules/` is a single `../` — 26 sites across 18 rules — so a literal
|
|
134
|
+
* two-level pattern matched only the minority spelling.
|
|
135
|
+
*/
|
|
136
|
+
const BODY_DOCS_RE = /(?:\.\.\/)+(docs\/(?:guidelines|contracts)\/[^)\s]+\.md)/g;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Source trees that project into `dist/agent-src/`, losing their `src/` (and
|
|
140
|
+
* `agent-src/`) segment.
|
|
141
|
+
*
|
|
142
|
+
* Until the guidelines lane shipped, no PROJECTED file linked into `src/`, so
|
|
143
|
+
* this rewrite had nothing to do and did not exist. A guideline does it 209
|
|
144
|
+
* times — a blind review measured 253 of 268 links under
|
|
145
|
+
* `dist/agent-src/guidelines/` resolving to nothing before this was added.
|
|
146
|
+
*
|
|
147
|
+
* TWO patterns, not one, and the difference is load-bearing. `rules` and
|
|
148
|
+
* `skills` are FLAT library roots directly under `src/`; `commands`,
|
|
149
|
+
* `contexts`, `personas`, `user-types`, `templates` and `scripts` exist only
|
|
150
|
+
* under `src/agent-src/`. A single pattern with an optional `agent-src/` group
|
|
151
|
+
* conflates them, and the conflation is not theoretical: it folded
|
|
152
|
+
* `../../src/scripts/media/lib/adapter-contract.md` — a real link in
|
|
153
|
+
* `provider-lifecycle-discipline.md` — onto `../scripts/…`, which resolves to
|
|
154
|
+
* `dist/agent-src/scripts/`, a projection of `src/agent-src/scripts/` and a
|
|
155
|
+
* different tree entirely. `check_condensed_paths` caught it; the first version
|
|
156
|
+
* of this regex turned one resolving link into a broken one.
|
|
157
|
+
*
|
|
158
|
+
* `src/domains` is deliberately absent from both: a domains command projects to
|
|
159
|
+
* `commands/<subpath>.md`, which is a re-shaping rather than a prefix strip,
|
|
160
|
+
* and guessing it would produce a link that looks right and is wrong.
|
|
161
|
+
*/
|
|
162
|
+
const BODY_SRC_FLAT_RE = /(?:\.\.\/)+src\/((?:rules|skills)\/[^)\s]+\.md)/g;
|
|
163
|
+
const BODY_SRC_AGENT_RE =
|
|
164
|
+
/(?:\.\.\/)+src\/agent-src\/((?:commands|contexts|personas|user-types|templates|scripts)\/[^)\s]+\.md)/g;
|
|
@@ -110,3 +110,88 @@ export function leanProjectionModeRaw(root: string): string {
|
|
|
110
110
|
}
|
|
111
111
|
return '';
|
|
112
112
|
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Raw `lean_projection.hosts` list out of `.agent-settings.yml`, or `[]`.
|
|
116
|
+
*
|
|
117
|
+
* Same indentation-shaped discipline as `leanProjectionModeRaw` above and for
|
|
118
|
+
* the same reason — a hook must never fail a tool call because a YAML parser
|
|
119
|
+
* could not load — extended to the three list shapes a human writes:
|
|
120
|
+
*
|
|
121
|
+
* lean_projection:
|
|
122
|
+
* hosts: [claude-code] # inline
|
|
123
|
+
* lean_projection:
|
|
124
|
+
* hosts: # block, indented under the key
|
|
125
|
+
* - claude-code
|
|
126
|
+
* lean_projection:
|
|
127
|
+
* hosts: # block, at the key's own indent
|
|
128
|
+
* - claude-code
|
|
129
|
+
*
|
|
130
|
+
* All three are legal YAML and `js-yaml` loads them identically; the third was
|
|
131
|
+
* read as `[]` until 2026-09-08 (R2 finding 2) and is covered by three fixtures
|
|
132
|
+
* in `tests/scripts/lean_projection_hosts.test.ts`.
|
|
133
|
+
*
|
|
134
|
+
* Interpretation is NOT done here. `[]` means "nothing was written", and
|
|
135
|
+
* `_lib/lean_projection_mode.ts::resolveLeanProjectionHosts` decides that this
|
|
136
|
+
* means the default rather than "no host" — keeping that decision in one place
|
|
137
|
+
* is what stops the projector and the delivery concern from disagreeing, which
|
|
138
|
+
* is the whole reason the mode reader is split this way.
|
|
139
|
+
*/
|
|
140
|
+
export function leanProjectionHostsRaw(root: string): string[] {
|
|
141
|
+
const file = path.join(root, SETTINGS_FILE);
|
|
142
|
+
let text: string;
|
|
143
|
+
try {
|
|
144
|
+
if (!fs.statSync(file).isFile()) return [];
|
|
145
|
+
text = fs.readFileSync(file, 'utf-8');
|
|
146
|
+
} catch {
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
const strip = (s: string): string => s.trim().replace(/^["']|["']$/g, '');
|
|
150
|
+
let inSection = false;
|
|
151
|
+
let inBlock = false;
|
|
152
|
+
let blockIndent = -1;
|
|
153
|
+
const out: string[] = [];
|
|
154
|
+
for (const raw of text.split(/\r\n|\r|\n/)) {
|
|
155
|
+
const line = raw.replace(/\s+$/, '');
|
|
156
|
+
if (!line || line.replace(/^\s+/, '').startsWith('#')) continue;
|
|
157
|
+
if (!(line.startsWith(' ') || line.startsWith('\t'))) {
|
|
158
|
+
inSection = /^lean_projection\s*:\s*$/.test(line);
|
|
159
|
+
inBlock = false;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (!inSection) continue;
|
|
163
|
+
const indent = (/^\s*/.exec(line) as RegExpExecArray)[0].length;
|
|
164
|
+
if (inBlock) {
|
|
165
|
+
const item = /^\s*-\s*(\S.*)$/.exec(line);
|
|
166
|
+
// `>=`, not `>`: YAML lets a block sequence sit at its KEY's own
|
|
167
|
+
// indent, and `js-yaml` — the parser `condense` uses on this same
|
|
168
|
+
// file — loads that shape identically to the deeper-indented one.
|
|
169
|
+
// With `>` the same-indent form parsed as `[]`, which
|
|
170
|
+
// `resolveLeanProjectionHosts` reads as "nothing was written" and
|
|
171
|
+
// answers with the default `[claude-code]` while the projector
|
|
172
|
+
// thins whatever the file actually says. Two readers disagreeing
|
|
173
|
+
// about the delivery-host set is the one failure this split exists
|
|
174
|
+
// to prevent (R2 finding 2). A SHALLOWER item still ends the block:
|
|
175
|
+
// it belongs to a different mapping level, never to `hosts`.
|
|
176
|
+
if (item !== null && indent >= blockIndent) {
|
|
177
|
+
const v = strip(item[1] ?? '');
|
|
178
|
+
if (v !== '') out.push(v);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
inBlock = false;
|
|
182
|
+
}
|
|
183
|
+
const inline = /^\s+hosts\s*:\s*\[([^\]]*)\]\s*$/.exec(line);
|
|
184
|
+
if (inline !== null) {
|
|
185
|
+
for (const part of (inline[1] ?? '').split(',')) {
|
|
186
|
+
const v = strip(part);
|
|
187
|
+
if (v !== '') out.push(v);
|
|
188
|
+
}
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
if (/^\s+hosts\s*:\s*$/.test(line)) {
|
|
192
|
+
inBlock = true;
|
|
193
|
+
blockIndent = indent;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return out;
|
|
197
|
+
}
|
|
@@ -42,3 +42,130 @@ export function writesThinFiles(mode: LeanProjectionMode): boolean {
|
|
|
42
42
|
export function deliversBodies(mode: LeanProjectionMode): boolean {
|
|
43
43
|
return mode === 'delivery';
|
|
44
44
|
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The hosts a thinning mode may actually thin.
|
|
48
|
+
*
|
|
49
|
+
* Deliberately NOT "every host id the package knows". `condense`'s `TOOL_DIRS`
|
|
50
|
+
* writes a per-rule tree for exactly three hosts, so those are the only ids for
|
|
51
|
+
* which `lean_projection.hosts` can mean anything: naming `windsurf` there would
|
|
52
|
+
* be a request to thin a single concatenated file that has no per-rule stub
|
|
53
|
+
* shape, and naming `codex` a request to thin a tree the installer writes and
|
|
54
|
+
* `condense` never touches. Accepting such an id silently would leave the
|
|
55
|
+
* operator believing a host was scoped when nothing reads the entry.
|
|
56
|
+
*/
|
|
57
|
+
export const THINNABLE_HOSTS: readonly string[] = ['claude-code', 'cursor', 'cline'];
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The shipped default host set for a thinning mode.
|
|
61
|
+
*
|
|
62
|
+
* One host, and it is the one host that both binds `pre_tool_use` and honours a
|
|
63
|
+
* deny (`docs/enforcement-by-host.md:18-28`) — i.e. the only host where the
|
|
64
|
+
* delivery concern's verdict is acted on. Widening this is a decision, never a
|
|
65
|
+
* default: see `resolveLeanProjectionHosts`, which never widens implicitly.
|
|
66
|
+
*/
|
|
67
|
+
export const DEFAULT_LEAN_PROJECTION_HOSTS: readonly string[] = ['claude-code'];
|
|
68
|
+
|
|
69
|
+
/** Why an id in a configured `hosts:` list was not kept. */
|
|
70
|
+
export type DroppedHostReason = 'unknown' | 'not-thinnable';
|
|
71
|
+
|
|
72
|
+
export interface LeanProjectionHosts {
|
|
73
|
+
/** The ids that survived, sorted and de-duplicated. */
|
|
74
|
+
readonly hosts: readonly string[];
|
|
75
|
+
/** Ids that were dropped, with the reason — reported, never silently discarded. */
|
|
76
|
+
readonly dropped: ReadonlyArray<{ readonly id: string; readonly reason: DroppedHostReason }>;
|
|
77
|
+
/** True when nothing was configured and the default was applied. */
|
|
78
|
+
readonly usedDefault: boolean;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Resolve a configured `lean_projection.hosts` list.
|
|
83
|
+
*
|
|
84
|
+
* Three properties, each of which is a failure this repository has seen in a
|
|
85
|
+
* neighbouring config surface:
|
|
86
|
+
*
|
|
87
|
+
* 1. **Absent means the default, never "all".** An empty or missing list
|
|
88
|
+
* resolves to `DEFAULT_LEAN_PROJECTION_HOSTS`. A key nobody set must not
|
|
89
|
+
* thin every host — that is D1, the defect this axis exists to repair.
|
|
90
|
+
* 2. **The set never widens implicitly.** Every id is checked against
|
|
91
|
+
* `THINNABLE_HOSTS`; anything else is dropped. A typo cannot enrol a host,
|
|
92
|
+
* and neither can a real host id that has no per-rule tree.
|
|
93
|
+
* 3. **A drop is reported, not swallowed.** The caller gets the ids and the
|
|
94
|
+
* reason so it can print them. Silently ignoring an entry an operator wrote
|
|
95
|
+
* is how a setting comes to mean nothing while looking configured.
|
|
96
|
+
*
|
|
97
|
+
* A configured list that resolves to NOTHING keeps `usedDefault: false` and an
|
|
98
|
+
* empty `hosts` — that is "thin no host", which is a legitimate and safe answer
|
|
99
|
+
* and must not fall back to the default. Falling back there would turn a
|
|
100
|
+
* fully-typo'd list into a Claude Code flip the operator never asked for.
|
|
101
|
+
*
|
|
102
|
+
* WHICH FILES REACH THIS AT ALL, stated because R2 finding 6 read the drop path
|
|
103
|
+
* as unreachable: `agent-settings.schema.json` and the wizard's Zod schema both
|
|
104
|
+
* constrain the items to an `enum`, so an out-of-vocabulary id written through
|
|
105
|
+
* either surface is a hard validation FAILURE and never arrives here. What
|
|
106
|
+
* arrives here is a HAND-EDITED `.agent-settings.yml` — the file
|
|
107
|
+
* `condense._lean_projection_settings` and `hooks/rule_inject_hook.gateOpen`
|
|
108
|
+
* both read directly, with no validation step in between. The two layers are
|
|
109
|
+
* defence in depth, not one contract stated twice: the schema is the authoring
|
|
110
|
+
* gate, this function is the read-time gate, and the drop wording below exists
|
|
111
|
+
* for the file the schema never saw.
|
|
112
|
+
*/
|
|
113
|
+
export function resolveLeanProjectionHosts(raw: unknown): LeanProjectionHosts {
|
|
114
|
+
const known = new Set(THINNABLE_HOSTS);
|
|
115
|
+
if (!Array.isArray(raw) || raw.length === 0) {
|
|
116
|
+
return { hosts: [...DEFAULT_LEAN_PROJECTION_HOSTS], dropped: [], usedDefault: true };
|
|
117
|
+
}
|
|
118
|
+
const hosts: string[] = [];
|
|
119
|
+
const dropped: Array<{ id: string; reason: DroppedHostReason }> = [];
|
|
120
|
+
for (const entry of raw) {
|
|
121
|
+
const id = typeof entry === 'string' ? entry.trim().toLowerCase() : '';
|
|
122
|
+
if (id === '') {
|
|
123
|
+
dropped.push({ id: String(entry), reason: 'unknown' });
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (!known.has(id)) {
|
|
127
|
+
// `not-thinnable` is reserved for an id this package genuinely knows
|
|
128
|
+
// as a host but which owns no per-rule tree. Everything else is a
|
|
129
|
+
// typo or an invention, and the two deserve different wording
|
|
130
|
+
// because the operator's next action differs: fix the spelling, or
|
|
131
|
+
// learn that the host cannot be thinned at all.
|
|
132
|
+
dropped.push({ id, reason: KNOWN_NON_THINNABLE_HOSTS.has(id) ? 'not-thinnable' : 'unknown' });
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (!hosts.includes(id)) hosts.push(id);
|
|
136
|
+
}
|
|
137
|
+
hosts.sort();
|
|
138
|
+
return { hosts, dropped, usedDefault: false };
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Host ids the package ships surfaces for that own no per-rule rule tree.
|
|
143
|
+
*
|
|
144
|
+
* Only used to word a drop precisely; it grants nothing. Sourced from
|
|
145
|
+
* `condense._ALL_TOOLS` plus the two hosts outside it that the host table
|
|
146
|
+
* carries (`codex`, `cowork`).
|
|
147
|
+
*/
|
|
148
|
+
const KNOWN_NON_THINNABLE_HOSTS: ReadonlySet<string> = new Set([
|
|
149
|
+
'claude-desktop', 'augment', 'copilot', 'windsurf', 'gemini', 'codex', 'cowork',
|
|
150
|
+
]);
|
|
151
|
+
|
|
152
|
+
/** One line per dropped id, for a caller that prints warnings. Empty when nothing was dropped. */
|
|
153
|
+
export function describeDroppedHosts(res: LeanProjectionHosts): string[] {
|
|
154
|
+
return res.dropped.map(({ id, reason }) =>
|
|
155
|
+
reason === 'not-thinnable'
|
|
156
|
+
? `lean_projection.hosts: "${id}" is a known host but has no per-rule rule tree — dropped`
|
|
157
|
+
: `lean_projection.hosts: "${id}" is not a thinnable host id — dropped`,
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Does the projector write stubs for this host, under this mode and host set?
|
|
163
|
+
*
|
|
164
|
+
* The single predicate `condense` calls. Mode is checked FIRST and on purpose:
|
|
165
|
+
* with `mode` unset the answer is `false` for every host regardless of what
|
|
166
|
+
* `hosts` says, so a `hosts:` list left behind after a rollback to `eager-all`
|
|
167
|
+
* thins nothing.
|
|
168
|
+
*/
|
|
169
|
+
export function thinsHost(mode: LeanProjectionMode, hosts: readonly string[], hostId: string): boolean {
|
|
170
|
+
return writesThinFiles(mode) && hosts.includes(hostId);
|
|
171
|
+
}
|
|
@@ -241,9 +241,8 @@ export type Slot =
|
|
|
241
241
|
* Default firing period per slot, before per-platform native-event corrections.
|
|
242
242
|
*
|
|
243
243
|
* `stop` is per-turn, NOT session end. On Claude Code the native `Stop` event
|
|
244
|
-
* fires after every assistant reply
|
|
245
|
-
*
|
|
246
|
-
* i.e. a working-memory refresh per reply. True session end is the separate
|
|
244
|
+
* fires after every assistant reply, so a concern bound there runs once per
|
|
245
|
+
* reply rather than once per session. True session end is the separate
|
|
247
246
|
* `session_end` slot.
|
|
248
247
|
*/
|
|
249
248
|
const SLOT_FREQUENCY_DEFAULT: Record<Slot, Frequency> = {
|