@event4u/agent-config 16.3.0 → 16.5.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 +178 -78
- package/README.md +2 -2
- package/agents/templates/.ai-council.yml.example +26 -8
- package/dist/agent-src/commands/analyze/inbox.md +10 -7
- package/dist/agent-src/commands/bug/investigate.md +1 -1
- package/dist/agent-src/commands/commit/in-chunks.md +40 -31
- package/dist/agent-src/commands/commit.md +72 -33
- package/dist/agent-src/commands/condense.md +2 -8
- package/dist/agent-src/commands/council/debate.md +11 -7
- package/dist/agent-src/commands/council/default.md +10 -9
- package/dist/agent-src/commands/council.md +1 -1
- package/dist/agent-src/commands/design.md +1 -1
- package/dist/agent-src/commands/estimate-ticket.md +1 -1
- package/dist/agent-src/commands/feature/explore.md +3 -3
- package/dist/agent-src/commands/feature/plan.md +1 -1
- package/dist/agent-src/commands/fix/ci.md +17 -3
- package/dist/agent-src/commands/fix/commit-messages.md +48 -23
- package/dist/agent-src/commands/fix/pr-comments.md +3 -6
- package/dist/agent-src/commands/implement-ticket.md +3 -3
- package/dist/agent-src/commands/memory/add.md +4 -16
- package/dist/agent-src/commands/memory/load.md +5 -6
- package/dist/agent-src/commands/memory/promote.md +3 -16
- package/dist/agent-src/commands/mission/upgrade.md +3 -2
- package/dist/agent-src/commands/optimize/agents-dir.md +2 -2
- package/dist/agent-src/commands/optimize/deep.md +4 -2
- package/dist/agent-src/commands/optimize/rtk.md +4 -26
- package/dist/agent-src/commands/pr/create/description-only.md +18 -15
- package/dist/agent-src/commands/pr/create.md +42 -34
- package/dist/agent-src/commands/pr/merge.md +136 -9
- package/dist/agent-src/commands/prepare-for-review.md +13 -11
- package/dist/agent-src/commands/project/analyze.md +7 -35
- package/dist/agent-src/commands/refine-ticket.md +1 -1
- package/dist/agent-src/commands/review/changes.md +14 -19
- package/dist/agent-src/commands/roadmap/next.md +10 -1
- package/dist/agent-src/commands/roadmap/process-full.md +52 -38
- package/dist/agent-src/commands/roadmap/resolve-blockers.md +64 -14
- package/dist/agent-src/commands/worktree/create.md +7 -3
- package/dist/agent-src/commands/worktree/verify.md +2 -1
- package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +5 -3
- package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +7 -9
- package/dist/agent-src/contexts/contracts/command-suggestion-flow.md +8 -6
- package/dist/agent-src/contexts/contracts/frugality-charter.md +8 -5
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +1 -1
- package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +0 -1
- package/dist/agent-src/contexts/execution/evidence-discipline.md +2 -2
- package/dist/agent-src/contexts/execution/non-interactive-contract.md +5 -8
- package/dist/agent-src/contexts/execution/rdp-gate.md +4 -4
- package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +9 -8
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +67 -52
- package/dist/agent-src/contexts/execution/subagent-routing.md +8 -8
- package/dist/agent-src/contexts/execution/subagent-steering.md +6 -4
- package/dist/agent-src/contexts/execution/terminal-states.md +2 -2
- package/dist/agent-src/contexts/execution/toolchain-resolver.md +4 -10
- package/dist/agent-src/contexts/subagent-configuration.md +1 -1
- package/dist/agent-src/guidelines/agent-infra/active-remediation-mechanics.md +39 -0
- package/dist/agent-src/guidelines/agent-infra/context-hygiene-mechanics.md +1 -1
- package/dist/agent-src/guidelines/agent-infra/cross-source-consistency-mechanics.md +8 -10
- package/dist/agent-src/guidelines/agent-infra/frontier-reasoning-operating-profile.md +3 -2
- package/dist/agent-src/guidelines/agent-infra/layered-settings.md +13 -1
- package/dist/agent-src/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
- package/dist/agent-src/guidelines/agent-infra/self-improvement-pipeline.md +10 -3
- package/dist/agent-src/guidelines/agent-infra/size-and-scope.md +36 -0
- package/dist/agent-src/guidelines/design-antipatterns.md +1 -1
- package/dist/agent-src/guidelines/php/git.md +15 -2
- package/dist/agent-src/rules/active-remediation.md +0 -1
- package/dist/agent-src/rules/analysis-skill-routing.md +0 -1
- package/dist/agent-src/rules/architecture.md +0 -1
- package/dist/agent-src/rules/artifact-drafting-protocol.md +0 -1
- package/dist/agent-src/rules/artifact-engagement-recording.md +0 -1
- package/dist/agent-src/rules/augment-edit-discipline.md +0 -1
- package/dist/agent-src/rules/autonomous-execution.md +0 -1
- package/dist/agent-src/rules/brand-consistency.md +0 -1
- package/dist/agent-src/rules/brand-source-of-truth.md +0 -1
- package/dist/agent-src/rules/broken-access-control.md +0 -1
- package/dist/agent-src/rules/cli-output-handling.md +0 -1
- package/dist/agent-src/rules/code-comment-discipline.md +0 -1
- package/dist/agent-src/rules/code-provenance.md +0 -1
- package/dist/agent-src/rules/command-suggestion-policy.md +0 -1
- package/dist/agent-src/rules/commit-conventions.md +1 -2
- package/dist/agent-src/rules/communication-through-line.md +1 -2
- package/dist/agent-src/rules/content-quoting-floor.md +1 -2
- package/dist/agent-src/rules/context-hygiene.md +5 -5
- package/dist/agent-src/rules/copilot-routing.md +1 -2
- package/dist/agent-src/rules/council-availability.md +4 -4
- package/dist/agent-src/rules/cross-source-consistency.md +4 -6
- package/dist/agent-src/rules/decision-revisit-gate.md +2 -3
- package/dist/agent-src/rules/delegation-policy.md +2 -3
- package/dist/agent-src/rules/design-fidelity.md +0 -1
- package/dist/agent-src/rules/design-review-after-ui-write.md +3 -3
- package/dist/agent-src/rules/devcontainer-routing.md +1 -2
- package/dist/agent-src/rules/doc-screenshot-hygiene.md +0 -1
- package/dist/agent-src/rules/docker-commands.md +0 -1
- package/dist/agent-src/rules/domain-adoption-policy.md +0 -1
- package/dist/agent-src/rules/domain-safety-disclaimer.md +0 -1
- package/dist/agent-src/rules/domain-safety-pii.md +0 -1
- package/dist/agent-src/rules/domain-safety-retention.md +0 -1
- package/dist/agent-src/rules/downstream-changes.md +0 -1
- package/dist/agent-src/rules/engineering-safety-floor.md +0 -1
- package/dist/agent-src/rules/external-code-graph-interop.md +0 -1
- package/dist/agent-src/rules/external-reference-deep-dive.md +0 -1
- package/dist/agent-src/rules/fast-path-marker-visibility.md +1 -2
- package/dist/agent-src/rules/finance-safety-floor.md +0 -1
- package/dist/agent-src/rules/fix-what-you-see.md +6 -32
- package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +0 -1
- package/dist/agent-src/rules/git-history-discipline.md +1 -2
- package/dist/agent-src/rules/guidelines.md +0 -1
- package/dist/agent-src/rules/history-discipline.md +0 -1
- package/dist/agent-src/rules/icon-consistency.md +0 -1
- package/dist/agent-src/rules/image-likeness-and-rights.md +0 -1
- package/dist/agent-src/rules/improve-before-implement.md +0 -1
- package/dist/agent-src/rules/invite-challenge.md +0 -1
- package/dist/agent-src/rules/laravel-routing.md +1 -2
- package/dist/agent-src/rules/laravel-translations.md +0 -1
- package/dist/agent-src/rules/legal-safety-floor.md +0 -1
- package/dist/agent-src/rules/lethal-trifecta-guard.md +0 -1
- package/dist/agent-src/rules/linked-projects-onboarding-gate.md +0 -1
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +0 -1
- package/dist/agent-src/rules/markdown-safe-codeblocks.md +0 -1
- package/dist/agent-src/rules/media-governance-routing.md +1 -2
- package/dist/agent-src/rules/media-sync-ground-truth.md +0 -1
- package/dist/agent-src/rules/minimal-safe-diff.md +0 -1
- package/dist/agent-src/rules/missing-skill-recovery.md +0 -1
- package/dist/agent-src/rules/missing-tool-handling.md +0 -1
- package/dist/agent-src/rules/model-recommendation.md +0 -1
- package/dist/agent-src/rules/neighbour-precedence.md +64 -0
- package/dist/agent-src/rules/no-attribution-footers.md +0 -1
- package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +0 -1
- package/dist/agent-src/rules/no-pr-progress-comments.md +0 -1
- package/dist/agent-src/rules/no-roadmap-references.md +0 -1
- package/dist/agent-src/rules/notes-first-reasoning.md +0 -1
- package/dist/agent-src/rules/onboarding-gate.md +0 -1
- package/dist/agent-src/rules/output-discipline.md +0 -1
- package/dist/agent-src/rules/package-ci-checks.md +0 -1
- package/dist/agent-src/rules/persona-governance.md +2 -3
- package/dist/agent-src/rules/php-coding.md +0 -1
- package/dist/agent-src/rules/prefer-enums-over-literals.md +0 -1
- package/dist/agent-src/rules/preservation-guard.md +0 -1
- package/dist/agent-src/rules/provider-lifecycle-discipline.md +2 -3
- package/dist/agent-src/rules/question-not-instruction.md +0 -1
- package/dist/agent-src/rules/reviewer-awareness.md +0 -1
- package/dist/agent-src/rules/roadmap-ci-steps-policy.md +0 -1
- package/dist/agent-src/rules/roadmap-progress-sync.md +3 -6
- package/dist/agent-src/rules/role-mode-adherence.md +0 -1
- package/dist/agent-src/rules/rule-type-governance.md +0 -1
- package/dist/agent-src/rules/runtime-safety.md +0 -1
- package/dist/agent-src/rules/scale-discipline.md +0 -1
- package/dist/agent-src/rules/secret-vcs-guard.md +0 -1
- package/dist/agent-src/rules/security-sensitive-stop.md +0 -1
- package/dist/agent-src/rules/self-repair-loop.md +0 -1
- package/dist/agent-src/rules/senior-engineering-discipline.md +0 -1
- package/dist/agent-src/rules/session-canary.md +0 -1
- package/dist/agent-src/rules/settings-ask-protocol.md +5 -6
- package/dist/agent-src/rules/size-enforcement.md +0 -1
- package/dist/agent-src/rules/skill-improvement-trigger.md +2 -3
- package/dist/agent-src/rules/skill-quality.md +0 -1
- package/dist/agent-src/rules/slash-command-routing-policy.md +0 -1
- package/dist/agent-src/rules/source-confidentiality.md +0 -1
- package/dist/agent-src/rules/source-discovery-gate.md +0 -1
- package/dist/agent-src/rules/source-of-truth.md +0 -1
- package/dist/agent-src/rules/spreadsheet-source-quality.md +1 -2
- package/dist/agent-src/rules/strategy-safety-floor.md +0 -1
- package/dist/agent-src/rules/symfony-routing.md +1 -2
- package/dist/agent-src/rules/think-before-action.md +0 -1
- package/dist/agent-src/rules/token-budget-discipline.md +14 -48
- package/dist/agent-src/rules/token-efficiency.md +0 -1
- package/dist/agent-src/rules/token-optimizer-maintenance.md +0 -1
- package/dist/agent-src/rules/tool-safety.md +0 -1
- package/dist/agent-src/rules/ui-audit-gate.md +1 -2
- package/dist/agent-src/rules/untrusted-input-defense.md +0 -1
- package/dist/agent-src/rules/upstream-proposal.md +0 -1
- package/dist/agent-src/rules/user-interaction.md +0 -1
- package/dist/agent-src/rules/user-interrupt-priority.md +0 -1
- package/dist/agent-src/scripts/gate_budget.ts +47 -23
- package/dist/agent-src/scripts/gate_execute.ts +12 -4
- package/dist/agent-src/skills/accessibility-auditor/data/aria-patterns.csv +2 -0
- package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +3 -3
- package/dist/agent-src/skills/ai-council/SKILL.md +7 -4
- package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +21 -11
- package/dist/agent-src/skills/ai-council/references/procedure.md +12 -6
- package/dist/agent-src/skills/analysis-autonomous-mode/SKILL.md +1 -1
- package/dist/agent-src/skills/bug-analyzer/SKILL.md +1 -1
- package/dist/agent-src/skills/canvas-design/SKILL.md +4 -2
- package/dist/agent-src/skills/command-routing/SKILL.md +3 -4
- package/dist/agent-src/skills/conventional-commits-writing/SKILL.md +127 -139
- package/dist/agent-src/skills/corpus-grounding/ATTRIBUTION.md +39 -0
- package/dist/agent-src/skills/corpus-grounding/SKILL.md +8 -2
- package/dist/agent-src/skills/database/data/manifest.json +2 -2
- package/dist/agent-src/skills/database/data/query-tuning.csv +13 -13
- package/dist/agent-src/skills/design-intelligence/references/integration-mapping.md +13 -10
- package/dist/agent-src/skills/design-system-capture/SKILL.md +0 -3
- package/dist/agent-src/skills/estimate-ticket/SKILL.md +1 -1
- package/dist/agent-src/skills/fe-design/references/design-patterns.md +49 -2
- package/dist/agent-src/skills/feature-planning/SKILL.md +1 -1
- package/dist/agent-src/skills/frontend-render-security/SKILL.md +9 -0
- package/dist/agent-src/skills/git-workflow/SKILL.md +44 -44
- package/dist/agent-src/skills/git-workflow/references/branch-update.md +312 -0
- package/dist/agent-src/skills/git-workflow/references/commit-subject.md +205 -0
- package/dist/agent-src/skills/iconography/SKILL.md +4 -2
- package/dist/agent-src/skills/image-provider-routing/SKILL.md +16 -5
- package/dist/agent-src/skills/jira-integration/SKILL.md +3 -3
- package/dist/agent-src/skills/logo-generation/SKILL.md +12 -8
- package/dist/agent-src/skills/merge-conflicts/SKILL.md +10 -4
- package/dist/agent-src/skills/po-discovery/SKILL.md +1 -1
- package/dist/agent-src/skills/refine-ticket/SKILL.md +4 -4
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +2 -2
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +4 -2
- package/dist/agent-src/skills/source-discovery/SKILL.md +1 -1
- package/dist/agent-src/skills/svg-authoring/SKILL.md +318 -0
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +3 -1
- package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
- package/dist/agent-src/skills/using-git-worktrees/SKILL.md +1 -1
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +2 -2
- package/dist/agent-src/skills/wireframe/SKILL.md +5 -2
- package/dist/agent-src/templates/AGENTS.md +1 -1
- package/dist/agent-src/templates/agent-settings.md +46 -129
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +3 -3
- package/dist/agent-src/templates/command.md +2 -2
- package/dist/agent-src/templates/roadmaps.md +6 -1
- package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -6
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +11 -7
- package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +3 -2
- package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +2 -1
- package/dist/agent-src/templates/scripts/work_engine/hooks/settings.ts +0 -6
- package/dist/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +9 -12
- package/dist/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +2 -1
- package/dist/agent-src/templates/skill.md +1 -1
- package/dist/cli/commands/uiRender.js +201 -4
- package/dist/cli/commands/uiRenderAsset.js +1308 -0
- package/dist/cli/commands/uiRenderAssetCompare.js +752 -0
- package/dist/cli/commands/uiRenderAssetGrid.js +265 -0
- package/dist/cli/commands/uiRenderAssetGrounds.js +323 -0
- package/dist/cli/commands/uiRenderAssetIsolation.js +85 -0
- package/dist/cli/commands/uiRenderAssetTypes.js +145 -0
- package/dist/cli/main.js +47 -1
- package/dist/cli/registry.js +2 -1
- package/dist/cli-delegate/check_update_banner.js +195 -119
- package/dist/cli-delegate/{chunk-S4UMZNES.js → chunk-4DBG5K7M.js} +5 -5
- package/dist/cli-delegate/{chunk-TRI6DQZ6.js → chunk-5GPULQBE.js} +60 -42
- package/dist/cli-delegate/{chunk-JQVYKIZA.js → chunk-6SRJTYJS.js} +33 -177
- package/dist/cli-delegate/chunk-6V5FMA3P.js +186 -0
- package/dist/cli-delegate/chunk-6YQC2HLF.js +415 -0
- package/dist/cli-delegate/{chunk-E4XIZDIB.js → chunk-7HKRE54K.js} +1 -64
- package/dist/cli-delegate/{chunk-7HQ52DHU.js → chunk-AL3RZ22D.js} +1 -1
- package/dist/cli-delegate/{chunk-DBH4AHDK.js → chunk-ED7KCMLB.js} +9 -11
- package/dist/cli-delegate/{chunk-NXEILF2K.js → chunk-F3QDG2GT.js} +481 -72
- package/dist/cli-delegate/{chunk-CQWX336L.js → chunk-G5VVIZRC.js} +3 -3
- package/dist/cli-delegate/{chunk-JY2I2DXV.js → chunk-H76PHZBI.js} +137 -60
- package/dist/cli-delegate/chunk-IAYTIIQW.js +67 -0
- package/dist/cli-delegate/{chunk-LIYTLH6O.js → chunk-KXXWJTDO.js} +5 -10
- package/dist/cli-delegate/{chunk-T7L2QK3K.js → chunk-LQOCRFWT.js} +1 -1
- package/dist/cli-delegate/{chunk-S4YWNRKO.js → chunk-MDPPKQCQ.js} +34 -1
- package/dist/cli-delegate/chunk-OAFSJBHH.js +272 -0
- package/dist/cli-delegate/{chunk-GKE7ZVFA.js → chunk-PWX7CKMD.js} +1 -1
- package/dist/cli-delegate/{chunk-NDJLNC6Q.js → chunk-T6BP34WI.js} +1 -0
- package/dist/cli-delegate/{chunk-RQNNW7IF.js → chunk-T7XSJSUQ.js} +433 -632
- package/dist/cli-delegate/{chunk-NQ7WT43P.js → chunk-TMWYUOK4.js} +75 -12
- package/dist/cli-delegate/{chunk-EEHDXSYD.js → chunk-WQWXGIWB.js} +12 -273
- package/dist/cli-delegate/{chunk-QLDHIPWR.js → chunk-XQTPXKFA.js} +1 -1
- package/dist/cli-delegate/cmd_analyze_session.js +223 -43
- package/dist/cli-delegate/cmd_brand_status.js +3 -2
- package/dist/cli-delegate/cmd_conformance.js +489 -238
- package/dist/cli-delegate/cmd_converge.js +3 -3
- package/dist/cli-delegate/cmd_doctor.js +15 -12
- package/dist/cli-delegate/cmd_doctor_neighbours.js +11 -4
- package/dist/cli-delegate/cmd_explain.js +43 -19
- package/dist/cli-delegate/cmd_export.js +10 -10
- package/dist/cli-delegate/cmd_git_convention.js +1851 -0
- package/dist/cli-delegate/cmd_handoff.js +40 -21
- package/dist/cli-delegate/cmd_mcp_available.js +3 -2
- package/dist/cli-delegate/cmd_migrate.js +3 -3
- package/dist/cli-delegate/cmd_packs_active.js +4 -3
- package/dist/cli-delegate/cmd_prune.js +10 -10
- package/dist/cli-delegate/cmd_route_audit.js +7 -7
- package/dist/cli-delegate/cmd_route_explain.js +5 -5
- package/dist/cli-delegate/cmd_session_recycle.js +9 -7
- package/dist/cli-delegate/cmd_settings_check.js +54 -7
- package/dist/cli-delegate/cmd_settings_get.js +18 -8
- package/dist/cli-delegate/cmd_settings_migrate.js +10 -10
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +10 -10
- package/dist/cli-delegate/cmd_uninstall.js +10 -10
- package/dist/cli-delegate/cmd_update.js +7 -7
- package/dist/cli-delegate/cmd_upgrade.js +7 -7
- package/dist/cli-delegate/cmd_validate.js +10 -10
- package/dist/cli-delegate/cmd_versions.js +5 -5
- package/dist/cli-delegate/gate_budget.js +1 -1
- package/dist/cli-delegate/gate_execute.js +2 -2
- package/dist/cli-delegate/roadmap_gates.js +2 -2
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +171 -107
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +7 -7
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +41 -22
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +16 -11
- package/dist/hooks/dispatch.js +2520 -1924
- package/dist/hooks/dispatch.sha256 +1 -1
- package/dist/hooks/svg_rules.chunk.cjs +1626 -0
- package/dist/hooks/svg_rules.chunk.cjs.sha256 +1 -0
- package/dist/install/install.mjs +462 -431
- package/dist/install/installThinLayer.js +40 -12
- package/dist/install/installedRuleLinks.js +105 -19
- package/dist/mcp/awesome-mcp-servers.row.md +1 -1
- package/dist/mcp/mcp-cloudflare-catalogue.json +2 -2
- package/dist/mcp/registry-manifest.json +5 -5
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +3063 -2160
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_settings.js +15 -120
- package/dist/scripts/_lib/compile_time_toggles.js +12 -21
- package/dist/scripts/_lib/git_convention.js +232 -0
- package/dist/scripts/_lib/global_deploy_inventory.js +730 -0
- package/dist/scripts/_lib/installed_layer.js +344 -18
- package/dist/scripts/_lib/package_root.js +68 -0
- package/dist/scripts/_lib/rule_law_section.js +1 -1
- package/dist/scripts/_lib/scan_scope.js +105 -0
- package/dist/scripts/_lib/settings_removed_keys.js +168 -0
- package/dist/scripts/_lib/svg_dom.js +284 -0
- package/dist/scripts/_lib/svg_geometry.js +477 -0
- package/dist/scripts/_lib/svg_motion.js +179 -0
- package/dist/scripts/_lib/svg_rules.js +1337 -0
- package/dist/scripts/_lib/svg_urls.js +67 -0
- package/dist/scripts/_lib/thin_rules.js +80 -3
- package/dist/scripts/lint_svg_asset.js +324 -0
- package/dist/server/app.js +2 -1
- package/dist/server/gitKeysGate.js +105 -0
- package/dist/server/routes/settings.js +67 -8
- package/dist/server/routes/wizard.js +4 -0
- package/dist/server/schemas/settings.js +23 -81
- package/dist/shared/skillRanking.js +30 -4
- package/dist/ui/assets/{index-Cwq4d0hX.js → index-C3djEJah.js} +2 -2
- package/dist/ui/index.html +1 -1
- package/docs/MIGRATION.md +72 -1
- package/docs/contracts/settings-classes.md +35 -65
- package/docs/guidelines/agent-infra/active-remediation-mechanics.md +39 -0
- package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +1 -1
- package/docs/guidelines/agent-infra/cross-source-consistency-mechanics.md +8 -10
- package/docs/guidelines/agent-infra/frontier-reasoning-operating-profile.md +3 -2
- package/docs/guidelines/agent-infra/layered-settings.md +13 -1
- package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
- package/docs/guidelines/agent-infra/self-improvement-pipeline.md +10 -3
- package/docs/guidelines/agent-infra/size-and-scope.md +36 -0
- package/docs/guidelines/design-antipatterns.md +1 -1
- package/docs/guidelines/php/git.md +15 -2
- package/package.json +4 -3
- package/src/agent-src/scripts/gate_budget.ts +47 -23
- package/src/agent-src/scripts/gate_execute.ts +12 -4
- package/src/agent-src/templates/AGENTS.md +1 -1
- package/src/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -6
- package/src/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +11 -7
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +3 -2
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +2 -1
- package/src/agent-src/templates/scripts/work_engine/hooks/settings.ts +0 -6
- package/src/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +9 -12
- package/src/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +2 -1
- package/src/config/agent-settings.template.yml +79 -312
- package/src/config/agents-paths.yml +16 -0
- package/src/config/assurance-capability-registry.json +7 -3
- package/src/config/ci-local-parity.yml +3 -0
- package/src/config/continuity-surface.json +3 -3
- package/src/config/discovery/packs.yml +17 -1
- package/src/config/evaluator-budgets.json +19 -6
- package/src/config/gate-coverage.yml +65 -23
- package/src/config/gate-violation-baselines.json +56 -16
- package/src/config/gitignore-block.txt +19 -0
- package/src/config/hook-bundle-budget.json +1 -1
- package/src/config/release-gate-locality.yml +2 -1
- package/src/config/routing-coverage-seed.json +55 -6
- package/src/config/rule-law-ceilings.json +12 -6
- package/src/config/rule-obligations.json +833 -0
- package/src/install/installThinLayer.ts +76 -10
- package/src/install/installedRuleLinks.ts +105 -17
- package/src/scripts/_cli/cmd_analyze_session.ts +9 -15
- package/src/scripts/_cli/cmd_conformance.ts +13 -2
- package/src/scripts/_cli/cmd_doctor.ts +10 -10
- package/src/scripts/_cli/cmd_doctor_neighbours.ts +133 -0
- package/src/scripts/_cli/cmd_explain.ts +72 -14
- package/src/scripts/_cli/cmd_git_convention.ts +637 -0
- package/src/scripts/_cli/cmd_settings_check.ts +66 -8
- package/src/scripts/_cli/cmd_settings_get.ts +18 -3
- package/src/scripts/_cli/doctor_execution.ts +72 -1
- package/src/scripts/_dispatch.bash +37 -2
- package/src/scripts/_lib/agent_settings.ts +15 -124
- package/src/scripts/_lib/blocked_by_marker.ts +1 -1
- package/src/scripts/_lib/compile_time_toggles.ts +12 -21
- package/src/scripts/_lib/dispatch_import_closure.ts +163 -0
- package/src/scripts/_lib/git_base_ref.ts +92 -0
- package/src/scripts/_lib/git_convention.ts +291 -0
- package/src/scripts/_lib/git_convention_carrier.ts +389 -0
- package/src/scripts/_lib/git_convention_grammar.ts +246 -0
- package/src/scripts/_lib/git_convention_measure.ts +344 -0
- package/src/scripts/_lib/global_deploy_inventory.ts +74 -0
- package/src/scripts/_lib/graph_feeder_record.ts +236 -13
- package/src/scripts/_lib/installed_layer.ts +448 -23
- package/src/scripts/_lib/knowledge_global.ts +14 -1
- package/src/scripts/_lib/module_reach.ts +456 -0
- package/src/scripts/_lib/neighbour_contradictions.ts +236 -0
- package/src/scripts/_lib/neighbour_tool_use.ts +8 -10
- package/src/scripts/_lib/ratification_artifact.ts +220 -1
- package/src/scripts/_lib/ratification_subject.ts +92 -0
- package/src/scripts/_lib/release_findings_ingest.ts +15 -7
- package/src/scripts/_lib/release_highlights.ts +5 -0
- package/src/scripts/_lib/rule_law_section.ts +1 -1
- package/src/scripts/_lib/rule_obligations.ts +205 -0
- package/src/scripts/_lib/self_repair.ts +1 -1
- package/src/scripts/_lib/settings_removed_keys.ts +173 -0
- package/src/scripts/_lib/svg_dom.ts +318 -0
- package/src/scripts/_lib/svg_geometry.ts +480 -0
- package/src/scripts/_lib/svg_motion.ts +208 -0
- package/src/scripts/_lib/svg_rules.ts +1453 -0
- package/src/scripts/_lib/svg_urls.ts +72 -0
- package/src/scripts/_lib/test_red_state.ts +5 -0
- package/src/scripts/_lib/thin_rules.ts +83 -3
- package/src/scripts/_lib/touched_file_quality.ts +142 -6
- package/src/scripts/_lib/verification_command.ts +59 -0
- package/src/scripts/_lib/verify_clause.ts +27 -17
- package/src/scripts/_lib/worker_budget.ts +1 -1
- package/src/scripts/adr/regenerate_index.ts +16 -1
- package/src/scripts/ai_council/config.ts +7 -7
- package/src/scripts/ai_council/modification_review.ts +100 -0
- package/src/scripts/ai_council/modification_review_questions.ts +90 -0
- package/src/scripts/ai_council/orchestrator.ts +5 -5
- package/src/scripts/ai_council/spend_gate.ts +18 -7
- package/src/scripts/ai_team/config.ts +11 -16
- package/src/scripts/audit_user_type_axis.ts +20 -8
- package/src/scripts/bench_ab_clone.ts +1 -2
- package/src/scripts/bench_concern_spawn_path.ts +129 -0
- package/src/scripts/bench_graph_feeder_latency.ts +584 -0
- package/src/scripts/check_agent_artifact_location.ts +36 -0
- package/src/scripts/check_branch_freshness.ts +147 -24
- package/src/scripts/check_enforcement_coverage.ts +130 -0
- package/src/scripts/check_evaluator_budgets.ts +4 -0
- package/src/scripts/check_finding_dispositions.ts +88 -25
- package/src/scripts/check_gate_coverage.ts +4 -3
- package/src/scripts/check_gate_reachability.ts +48 -1
- package/src/scripts/check_generator_sync.ts +48 -0
- package/src/scripts/check_hook_bundle_composition.ts +107 -0
- package/src/scripts/check_kernel_edit_ratified.ts +86 -6
- package/src/scripts/check_pack_size.ts +1 -1
- package/src/scripts/check_release_manifest_content.ts +189 -0
- package/src/scripts/check_standing_rule_delivery.ts +96 -0
- package/src/scripts/check_suppression_hygiene.ts +2 -5
- package/src/scripts/ci_settle.ts +42 -5
- package/src/scripts/classify_merge_risk.ts +320 -0
- package/src/scripts/closure_scan.ts +91 -1
- package/src/scripts/command_suggester/settings.ts +8 -108
- package/src/scripts/command_suggester/types.ts +4 -5
- package/src/scripts/consumer_matrix.ts +102 -0
- package/src/scripts/context_hygiene_hook.ts +13 -23
- package/src/scripts/cost/preflight.mjs +12 -1
- package/src/scripts/council_cli.ts +7 -7
- package/src/scripts/dispatch_r2_reviewer.ts +24 -11
- package/src/scripts/explain_run.ts +8 -13
- package/src/scripts/generate_git_convention_grammar.ts +127 -0
- package/src/scripts/generate_host_cost_table.ts +20 -3
- package/src/scripts/handoff_context_hook.ts +86 -37
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +25 -6
- package/src/scripts/hooks/block_config_weakening.ts +48 -5
- package/src/scripts/hooks/block_plumbing_writes.ts +8 -4
- package/src/scripts/hooks/block_speaking_inbox_dir.ts +16 -1
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/delegation_nudge_hook.ts +2 -3
- package/src/scripts/hooks/design_pass_hook.ts +157 -3
- package/src/scripts/hooks/evidence_independence.ts +12 -4
- package/src/scripts/hooks/mcp_usage_observation_hook.ts +121 -0
- package/src/scripts/hooks/push_settle_hook.ts +4 -3
- package/src/scripts/hooks/rule_inject_hook.ts +44 -3
- package/src/scripts/hooks/state_io.ts +8 -4
- package/src/scripts/hooks/svg_obligation.ts +497 -0
- package/src/scripts/hooks/svg_rules_loader.ts +133 -0
- package/src/scripts/hooks/telemetry_usage_hook.ts +7 -46
- package/src/scripts/hooks/turn_end_gate_hook.ts +6 -3
- package/src/scripts/install-hooks.sh +42 -14
- package/src/scripts/install.ts +7 -31
- package/src/scripts/lint_blocker_citations.ts +198 -0
- package/src/scripts/lint_consolidation_lineage.ts +6 -3
- package/src/scripts/lint_design_quality.ts +60 -12
- package/src/scripts/lint_evidence_artifacts.ts +9 -0
- package/src/scripts/lint_hook_concern_budget.ts +10 -21
- package/src/scripts/lint_motion_authority_drift.ts +27 -0
- package/src/scripts/lint_pack_boundaries.ts +406 -28
- package/src/scripts/lint_roadmap_blockers.ts +282 -29
- package/src/scripts/lint_roadmap_complexity.ts +4 -2
- package/src/scripts/lint_rule_law_section.ts +151 -21
- package/src/scripts/lint_rule_skill_pack_reach.ts +17 -0
- package/src/scripts/lint_settings_classes.ts +1 -1
- package/src/scripts/lint_svg_asset.ts +365 -0
- package/src/scripts/lint_ticked_unmet_criteria.ts +165 -0
- package/src/scripts/lint_workflow_security.ts +12 -1
- package/src/scripts/measure_skill_ranker_baseline.ts +5 -0
- package/src/scripts/model_rule_injection.ts +3 -3
- package/src/scripts/onboarding_gate_hook.ts +7 -6
- package/src/scripts/print_required_checks.ts +15 -3
- package/src/scripts/probe_host_compliance.ts +33 -5
- package/src/scripts/probe_turnaround.ts +183 -3
- package/src/scripts/ratification_header.ts +77 -0
- package/src/scripts/refusal_envelope.ts +138 -0
- package/src/scripts/release_publication.ts +29 -3
- package/src/scripts/report_dispatch_import_closure.ts +76 -0
- package/src/scripts/report_installed_rule_links.ts +118 -1
- package/src/scripts/report_module_reach.ts +212 -0
- package/src/scripts/report_obligation_mechanism.ts +16 -18
- package/src/scripts/report_parked_blockers.ts +222 -0
- package/src/scripts/report_required_checks_drift.ts +196 -0
- package/src/scripts/report_skill_ranker_confusion.ts +103 -2
- package/src/scripts/report_standing_payload_by_host.ts +1 -1
- package/src/scripts/routing_doctor.ts +2 -2
- package/src/scripts/schemas/agent-settings.schema.json +17 -31
- package/src/scripts/schemas/command.schema.json +1 -1
- package/src/scripts/schemas/skill.schema.json +1 -1
- package/src/scripts/self_review_gate.ts +39 -2
- package/src/scripts/skill_tools/score_skill_relevance.ts +28 -19
- package/src/scripts/sync_pr_branch.ts +403 -132
- package/src/scripts/trigger_eval_grandfather.json +0 -16
- package/src/server/schemas/settings.ts +33 -177
- package/src/shared/skillRanking.ts +53 -4
- package/dist/cli-delegate/chunk-NYX3L2PZ.js +0 -99
- package/src/scripts/_lib/config_chain.ts +0 -477
- package/src/scripts/_lib/conformance_report.ts +0 -403
- package/src/scripts/_lib/eval_discrimination.ts +0 -95
- package/src/scripts/_lib/evaluator_promotion.ts +0 -225
- package/src/scripts/_lib/file_slicer.ts +0 -117
- package/src/scripts/_lib/legacy_boundary_map.ts +0 -228
- package/src/scripts/_lib/minimality_tiebreak.ts +0 -168
- package/src/scripts/_lib/overbuild_lens_contract.ts +0 -196
- package/src/scripts/_lib/role_split.ts +0 -338
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* lint_svg_asset — the command-line surface over the SVG rule set.
|
|
4
|
+
*
|
|
5
|
+
* The rules live in `_lib/svg_rules.ts`, because the design pass imports them
|
|
6
|
+
* into the hook bundle and must not drag a CLI in with them (see that file's
|
|
7
|
+
* header for the measurement). Everything this module adds is the part only a
|
|
8
|
+
* command needs: argument parsing, the directory walk, the project config, the
|
|
9
|
+
* scanned-nothing refusal, and the step 1.2 preservation readout.
|
|
10
|
+
*
|
|
11
|
+
* Inline-ignore (same shape as `lint_design_quality`, works in XML comments):
|
|
12
|
+
* svg-asset-disable <rule-id> [-- reason] (file scope)
|
|
13
|
+
* svg-asset-disable-next-line <rule-id> [-- reason]
|
|
14
|
+
* svg-asset-disable-line <rule-id> [-- reason]
|
|
15
|
+
*
|
|
16
|
+
* Per-project config (`.svg-asset.json` in the project root):
|
|
17
|
+
* { "ignoreRules": ["svg-a11y-generic-id"], "ignoreFiles": ["vendor/**"] }
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* lint_svg_asset --dir <path> [--delivery inline|img|css-bg|document]
|
|
21
|
+
* lint_svg_asset --file <a.svg> [--file <b.svg>] [--delivery …]
|
|
22
|
+
* lint_svg_asset --file <after.svg> --baseline <before.svg> --allow id,id
|
|
23
|
+
*
|
|
24
|
+
* Exit codes: 0 = clean, 2 = findings, 1 = internal error (including the
|
|
25
|
+
* scanned-nothing refusal — a gate that scanned no file is not a clean gate).
|
|
26
|
+
*/
|
|
27
|
+
import fs from 'node:fs';
|
|
28
|
+
import path from 'node:path';
|
|
29
|
+
|
|
30
|
+
import { assertScanned, DeadScopeError } from './_lib/scan_scope.js';
|
|
31
|
+
import {
|
|
32
|
+
DELIVERY_MODES,
|
|
33
|
+
parseElements,
|
|
34
|
+
scanHostHtml,
|
|
35
|
+
scanSvg,
|
|
36
|
+
type DeliveryMode,
|
|
37
|
+
type Finding,
|
|
38
|
+
type ProjectConfig,
|
|
39
|
+
type SvgElement,
|
|
40
|
+
} from './_lib/svg_rules.js';
|
|
41
|
+
|
|
42
|
+
export * from './_lib/svg_rules.js';
|
|
43
|
+
|
|
44
|
+
// Step 1.2 — preservation readout for a surgical edit
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
|
|
47
|
+
export interface PreservationChange {
|
|
48
|
+
id: string;
|
|
49
|
+
element: string;
|
|
50
|
+
attribute: string;
|
|
51
|
+
before: string;
|
|
52
|
+
after: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Canonicalised attribute map — number formatting, attribute order and
|
|
57
|
+
* whitespace normalised away, so a re-serialisation that changed nothing reads
|
|
58
|
+
* as nothing changed.
|
|
59
|
+
*/
|
|
60
|
+
export function canonicalAttrs(attrs: Record<string, string>): Record<string, string> {
|
|
61
|
+
const out: Record<string, string> = {};
|
|
62
|
+
for (const key of Object.keys(attrs).sort()) {
|
|
63
|
+
const v = (attrs[key] ?? '')
|
|
64
|
+
.replace(/\s+/g, ' ')
|
|
65
|
+
.trim()
|
|
66
|
+
// Numbers only where a number is what it is. A hex color is a
|
|
67
|
+
// TOKEN, not a quantity: normalising inside `#00ff00` collapses it
|
|
68
|
+
// onto `#0ff0`, and the readout then reports no change for a color
|
|
69
|
+
// edit outside the allowed ids — a surgical-edit witness that
|
|
70
|
+
// cannot see a recolour.
|
|
71
|
+
.replace(/#[0-9a-fA-F]+|-?\d+\.?\d*(?:[eE][-+]?\d+)?/g, (tok) => {
|
|
72
|
+
if (tok.startsWith('#')) return tok.toLowerCase();
|
|
73
|
+
const num = Number(tok);
|
|
74
|
+
return Number.isFinite(num) ? String(Number(num.toFixed(4))) : tok;
|
|
75
|
+
});
|
|
76
|
+
out[key] = v;
|
|
77
|
+
}
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Every element outside the allowed set that changed between two revisions.
|
|
83
|
+
*
|
|
84
|
+
* NO PIXEL DIFF decides this. Anti-aliasing and font metrics would make a
|
|
85
|
+
* pixel comparison a per-machine verdict, and the discipline this witnesses —
|
|
86
|
+
* `design-fidelity-mechanics.md` § surgical edits — is about which elements
|
|
87
|
+
* the edit was allowed to touch, which is an attribute fact.
|
|
88
|
+
*/
|
|
89
|
+
export function preservationReadout(
|
|
90
|
+
beforeContent: string,
|
|
91
|
+
afterContent: string,
|
|
92
|
+
allowedIds: readonly string[],
|
|
93
|
+
): PreservationChange[] {
|
|
94
|
+
const allow = new Set(allowedIds.map((s) => s.trim()).filter(Boolean));
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* A stable key per element, and the id chain above it.
|
|
98
|
+
*
|
|
99
|
+
* An element WITHOUT an id is keyed by its nearest id-bearing ancestor plus
|
|
100
|
+
* its tag and its ordinal INSIDE that ancestor — never by a document-wide
|
|
101
|
+
* index. A document-wide index shifts for every element after an allowed
|
|
102
|
+
* deletion, so removing one child of the allowed group reported every
|
|
103
|
+
* un-idded element after it as changed. Measured on the `grouped-transforms`
|
|
104
|
+
* triple: the correct edit reported `rect#7 (element)` and the readout could
|
|
105
|
+
* not tell a clean surgical edit from a dirty one.
|
|
106
|
+
*/
|
|
107
|
+
const index = (content: string): Map<string, { el: SvgElement; chain: string[] }> => {
|
|
108
|
+
const map = new Map<string, { el: SvgElement; chain: string[] }>();
|
|
109
|
+
const stack: Array<{ name: string; id: string | null }> = [];
|
|
110
|
+
const ordinals = new Map<string, number>();
|
|
111
|
+
for (const el of parseElements(content)) {
|
|
112
|
+
if (el.closing) {
|
|
113
|
+
if (stack[stack.length - 1]?.name === el.name) stack.pop();
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const chain = stack.map((f) => f.id).filter((x): x is string => x !== null);
|
|
117
|
+
const ownerId = [...stack].reverse().find((f) => f.id !== null)?.id ?? '';
|
|
118
|
+
const own = el.attrs['id'] ?? null;
|
|
119
|
+
let key: string;
|
|
120
|
+
if (own) {
|
|
121
|
+
key = own;
|
|
122
|
+
} else {
|
|
123
|
+
const bucket = `${ownerId}/${el.name}`;
|
|
124
|
+
const n = (ordinals.get(bucket) ?? 0) + 1;
|
|
125
|
+
ordinals.set(bucket, n);
|
|
126
|
+
key = `${bucket}#${n}`;
|
|
127
|
+
}
|
|
128
|
+
map.set(key, { el, chain: own ? [...chain, own] : chain });
|
|
129
|
+
if (!el.selfClosing) stack.push({ name: el.name, id: own });
|
|
130
|
+
}
|
|
131
|
+
return map;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const before = index(beforeContent);
|
|
135
|
+
const after = index(afterContent);
|
|
136
|
+
const changes: PreservationChange[] = [];
|
|
137
|
+
/** An element inside an allowed subtree is itself allowed. */
|
|
138
|
+
const permitted = (entry: { chain: string[] } | undefined): boolean =>
|
|
139
|
+
Boolean(entry && entry.chain.some((id) => allow.has(id)));
|
|
140
|
+
|
|
141
|
+
for (const [key, beforeEntry] of before) {
|
|
142
|
+
if (permitted(beforeEntry)) continue;
|
|
143
|
+
const afterEntry = after.get(key);
|
|
144
|
+
if (!afterEntry) {
|
|
145
|
+
changes.push({
|
|
146
|
+
id: key,
|
|
147
|
+
element: beforeEntry.el.name,
|
|
148
|
+
attribute: '(element)',
|
|
149
|
+
before: 'present',
|
|
150
|
+
after: 'removed',
|
|
151
|
+
});
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const a = canonicalAttrs(beforeEntry.el.attrs);
|
|
155
|
+
const b = canonicalAttrs(afterEntry.el.attrs);
|
|
156
|
+
for (const attr of new Set([...Object.keys(a), ...Object.keys(b)])) {
|
|
157
|
+
if ((a[attr] ?? '') === (b[attr] ?? '')) continue;
|
|
158
|
+
changes.push({
|
|
159
|
+
id: key,
|
|
160
|
+
element: beforeEntry.el.name,
|
|
161
|
+
attribute: attr,
|
|
162
|
+
before: a[attr] ?? '(absent)',
|
|
163
|
+
after: b[attr] ?? '(absent)',
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
for (const [key, afterEntry] of after) {
|
|
168
|
+
if (permitted(afterEntry) || before.has(key)) continue;
|
|
169
|
+
changes.push({
|
|
170
|
+
id: key,
|
|
171
|
+
element: afterEntry.el.name,
|
|
172
|
+
attribute: '(element)',
|
|
173
|
+
before: 'absent',
|
|
174
|
+
after: 'added',
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
return changes;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function loadConfig(dir: string): ProjectConfig {
|
|
181
|
+
const configPath = path.join(dir, '.svg-asset.json');
|
|
182
|
+
if (!fs.existsSync(configPath)) return {};
|
|
183
|
+
try {
|
|
184
|
+
return JSON.parse(fs.readFileSync(configPath, 'utf-8')) as ProjectConfig;
|
|
185
|
+
} catch {
|
|
186
|
+
return {};
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function* walkDir(dir: string, ext: RegExp): Generator<string> {
|
|
191
|
+
if (!fs.existsSync(dir)) return;
|
|
192
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
193
|
+
const full = path.join(dir, entry.name);
|
|
194
|
+
if (entry.name.startsWith('.') || entry.name === 'node_modules') continue;
|
|
195
|
+
if (entry.isDirectory()) yield* walkDir(full, ext);
|
|
196
|
+
else if (ext.test(entry.name)) yield full;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// ---------------------------------------------------------------------------
|
|
201
|
+
// CLI
|
|
202
|
+
// ---------------------------------------------------------------------------
|
|
203
|
+
|
|
204
|
+
function readFlag(args: string[], name: string): string | undefined {
|
|
205
|
+
const i = args.indexOf(name);
|
|
206
|
+
return i >= 0 ? args[i + 1] : undefined;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function readAll(args: string[], name: string): string[] {
|
|
210
|
+
const out: string[] = [];
|
|
211
|
+
for (let i = 0; i < args.length; i++) if (args[i] === name && args[i + 1]) out.push(args[i + 1] as string);
|
|
212
|
+
return out;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export function main(argv: readonly string[] = process.argv.slice(2)): number {
|
|
216
|
+
const args = [...argv];
|
|
217
|
+
const jsonMode = args.includes('--json');
|
|
218
|
+
const quiet = args.includes('--quiet');
|
|
219
|
+
const deliveryRaw = readFlag(args, '--delivery');
|
|
220
|
+
if (deliveryRaw && !DELIVERY_MODES.includes(deliveryRaw as DeliveryMode)) {
|
|
221
|
+
process.stderr.write(
|
|
222
|
+
`[lint_svg_asset] unknown --delivery "${deliveryRaw}"; expected one of ${DELIVERY_MODES.join(', ')}\n`,
|
|
223
|
+
);
|
|
224
|
+
return 1;
|
|
225
|
+
}
|
|
226
|
+
const delivery = deliveryRaw as DeliveryMode | undefined;
|
|
227
|
+
|
|
228
|
+
// --- step 1.2: preservation readout -------------------------------------
|
|
229
|
+
const baseline = readFlag(args, '--baseline');
|
|
230
|
+
if (baseline) {
|
|
231
|
+
const files = readAll(args, '--file');
|
|
232
|
+
const after = files[0];
|
|
233
|
+
if (!after) {
|
|
234
|
+
process.stderr.write('[lint_svg_asset] --baseline needs a --file <after.svg> to compare against\n');
|
|
235
|
+
return 1;
|
|
236
|
+
}
|
|
237
|
+
if (!fs.existsSync(baseline) || !fs.existsSync(after)) {
|
|
238
|
+
process.stderr.write('[lint_svg_asset] --baseline or --file path not found\n');
|
|
239
|
+
return 1;
|
|
240
|
+
}
|
|
241
|
+
const allow = (readFlag(args, '--allow') ?? '').split(',').map((s) => s.trim()).filter(Boolean);
|
|
242
|
+
const changes = preservationReadout(
|
|
243
|
+
fs.readFileSync(baseline, 'utf-8'),
|
|
244
|
+
fs.readFileSync(after, 'utf-8'),
|
|
245
|
+
allow,
|
|
246
|
+
);
|
|
247
|
+
if (jsonMode) {
|
|
248
|
+
process.stdout.write(`${JSON.stringify(changes, null, 2)}\n`);
|
|
249
|
+
return changes.length ? 2 : 0;
|
|
250
|
+
}
|
|
251
|
+
if (!changes.length) {
|
|
252
|
+
if (!quiet) {
|
|
253
|
+
process.stdout.write(
|
|
254
|
+
`✅ lint_svg_asset --baseline: nothing changed outside ${allow.length} allowed id(s).\n`,
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
return 0;
|
|
258
|
+
}
|
|
259
|
+
for (const c of changes) {
|
|
260
|
+
process.stdout.write(
|
|
261
|
+
`❌ ${after} [svg-preserve-changed-outside-allowed] <${c.element} id="${c.id}"> ` +
|
|
262
|
+
`${c.attribute}: "${c.before}" → "${c.after}"\n`,
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
process.stdout.write(
|
|
266
|
+
`\nlint_svg_asset: ${changes.length} element change(s) outside the allowed set. ` +
|
|
267
|
+
'A surgical edit touches only what it declared.\n',
|
|
268
|
+
);
|
|
269
|
+
return 2;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// --- scanning -----------------------------------------------------------
|
|
273
|
+
const explicit = readAll(args, '--file');
|
|
274
|
+
const dirArg = readFlag(args, '--dir');
|
|
275
|
+
const targets: string[] = [];
|
|
276
|
+
let roots: string[] = [];
|
|
277
|
+
|
|
278
|
+
if (explicit.length) {
|
|
279
|
+
targets.push(...explicit.map((f) => path.resolve(f)));
|
|
280
|
+
roots = targets;
|
|
281
|
+
} else {
|
|
282
|
+
const scanDir = dirArg ? path.resolve(dirArg) : path.resolve(process.cwd(), 'src');
|
|
283
|
+
roots = [scanDir];
|
|
284
|
+
if (!fs.existsSync(scanDir)) {
|
|
285
|
+
// The two cases are NOT the same, and collapsing them into exit 0
|
|
286
|
+
// made a renamed or mistyped `--dir` report success in CI. An
|
|
287
|
+
// ABSENT DEFAULT root is the opt-in escape — a consumer with no
|
|
288
|
+
// `src/` has nothing to scan and must not red. An EXPLICIT `--dir`
|
|
289
|
+
// that does not resolve is a broken invocation, and this module's
|
|
290
|
+
// own header already says a gate that scanned no file is not a
|
|
291
|
+
// clean gate.
|
|
292
|
+
if (!quiet) process.stderr.write(`[lint_svg_asset] scan directory not found: ${scanDir}\n`);
|
|
293
|
+
if (dirArg) return 1;
|
|
294
|
+
process.stderr.write(
|
|
295
|
+
'This linter is opt-in. Run with --dir <path> or --file <a.svg> pointing at your assets.\n',
|
|
296
|
+
);
|
|
297
|
+
return 0;
|
|
298
|
+
}
|
|
299
|
+
for (const f of walkDir(scanDir, /\.(svg|html|htm)$/i)) targets.push(f);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const config = loadConfig(process.cwd());
|
|
303
|
+
const ignoreRules = new Set((config.ignoreRules ?? []).map((r) => r.toLowerCase()));
|
|
304
|
+
const ignoreGlobs = config.ignoreFiles ?? [];
|
|
305
|
+
const scanned = targets.filter((f) => !ignoreGlobs.some((g) => f.includes(g.replace('**', ''))));
|
|
306
|
+
|
|
307
|
+
try {
|
|
308
|
+
assertScanned({ gate: 'lint_svg_asset', scanned: scanned.length, units: 'SVG/HTML file(s)', roots });
|
|
309
|
+
} catch (exc) {
|
|
310
|
+
if (exc instanceof DeadScopeError) {
|
|
311
|
+
process.stderr.write(`❌ ${exc.message}\n`);
|
|
312
|
+
return 1;
|
|
313
|
+
}
|
|
314
|
+
throw exc;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const all: Finding[] = [];
|
|
318
|
+
for (const abs of scanned) {
|
|
319
|
+
const rel = path.relative(process.cwd(), abs);
|
|
320
|
+
try {
|
|
321
|
+
const content = fs.readFileSync(abs, 'utf-8');
|
|
322
|
+
const findings = /\.svg$/i.test(abs)
|
|
323
|
+
? scanSvg(content, rel, { delivery })
|
|
324
|
+
: scanHostHtml(content, rel, { delivery });
|
|
325
|
+
all.push(...findings.filter((f) => !ignoreRules.has(f.rule.toLowerCase())));
|
|
326
|
+
} catch (err) {
|
|
327
|
+
if (!quiet) process.stderr.write(`[lint_svg_asset] error: ${abs}: ${err}\n`);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (jsonMode) {
|
|
332
|
+
process.stdout.write(`${JSON.stringify(all, null, 2)}\n`);
|
|
333
|
+
return all.length > 0 ? 2 : 0;
|
|
334
|
+
}
|
|
335
|
+
if (!all.length) {
|
|
336
|
+
if (!quiet) {
|
|
337
|
+
process.stdout.write(
|
|
338
|
+
`✅ lint_svg_asset: clean — ${scanned.length} file(s) checked, no violations.\n`,
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
return 0;
|
|
342
|
+
}
|
|
343
|
+
const errors = all.filter((f) => f.severity === 'error');
|
|
344
|
+
const warnings = all.filter((f) => f.severity === 'warning');
|
|
345
|
+
const inert = all.filter((f) => f.severity === 'inert');
|
|
346
|
+
for (const f of all) {
|
|
347
|
+
const icon = f.severity === 'error' ? '❌' : f.severity === 'warning' ? '⚠️ ' : 'ℹ️ ';
|
|
348
|
+
process.stdout.write(`${icon} ${f.file}:${f.line} [${f.rule}] ${f.snippet}\n`);
|
|
349
|
+
}
|
|
350
|
+
process.stdout.write(
|
|
351
|
+
`\nlint_svg_asset: ${errors.length} error(s), ${warnings.length} warning(s), ${inert.length} inert. ` +
|
|
352
|
+
'Use svg-asset-disable-next-line <rule> -- reason or .svg-asset.json to suppress; ' +
|
|
353
|
+
'svg-safety-* findings yield only to .svg-asset.json, never to a marker in the file. ' +
|
|
354
|
+
'Advisory: an "inert" row is not a clean row — the same file inlined tomorrow is an error.\n',
|
|
355
|
+
);
|
|
356
|
+
return 2;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/* c8 ignore start — entrypoint guard, exercised by the CLI not by the tests */
|
|
360
|
+
const invokedDirectly =
|
|
361
|
+
typeof process !== 'undefined' &&
|
|
362
|
+
Array.isArray(process.argv) &&
|
|
363
|
+
/lint_svg_asset\.(ts|js)$/.test(process.argv[1] ?? '');
|
|
364
|
+
if (invokedDirectly) process.exit(main());
|
|
365
|
+
/* c8 ignore stop */
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Reports an acceptance criterion ticked over its own "NOT met".
|
|
4
|
+
*
|
|
5
|
+
* A `- [x] AC-<n>` item whose own text says a half of it `is NOT met` is a
|
|
6
|
+
* contradiction a reader of the checkbox never sees: the glyph says done, the
|
|
7
|
+
* prose says not. The honest glyph is `[~]`, which carries the unmet half as a
|
|
8
|
+
* deferral rather than hiding it under a tick.
|
|
9
|
+
*
|
|
10
|
+
* The criterion's text is the bullet line plus its indented continuation lines,
|
|
11
|
+
* up to a blank line, a less-indented line or the next checkbox. Fenced code is
|
|
12
|
+
* skipped, so a quoted example is not a finding. The match is the literal
|
|
13
|
+
* `NOT met` — upper-case on purpose, because that is how an author marks the
|
|
14
|
+
* unmet half, and a lower-case "not met" inside an explanation is prose.
|
|
15
|
+
*
|
|
16
|
+
* Usage:
|
|
17
|
+
* ./scripts-run src/scripts/lint_ticked_unmet_criteria
|
|
18
|
+
* ./scripts-run src/scripts/lint_ticked_unmet_criteria --root <repo>
|
|
19
|
+
*
|
|
20
|
+
* Scans every `*.md` under the roadmap tree, archive included: an archived
|
|
21
|
+
* roadmap is exactly where a contradictory tick outlives the session that
|
|
22
|
+
* made it.
|
|
23
|
+
*
|
|
24
|
+
* Exit codes: 0 no hit · 1 at least one hit · 2 usage error.
|
|
25
|
+
*/
|
|
26
|
+
import * as fs from 'node:fs';
|
|
27
|
+
import * as path from 'node:path';
|
|
28
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
29
|
+
|
|
30
|
+
import { reportScanned } from './_lib/scan_scope.js';
|
|
31
|
+
|
|
32
|
+
interface Hit {
|
|
33
|
+
file: string;
|
|
34
|
+
line: number;
|
|
35
|
+
criterion: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const TICKED_AC_RE = /^([ \t]*)[-*][ \t]+\[[xX]\][ \t]+(AC-[\w.-]+)/;
|
|
39
|
+
const CHECKBOX_RE = /^[ \t]*[-*][ \t]+\[[ xX~-]\]/;
|
|
40
|
+
const FENCE_RE = /^[ \t]*(```|~~~)/;
|
|
41
|
+
const UNMET = 'NOT met';
|
|
42
|
+
|
|
43
|
+
function _indent(line: string): number {
|
|
44
|
+
return (/^[ \t]*/.exec(line)?.[0] ?? '').length;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function scanText(text: string, file: string): Hit[] {
|
|
48
|
+
const lines = text.split('\n');
|
|
49
|
+
const hits: Hit[] = [];
|
|
50
|
+
let inFence = false;
|
|
51
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
52
|
+
const line = lines[i] as string;
|
|
53
|
+
if (FENCE_RE.test(line)) {
|
|
54
|
+
inFence = !inFence;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (inFence) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
const m = TICKED_AC_RE.exec(line);
|
|
61
|
+
if (!m) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const base = (m[1] as string).length;
|
|
65
|
+
const block = [line];
|
|
66
|
+
for (let j = i + 1; j < lines.length; j += 1) {
|
|
67
|
+
const next = lines[j] as string;
|
|
68
|
+
if (next.trim() === '' || CHECKBOX_RE.test(next) || FENCE_RE.test(next) || _indent(next) <= base) {
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
block.push(next);
|
|
72
|
+
}
|
|
73
|
+
if (block.join('\n').includes(UNMET)) {
|
|
74
|
+
hits.push({ file, line: i + 1, criterion: m[2] as string });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return hits;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function _walk(dir: string): string[] {
|
|
81
|
+
let entries: fs.Dirent[];
|
|
82
|
+
try {
|
|
83
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
84
|
+
} catch {
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
const out: string[] = [];
|
|
88
|
+
for (const e of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
89
|
+
const full = path.join(dir, e.name);
|
|
90
|
+
if (e.isDirectory()) {
|
|
91
|
+
out.push(..._walk(full));
|
|
92
|
+
} else if (e.isFile() && e.name.endsWith('.md')) {
|
|
93
|
+
out.push(full);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return out;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function scanTree(root: string): { hits: Hit[]; scanned: number } {
|
|
100
|
+
const files = _walk(path.join(root, 'agents', 'roadmaps'));
|
|
101
|
+
const hits: Hit[] = [];
|
|
102
|
+
for (const abs of files) {
|
|
103
|
+
const rel = path.relative(root, abs).split(path.sep).join('/');
|
|
104
|
+
hits.push(...scanText(fs.readFileSync(abs, 'utf8'), rel));
|
|
105
|
+
}
|
|
106
|
+
return { hits, scanned: files.length };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const _DEFAULT_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
110
|
+
|
|
111
|
+
function main(argv: string[] = process.argv.slice(2)): number {
|
|
112
|
+
let root = _DEFAULT_ROOT;
|
|
113
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
114
|
+
const arg = argv[i];
|
|
115
|
+
if (arg === '--root') {
|
|
116
|
+
const v = argv[i + 1];
|
|
117
|
+
if (v === undefined) {
|
|
118
|
+
process.stderr.write('lint_ticked_unmet_criteria: --root requires a value\n');
|
|
119
|
+
return 2;
|
|
120
|
+
}
|
|
121
|
+
root = path.resolve(v);
|
|
122
|
+
i += 1;
|
|
123
|
+
} else {
|
|
124
|
+
process.stderr.write(`lint_ticked_unmet_criteria: unknown argument: ${String(arg)}\n`);
|
|
125
|
+
return 2;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const { hits, scanned } = scanTree(root);
|
|
129
|
+
reportScanned({
|
|
130
|
+
gate: 'lint_ticked_unmet_criteria',
|
|
131
|
+
scanned,
|
|
132
|
+
units: 'roadmap file(s)',
|
|
133
|
+
roots: ['agents/roadmaps'],
|
|
134
|
+
allowEmpty: 'EMPTY_VALID: a checkout with no roadmap has no criterion to tick',
|
|
135
|
+
});
|
|
136
|
+
if (hits.length === 0) {
|
|
137
|
+
process.stdout.write(`✅ lint_ticked_unmet_criteria: ${String(scanned)} roadmap file(s), no criterion ticked over "${UNMET}".\n`);
|
|
138
|
+
return 0;
|
|
139
|
+
}
|
|
140
|
+
process.stderr.write(
|
|
141
|
+
`❌ lint_ticked_unmet_criteria: ${String(hits.length)} criterion/criteria ticked [x] over their own "${UNMET}":\n`,
|
|
142
|
+
);
|
|
143
|
+
for (const h of hits) {
|
|
144
|
+
process.stderr.write(` ${h.file}:${String(h.line)} · ${h.criterion}\n`);
|
|
145
|
+
}
|
|
146
|
+
process.stderr.write('\n The unmet half is a deferral: use `[~]` and carry it, or meet it.\n');
|
|
147
|
+
return 1;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (process.argv[1] !== undefined) {
|
|
151
|
+
try {
|
|
152
|
+
const here = fs.realpathSync(fileURLToPath(import.meta.url));
|
|
153
|
+
const argv1 = fs.realpathSync(path.resolve(process.argv[1]));
|
|
154
|
+
if (here === argv1) {
|
|
155
|
+
process.exit(main());
|
|
156
|
+
}
|
|
157
|
+
} catch {
|
|
158
|
+
if (import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href) {
|
|
159
|
+
process.exit(main());
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export { scanText, scanTree, main };
|
|
165
|
+
export type { Hit };
|
|
@@ -28,6 +28,9 @@
|
|
|
28
28
|
* TIERS are untouched; only the description of what MEDIUM covers now matches
|
|
29
29
|
* the code. Re-tiering the locked model is a separate decision, recorded as
|
|
30
30
|
* unresolved in agents/evidence/analysis/workflow-security-net-degraded-decision.md.
|
|
31
|
+
* The CI INVOCATION is decided there too: since 2026-10-07 consistency.yml runs
|
|
32
|
+
* this gate under `--strict` (AI council, 2/2), so a HIGH fails a pull request;
|
|
33
|
+
* the tiers are unchanged.
|
|
31
34
|
*
|
|
32
35
|
* Script-injection detection (regex-based) is intentionally deferred — it
|
|
33
36
|
* requires an AST-aware pass to avoid false positives on quoted / escaped
|
|
@@ -805,7 +808,9 @@ export function main(argv?: string[]): number {
|
|
|
805
808
|
);
|
|
806
809
|
if (high.length || medium.length) {
|
|
807
810
|
process.stdout.write(
|
|
808
|
-
|
|
811
|
+
args.strict
|
|
812
|
+
? ' (--strict — HIGH findings fail this run; MEDIUM stays advisory)\n'
|
|
813
|
+
: ' (warn-only — run with --strict to make HIGH findings block CI)\n',
|
|
809
814
|
);
|
|
810
815
|
} else {
|
|
811
816
|
process.stdout.write(' no non-allowlisted findings\n');
|
|
@@ -813,6 +818,12 @@ export function main(argv?: string[]): number {
|
|
|
813
818
|
}
|
|
814
819
|
|
|
815
820
|
if (args.strict && high.length) {
|
|
821
|
+
if (args.quiet) {
|
|
822
|
+
// --quiet suppresses the report; a failing run still names its cause.
|
|
823
|
+
process.stderr.write(
|
|
824
|
+
`workflow-security: ${high.length} HIGH under --strict — rerun without --quiet for the findings\n`,
|
|
825
|
+
);
|
|
826
|
+
}
|
|
816
827
|
return 1;
|
|
817
828
|
}
|
|
818
829
|
return 0;
|
|
@@ -495,6 +495,11 @@ export const RANKER_LABELS: Readonly<Record<string, RankOptions>> = {
|
|
|
495
495
|
headings: { includeHeadings: true },
|
|
496
496
|
idf: { idfWeighting: true },
|
|
497
497
|
'idf+when-to-use': { idfWeighting: true, includeWhenToUse: true },
|
|
498
|
+
// `road-to-a-ranker-whose-ties-break-on-signal` Phase 3: the order inside a
|
|
499
|
+
// block of equal integer scores, alone and over the one weighting that
|
|
500
|
+
// makes the unrounded score vary.
|
|
501
|
+
ties: { tieBreakUnrounded: true },
|
|
502
|
+
'idf+ties': { idfWeighting: true, tieBreakUnrounded: true },
|
|
498
503
|
};
|
|
499
504
|
|
|
500
505
|
/**
|
|
@@ -617,7 +617,7 @@ export function runEndpoints(corpusDir: string): EndpointResult[] {
|
|
|
617
617
|
let deliveries = 0;
|
|
618
618
|
let unequal = 0;
|
|
619
619
|
for (const c of positives) {
|
|
620
|
-
const injection = buildInjection(REPO_ROOT, c.prompt, c.openFiles, null, new Set());
|
|
620
|
+
const injection = buildInjection(REPO_ROOT, c.prompt, c.openFiles, null, new Set(), false);
|
|
621
621
|
if (injection === null) continue;
|
|
622
622
|
for (const id of injection.rules) {
|
|
623
623
|
const projected = loadRuleBody(REPO_ROOT, id);
|
|
@@ -803,12 +803,12 @@ export function runSelftest(corpusDir: string): SelftestCase[] {
|
|
|
803
803
|
const probe = cases.find(
|
|
804
804
|
(c) =>
|
|
805
805
|
c.label === 'positive' &&
|
|
806
|
-
buildInjection(REPO_ROOT, c.prompt, c.openFiles, null, new Set()) !== null,
|
|
806
|
+
buildInjection(REPO_ROOT, c.prompt, c.openFiles, null, new Set(), false) !== null,
|
|
807
807
|
);
|
|
808
808
|
const injection =
|
|
809
809
|
probe === undefined
|
|
810
810
|
? null
|
|
811
|
-
: buildInjection(REPO_ROOT, probe.prompt, probe.openFiles, null, new Set());
|
|
811
|
+
: buildInjection(REPO_ROOT, probe.prompt, probe.openFiles, null, new Set(), false);
|
|
812
812
|
if (injection === null || injection.rules.length === 0) {
|
|
813
813
|
out.push({
|
|
814
814
|
endpoint: 'a-delivery',
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* deterministic state file the rule body can cite as the source of
|
|
11
11
|
* truth for "do I need to prompt the user about /onboard?".
|
|
12
12
|
*
|
|
13
|
-
* Output is written to `agents/
|
|
13
|
+
* Output is written to `agents/state/onboarding-gate.json` with:
|
|
14
14
|
* {
|
|
15
15
|
* "required": <bool>, // true → rule fires on first turn
|
|
16
16
|
* "reason": "<string>", // why this state was set
|
|
@@ -33,8 +33,9 @@ import path from "node:path";
|
|
|
33
33
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
34
34
|
|
|
35
35
|
// Re-use the shared atomic-write helper so concerns honour the single
|
|
36
|
-
// `agents/
|
|
37
|
-
//
|
|
36
|
+
// `agents/state/.dispatcher.lock` discipline (hook-architecture-v1.md,
|
|
37
|
+
// Concurrency, Phase 7.4) — the lock sits beside THIS hook's own target, not
|
|
38
|
+
// the fixed `agents/runtime/state/` path the discipline cites generally.
|
|
38
39
|
import { atomic_write_json } from "./hooks/state_io.js";
|
|
39
40
|
import { readHookStdin } from "./hooks/hook_stdin.js";
|
|
40
41
|
|
|
@@ -153,11 +154,11 @@ function _now_iso(): string {
|
|
|
153
154
|
}
|
|
154
155
|
|
|
155
156
|
/**
|
|
156
|
-
* Write `agents/
|
|
157
|
+
* Write `agents/state/onboarding-gate.json` atomically.
|
|
157
158
|
*
|
|
158
|
-
* Uses the shared `agents/
|
|
159
|
+
* Uses the shared `agents/state/.dispatcher.lock` so concurrent
|
|
159
160
|
* dispatcher invocations across platforms cannot tear the file
|
|
160
|
-
* (hook-architecture-v1.md
|
|
161
|
+
* (hook-architecture-v1.md, Concurrency, Phase 7.4).
|
|
161
162
|
*/
|
|
162
163
|
function _write_state(
|
|
163
164
|
consumer_root: string,
|