@event4u/agent-config 9.9.0 → 9.10.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/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +153 -194
- package/README.md +1 -1
- package/dist/agent-src/commands/agent-status.md +12 -11
- package/dist/agent-src/commands/agents/user/accept.md +115 -30
- package/dist/agent-src/commands/agents/user/delete.md +147 -0
- package/dist/agent-src/commands/agents/user/review.md +65 -28
- package/dist/agent-src/commands/agents/user/show.md +82 -29
- package/dist/agent-src/commands/agents/user/update.md +2 -2
- package/dist/agent-src/commands/agents/user.md +16 -3
- package/dist/agent-src/commands/check-current-md.md +0 -10
- package/dist/agent-src/commands/condense.md +28 -97
- package/dist/agent-src/commands/cost/report.md +7 -0
- package/dist/agent-src/commands/fix/portability.md +0 -8
- package/dist/agent-src/commands/fix/refs.md +0 -8
- package/dist/agent-src/commands/humanize.md +2 -2
- package/dist/agent-src/commands/jira-ticket.md +1 -1
- package/dist/agent-src/commands/memory/load.md +11 -0
- package/dist/agent-src/commands/optimize/skills.md +1 -1
- package/dist/agent-src/commands/pr/create.md +4 -4
- package/dist/agent-src/commands/profile/show.md +3 -3
- package/dist/agent-src/commands/rule-compliance-audit.md +5 -4
- package/dist/agent-src/commands/security-audit-config.md +1 -1
- package/dist/agent-src/commands/sync/gitignore/fix.md +1 -1
- package/dist/agent-src/commands/tdd.md +21 -0
- package/dist/agent-src/commands/team/delegate.md +2 -2
- package/dist/agent-src/commands/team-knowledge/bootstrap.md +9 -8
- package/dist/agent-src/commands/team-knowledge/consolidate.md +8 -7
- package/dist/agent-src/commands/team.md +4 -1
- package/dist/agent-src/commands/upstream-contribute.md +0 -1
- package/dist/agent-src/contexts/authority/commit-mechanics.md +7 -0
- package/dist/agent-src/contexts/authority/destructive-mechanics.md +16 -0
- package/dist/agent-src/contexts/authority/scope-mechanics.md +61 -0
- package/dist/agent-src/contexts/communication/rules-auto/reply-close-mechanics.md +20 -18
- package/dist/agent-src/contexts/communication/rules-auto/skill-quality-mechanics.md +1 -1
- package/dist/agent-src/contexts/communication/rules-auto/slash-command-routing-policy-mechanics.md +1 -1
- package/dist/agent-src/contexts/communication/rules-auto/source-of-truth-mechanics.md +9 -10
- package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +1 -1
- package/dist/agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +11 -0
- package/dist/agent-src/contexts/contracts/artifact-engagement-flow.md +26 -15
- package/dist/agent-src/contexts/contracts/command-suggestion-flow.md +3 -0
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +67 -37
- package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +1 -1
- package/dist/agent-src/contexts/execution/autonomy-examples.md +1 -1
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +7 -6
- package/dist/agent-src/contexts/execution/evidence-discipline.md +92 -77
- package/dist/agent-src/contexts/execution/orchestration-benchmark-gate.md +22 -21
- package/dist/agent-src/contexts/execution/orchestration-telemetry.md +24 -0
- package/dist/agent-src/contexts/execution/project-intelligence.md +122 -103
- package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +23 -21
- package/dist/agent-src/contexts/execution/subagent-response-contract.md +5 -5
- package/dist/agent-src/contexts/execution/subagent-routing.md +11 -0
- package/dist/agent-src/contexts/execution/subagent-spawn-contract.md +13 -13
- package/dist/agent-src/contexts/execution/subagent-steering.md +36 -34
- package/dist/agent-src/contexts/execution/toolchain-resolver.md +1 -1
- package/dist/agent-src/contexts/execution/user-memory-channels.md +189 -0
- package/dist/agent-src/contexts/execution/verification-mechanics.md +9 -0
- package/dist/agent-src/contexts/model-recommendations.md +3 -2
- package/dist/agent-src/contexts/subagent-configuration.md +3 -3
- package/dist/agent-src/ghostwriter/README.md +2 -2
- package/dist/agent-src/packs/README.md +1 -1
- package/dist/agent-src/personas/README.md +5 -5
- package/dist/agent-src/personas/_template-specialist/persona.md +3 -3
- package/dist/agent-src/personas/backend-architect.md +24 -23
- package/dist/agent-src/personas/eloquent-tamer.md +30 -30
- package/dist/agent-src/personas/frontend-engineer.md +30 -30
- package/dist/agent-src/personas/product-owner.md +41 -38
- package/dist/agent-src/personas/qa.md +13 -13
- package/dist/agent-src/personas/security-engineer.md +22 -22
- package/dist/agent-src/presets/README.md +3 -3
- package/dist/agent-src/profiles/README.md +3 -3
- package/dist/agent-src/rules/active-remediation.md +2 -2
- package/dist/agent-src/rules/artifact-engagement-recording.md +4 -4
- package/dist/agent-src/rules/ask-when-uncertain.md +0 -4
- package/dist/agent-src/rules/augment-edit-discipline.md +1 -1
- package/dist/agent-src/rules/broken-access-control.md +4 -4
- package/dist/agent-src/rules/code-comment-discipline.md +1 -1
- package/dist/agent-src/rules/code-provenance.md +2 -2
- package/dist/agent-src/rules/commit-policy.md +4 -9
- package/dist/agent-src/rules/communication-through-line.md +5 -5
- package/dist/agent-src/rules/decision-revisit-gate.md +1 -1
- package/dist/agent-src/rules/doc-screenshot-hygiene.md +1 -1
- package/dist/agent-src/rules/domain-adoption-policy.md +1 -1
- package/dist/agent-src/rules/domain-safety-pii.md +1 -1
- package/dist/agent-src/rules/external-code-graph-interop.md +1 -1
- package/dist/agent-src/rules/fast-path-marker-visibility.md +43 -7
- package/dist/agent-src/rules/finance-safety-floor.md +1 -1
- package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +3 -3
- package/dist/agent-src/rules/history-discipline.md +1 -1
- package/dist/agent-src/rules/legal-safety-floor.md +1 -1
- package/dist/agent-src/rules/lethal-trifecta-guard.md +5 -5
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +10 -8
- package/dist/agent-src/rules/media-governance-routing.md +13 -13
- package/dist/agent-src/rules/media-sync-ground-truth.md +29 -11
- package/dist/agent-src/rules/no-cheap-questions.md +7 -7
- package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +29 -18
- package/dist/agent-src/rules/non-destructive-by-default.md +5 -23
- package/dist/agent-src/rules/onboarding-gate.md +14 -4
- package/dist/agent-src/rules/persona-governance.md +2 -2
- package/dist/agent-src/rules/prefer-enums-over-literals.md +9 -9
- package/dist/agent-src/rules/preservation-guard.md +10 -2
- package/dist/agent-src/rules/question-not-instruction.md +1 -1
- package/dist/agent-src/rules/roadmap-progress-sync.md +6 -6
- package/dist/agent-src/rules/rule-type-governance.md +1 -1
- package/dist/agent-src/rules/scale-discipline.md +1 -1
- package/dist/agent-src/rules/scope-control.md +1 -1
- package/dist/agent-src/rules/secret-vcs-guard.md +1 -1
- package/dist/agent-src/rules/security-sensitive-stop.md +17 -11
- package/dist/agent-src/rules/senior-engineering-discipline.md +17 -17
- package/dist/agent-src/rules/session-canary.md +1 -1
- package/dist/agent-src/rules/skill-quality.md +1 -1
- package/dist/agent-src/rules/source-confidentiality.md +21 -19
- package/dist/agent-src/rules/source-of-truth.md +6 -5
- package/dist/agent-src/rules/spreadsheet-source-quality.md +2 -2
- package/dist/agent-src/rules/strategy-safety-floor.md +1 -1
- package/dist/agent-src/rules/think-before-action.md +5 -5
- package/dist/agent-src/rules/token-budget-discipline.md +5 -3
- package/dist/agent-src/rules/token-efficiency.md +2 -2
- package/dist/agent-src/rules/untrusted-input-defense.md +4 -4
- package/dist/agent-src/rules/user-interaction.md +12 -0
- package/dist/agent-src/rules/verify-before-complete.md +4 -24
- package/dist/agent-src/skills/adversarial-review/SKILL.md +2 -2
- package/dist/agent-src/skills/agent-security-review/SKILL.md +52 -45
- package/dist/agent-src/skills/agents-md-thin-root/SKILL.md +2 -2
- package/dist/agent-src/skills/ai-code-blindspots/SKILL.md +20 -20
- package/dist/agent-src/skills/ai-council/SKILL.md +185 -128
- package/dist/agent-src/skills/analysis-skill-router/SKILL.md +3 -3
- package/dist/agent-src/skills/api-endpoint/SKILL.md +2 -2
- package/dist/agent-src/skills/artisan-commands/SKILL.md +2 -2
- package/dist/agent-src/skills/async-python-patterns/SKILL.md +8 -7
- package/dist/agent-src/skills/authz-review/SKILL.md +16 -15
- package/dist/agent-src/skills/aws-infrastructure/SKILL.md +5 -5
- package/dist/agent-src/skills/blade-ui/SKILL.md +1 -1
- package/dist/agent-src/skills/bug-analyzer/SKILL.md +30 -12
- package/dist/agent-src/skills/code-intelligence/SKILL.md +0 -1
- package/dist/agent-src/skills/code-intelligence/evals/triggers.json +52 -0
- package/dist/agent-src/skills/code-review/SKILL.md +6 -6
- package/dist/agent-src/skills/command-routing/SKILL.md +5 -4
- package/dist/agent-src/skills/composer-packages/SKILL.md +2 -2
- package/dist/agent-src/skills/condense-memory/SKILL.md +43 -41
- package/dist/agent-src/skills/context-document/SKILL.md +23 -21
- package/dist/agent-src/skills/copilot-config/SKILL.md +6 -1
- package/dist/agent-src/skills/decision-record/SKILL.md +20 -18
- package/dist/agent-src/skills/design-intelligence/SKILL.md +4 -4
- package/dist/agent-src/skills/design-review/SKILL.md +15 -14
- package/dist/agent-src/skills/design-system-capture/reference/design-system-json.md +28 -25
- package/dist/agent-src/skills/devcontainer/SKILL.md +2 -2
- package/dist/agent-src/skills/docker/SKILL.md +1 -1
- package/dist/agent-src/skills/docx-authoring/evals/triggers.json +52 -0
- package/dist/agent-src/skills/emit-tickets/SKILL.md +2 -2
- package/dist/agent-src/skills/error-handling-patterns/SKILL.md +1 -1
- package/dist/agent-src/skills/estimate-ticket/SKILL.md +2 -2
- package/dist/agent-src/skills/evaluate-llm-feature/SKILL.md +0 -1
- package/dist/agent-src/skills/evaluate-llm-feature/evals/triggers.json +52 -0
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +6 -5
- package/dist/agent-src/skills/feature-planning/SKILL.md +2 -2
- package/dist/agent-src/skills/finishing-a-development-branch/SKILL.md +3 -3
- package/dist/agent-src/skills/flux/SKILL.md +1 -1
- package/dist/agent-src/skills/frontend-render-security/SKILL.md +13 -13
- package/dist/agent-src/skills/git-workflow/SKILL.md +33 -33
- package/dist/agent-src/skills/grafana/SKILL.md +5 -0
- package/dist/agent-src/skills/humanizer/SKILL.md +83 -66
- package/dist/agent-src/skills/humanizer/data/patterns.md +14 -14
- package/dist/agent-src/skills/humanizer/references/anti-aiisms.md +4 -4
- package/dist/agent-src/skills/judge-artifact-completeness/SKILL.md +82 -37
- package/dist/agent-src/skills/judge-bug-hunter/SKILL.md +17 -5
- package/dist/agent-src/skills/judge-injection-defense/SKILL.md +63 -25
- package/dist/agent-src/skills/judge-security-auditor/SKILL.md +2 -0
- package/dist/agent-src/skills/judge-synthesis/SKILL.md +72 -28
- package/dist/agent-src/skills/laravel-horizon/SKILL.md +5 -0
- package/dist/agent-src/skills/laravel-mail/SKILL.md +5 -4
- package/dist/agent-src/skills/laravel-middleware/SKILL.md +5 -4
- package/dist/agent-src/skills/laravel-notifications/SKILL.md +10 -9
- package/dist/agent-src/skills/laravel-pennant/SKILL.md +1 -1
- package/dist/agent-src/skills/laravel-pulse/SKILL.md +9 -8
- package/dist/agent-src/skills/laravel-reverb/SKILL.md +6 -5
- package/dist/agent-src/skills/laravel-scheduling/SKILL.md +6 -1
- package/dist/agent-src/skills/laravel-validation/SKILL.md +12 -0
- package/dist/agent-src/skills/launch-readiness/SKILL.md +1 -1
- package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +7 -7
- package/dist/agent-src/skills/learning-tutor/SKILL.md +44 -43
- package/dist/agent-src/skills/learning-tutor/evals/triggers.json +52 -0
- package/dist/agent-src/skills/license-compliance-audit/SKILL.md +7 -7
- package/dist/agent-src/skills/license-compliance-borrow-check/SKILL.md +3 -3
- package/dist/agent-src/skills/license-compliance-credits/SKILL.md +4 -4
- package/dist/agent-src/skills/llm-provider-knowledge/SKILL.md +0 -1
- package/dist/agent-src/skills/memory-consolidation/SKILL.md +69 -64
- package/dist/agent-src/skills/motion-choreographer/SKILL.md +6 -6
- package/dist/agent-src/skills/pdf-tools/evals/triggers.json +52 -0
- package/dist/agent-src/skills/performance-analysis/SKILL.md +7 -3
- package/dist/agent-src/skills/persona-improvement/SKILL.md +0 -2
- package/dist/agent-src/skills/persona-improvement/evals/triggers.json +52 -0
- package/dist/agent-src/skills/php-coder/SKILL.md +10 -0
- package/dist/agent-src/skills/prediction-pool-optimizer/SKILL.md +129 -120
- package/dist/agent-src/skills/prediction-pool-optimizer/reference/ev-fixtures.md +36 -35
- package/dist/agent-src/skills/prediction-pool-optimizer/reference/odds-and-bonus.md +45 -41
- package/dist/agent-src/skills/project-analysis-core/SKILL.md +4 -4
- package/dist/agent-src/skills/project-analysis-hypothesis-driven/SKILL.md +3 -3
- package/dist/agent-src/skills/project-analysis-react/SKILL.md +1 -1
- package/dist/agent-src/skills/project-analysis-symfony/SKILL.md +1 -1
- package/dist/agent-src/skills/project-analysis-zend-laminas/SKILL.md +2 -2
- package/dist/agent-src/skills/prompt-engineering-patterns/SKILL.md +1 -1
- package/dist/agent-src/skills/prompt-validator/SKILL.md +39 -39
- package/dist/agent-src/skills/quality-tools/SKILL.md +15 -15
- package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +55 -19
- package/dist/agent-src/skills/react-shadcn-ui/reference/registry.md +29 -27
- package/dist/agent-src/skills/readme-writing-package/SKILL.md +2 -2
- package/dist/agent-src/skills/reasoning-orchestrator/SKILL.md +25 -25
- package/dist/agent-src/skills/recursive-verification/SKILL.md +6 -5
- package/dist/agent-src/skills/refine-prompt/SKILL.md +1 -1
- package/dist/agent-src/skills/refine-ticket/SKILL.md +20 -2
- package/dist/agent-src/skills/repomix-packer/SKILL.md +1 -1
- package/dist/agent-src/skills/requesting-code-review/SKILL.md +2 -2
- package/dist/agent-src/skills/roadmap-management/SKILL.md +80 -66
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +84 -77
- package/dist/agent-src/skills/rule-refactor/SKILL.md +1 -1
- package/dist/agent-src/skills/screenshot-hygiene/evals/triggers.json +52 -0
- package/dist/agent-src/skills/security-audit/SKILL.md +26 -9
- package/dist/agent-src/skills/security-maturity-assessment/SKILL.md +38 -16
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +14 -11
- package/dist/agent-src/skills/skill-writing/SKILL.md +9 -8
- package/dist/agent-src/skills/song-to-script/SKILL.md +93 -85
- package/dist/agent-src/skills/sql-writing/SKILL.md +2 -2
- package/dist/agent-src/skills/stakeholder-tradeoff/SKILL.md +4 -3
- package/dist/agent-src/skills/standards-from-config/SKILL.md +61 -43
- package/dist/agent-src/skills/subagent-orchestration/SKILL.md +22 -8
- package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +28 -2
- package/dist/agent-src/skills/supply-chain-intake/SKILL.md +13 -13
- package/dist/agent-src/skills/systematic-debugging/SKILL.md +22 -21
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +1 -1
- package/dist/agent-src/skills/technical-specification/SKILL.md +5 -0
- package/dist/agent-src/skills/terraform/SKILL.md +2 -2
- package/dist/agent-src/skills/terragrunt/SKILL.md +8 -8
- package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +1 -1
- package/dist/agent-src/skills/threat-modeling/SKILL.md +19 -13
- package/dist/agent-src/skills/universal-project-analysis/SKILL.md +1 -1
- package/dist/agent-src/skills/upstream-contribute/SKILL.md +0 -1
- package/dist/agent-src/skills/using-git-worktrees/SKILL.md +9 -9
- package/dist/agent-src/skills/validate-feature-fit/SKILL.md +3 -1
- package/dist/agent-src/skills/verify-completion-evidence/SKILL.md +4 -6
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +67 -61
- package/dist/agent-src/skills/video-director/SKILL.md +7 -7
- package/dist/agent-src/skills/worktree-lifecycle/SKILL.md +3 -3
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/contexts/knowledge-pages.md +47 -45
- package/dist/agent-src/templates/contexts/lesson-card.md +2 -2
- package/dist/agent-src/templates/contexts/tenant-boundaries.md +2 -2
- package/dist/agent-src/templates/contexts.md +1 -1
- package/dist/agent-src/templates/features.md +1 -1
- package/dist/agent-src/templates/roadmaps.md +125 -116
- package/dist/agent-src/templates/rule.md +2 -1
- package/dist/agent-src/templates/scripts/pr_risk_review.ts +0 -0
- package/dist/agent-src/templates/scripts/telemetry/aggregator.ts +0 -0
- package/dist/agent-src/templates/scripts/tier_usage_report.ts +2 -2
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +2 -2
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/review.ts +1 -1
- package/dist/agent-src/user-types/README.md +8 -8
- package/dist/agent-src/user-types/galabau-field-crew.md +34 -33
- package/dist/agent-src/user-types/metalworking-shop.md +35 -34
- package/dist/agent-src/user-types/truck-driver.md +22 -20
- package/dist/cli/python/workspace_roles.js +2 -2
- package/dist/cli/python/workspace_roles.js.map +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +88 -62
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +6 -5
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +5 -4
- package/dist/hooks/dispatch.js +186 -12
- package/dist/install/install.mjs +8 -0
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +1199 -857
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/compile_time_toggles.js +48 -0
- package/dist/scripts/_lib/compile_time_toggles.js.map +1 -0
- package/dist/scripts/condense.js +234 -217
- package/dist/scripts/condense.js.map +1 -1
- package/dist/server/schemas/settings.js +4 -0
- package/dist/server/schemas/settings.js.map +1 -1
- package/dist/shared/userMd/utils.js +30 -0
- package/dist/shared/userMd/utils.js.map +1 -1
- package/dist/ui/assets/index-BpSQt5vm.js.map +1 -1
- package/docs/guidelines/agent-infra/api-cost-levers.md +56 -5
- package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +93 -33
- package/package.json +1 -1
- package/src/agent-src/templates/scripts/pr_risk_review.ts +0 -0
- package/src/agent-src/templates/scripts/telemetry/aggregator.ts +0 -0
- package/src/agent-src/templates/scripts/tier_usage_report.ts +2 -2
- package/src/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +2 -2
- package/src/agent-src/templates/scripts/work_engine/directives/ui/review.ts +1 -1
- package/src/config/agent-settings.template.yml +32 -2
- package/src/config/ci-local-parity.yml +142 -0
- package/src/config/gate-coverage.yml +127 -0
- package/src/config/preamble-payload-budget.json +44 -0
- package/src/scripts/_cli/cmd_doctor.ts +78 -2
- package/src/scripts/_lib/agent_user_profile.ts +381 -0
- package/src/scripts/_lib/agents_overlay.ts +9 -0
- package/src/scripts/_lib/anchor_eval.ts +311 -0
- package/src/scripts/_lib/cc_transcript.ts +316 -0
- package/src/scripts/_lib/compile_time_toggles.ts +79 -0
- package/src/scripts/_lib/confusables.ts +101 -0
- package/src/scripts/_lib/duplicate_scope_census.ts +77 -0
- package/src/scripts/_lib/managed_agents_folder.ts +181 -0
- package/src/scripts/_lib/payload_hash_drift.ts +126 -0
- package/src/scripts/_lib/preservation_migration.ts +291 -0
- package/src/scripts/_lib/retrieval_sanitize.ts +166 -2
- package/src/scripts/_lib/scan_scope.ts +115 -0
- package/src/scripts/_lib/user_global_memory_audit.ts +187 -0
- package/src/scripts/_lib/user_global_observations.ts +830 -0
- package/src/scripts/_lib/user_global_revocations.ts +110 -0
- package/src/scripts/_lib/user_memory_gate_counters.ts +291 -0
- package/src/scripts/ai_council/blind_review.ts +0 -0
- package/src/scripts/ai_council/budget_guard.ts +90 -11
- package/src/scripts/ai_council/bundler.ts +2 -2
- package/src/scripts/ai_council/clients.ts +59 -3
- package/src/scripts/ai_council/config.ts +38 -0
- package/src/scripts/ai_council/orchestrator.ts +54 -9
- package/src/scripts/ai_team/team_dispatch.ts +17 -6
- package/src/scripts/anchor_eval_falsify.ts +198 -0
- package/src/scripts/anchor_scoring_run.ts +239 -0
- package/src/scripts/annotate_discovery.ts +1 -65
- package/src/scripts/bench_quality_run.ts +168 -4
- package/src/scripts/cache_realization_report.ts +782 -0
- package/src/scripts/check_artefact_count_messaging.ts +5 -1
- package/src/scripts/check_augment_description_cap.ts +15 -4
- package/src/scripts/check_ci_local_parity.ts +317 -0
- package/src/scripts/check_condensation.ts +96 -191
- package/src/scripts/check_context_paths.ts +38 -9
- package/src/scripts/check_gate_coverage.ts +299 -0
- package/src/scripts/check_iron_law_prominence.ts +22 -1
- package/src/scripts/check_kernel_prefix_stability.ts +0 -0
- package/src/scripts/check_no_new_legacy_path.ts +16 -6
- package/src/scripts/check_no_roadmap_refs.ts +22 -9
- package/src/scripts/check_originality_freshness.ts +167 -0
- package/src/scripts/check_preamble_payload_budget.ts +130 -0
- package/src/scripts/check_proposal.ts +0 -0
- package/src/scripts/check_references.ts +0 -1
- package/src/scripts/check_safety_floor_untouched.ts +171 -24
- package/src/scripts/check_site_links.ts +62 -3
- package/src/scripts/ci_status.ts +0 -0
- package/src/scripts/cluster_near_miss_patterns.ts +0 -0
- package/src/scripts/code_graph/build.ts +0 -0
- package/src/scripts/command_suggester/types.ts +0 -0
- package/src/scripts/compile_router.ts +10 -14
- package/src/scripts/condense.sh +3 -4
- package/src/scripts/condense.ts +247 -228
- package/src/scripts/cost/track.mjs +168 -33
- package/src/scripts/cost_summary.ts +33 -1
- package/src/scripts/council_cli.ts +45 -3
- package/src/scripts/discovery_graph.ts +0 -0
- package/src/scripts/encoding_corpus.ts +500 -0
- package/src/scripts/encoding_corpus_report.ts +216 -0
- package/src/scripts/generate_index.ts +19 -2
- package/src/scripts/install-hooks.sh +2 -2
- package/src/scripts/learning_sidecar.ts +0 -0
- package/src/scripts/lint_confusables.ts +10 -72
- package/src/scripts/lint_featured_skills.ts +0 -0
- package/src/scripts/lint_hidden_unicode.ts +208 -0
- package/src/scripts/lint_load_context.ts +17 -5
- package/src/scripts/lint_new_skill_gate.ts +9 -3
- package/src/scripts/lint_no_python_twin_rationale.ts +17 -2
- package/src/scripts/lint_originality.ts +1 -1
- package/src/scripts/lint_skill_originality.ts +1 -1
- package/src/scripts/lint_ticket_buildable.ts +1 -1
- package/src/scripts/mcp_server/tools.ts +4 -4
- package/src/scripts/measure_scope_dedup.ts +224 -0
- package/src/scripts/memory_lookup.ts +0 -0
- package/src/scripts/mine_session.ts +98 -0
- package/src/scripts/orchestration_payload_hash_drift.ts +145 -0
- package/src/scripts/preamble_byte_census.ts +574 -0
- package/src/scripts/probe_skill_registration.ts +2 -2
- package/src/scripts/redact_hook_capture.ts +13 -0
- package/src/scripts/release.ts +65 -10
- package/src/scripts/router_telemetry.ts +1 -1
- package/src/scripts/second_brain_retrieval.ts +14 -4
- package/src/scripts/skill_linter.ts +5 -0
- package/src/scripts/surface-tiers.yml +2 -0
- package/src/scripts/validate_pack_yaml.ts +0 -0
- package/src/server/schemas/settings.ts +8 -0
- package/src/shared/userMd/utils.ts +31 -0
- package/dist/agent-src/rules/telegraph-speak.md +0 -87
|
@@ -105,9 +105,15 @@ function _skill_roots(): string[] {
|
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
108
|
+
// ADR-051 moved skill authoring to `src/skills`; a later commit deleted
|
|
109
|
+
// `packages/` entirely. Until 2026-07-29 the only fallback was the retired
|
|
110
|
+
// container, so this resolved to [] and the overlap gate silently passed
|
|
111
|
+
// every new skill.
|
|
112
|
+
if (roots.length === 0) {
|
|
113
|
+
const cand = path.join(ROOT, 'src', 'skills');
|
|
114
|
+
if (_isDir(cand)) {
|
|
115
|
+
roots = [cand];
|
|
116
|
+
}
|
|
111
117
|
}
|
|
112
118
|
return roots;
|
|
113
119
|
}
|
|
@@ -26,9 +26,24 @@ const _HERE = fileURLToPath(import.meta.url);
|
|
|
26
26
|
export const ROOT = path.resolve(path.dirname(_HERE), '..', '..');
|
|
27
27
|
const SCOPE = path.join(ROOT, 'src', 'scripts');
|
|
28
28
|
|
|
29
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* Banned rationale shapes (case-insensitive).
|
|
31
|
+
*
|
|
32
|
+
* `twin-of` is qualified with a Python signal on purpose. The bare `/\btwin of\b/`
|
|
33
|
+
* it replaced banned an English word rather than a claim shape, and produced 6 false
|
|
34
|
+
* positives out of 7 findings: a CLI twin of an MCP tool, a sync twin of an async
|
|
35
|
+
* probe in the same file, a debate twin of a sibling function, a SQLite twin of a
|
|
36
|
+
* JSON cache. None of those rationalise anything by fidelity to a deleted Python
|
|
37
|
+
* original — which is the only thing this gate exists to stop — and rewording correct
|
|
38
|
+
* comments to dodge a word would have been the tail wagging the dog.
|
|
39
|
+
*
|
|
40
|
+
* The narrowing does not weaken the gate: every shape it targets names Python by
|
|
41
|
+
* construction ("TypeScript twin of the Python original", "twin of the retired
|
|
42
|
+
* .py"), so the qualifier is satisfied precisely when the claim is the banned one.
|
|
43
|
+
* The other three patterns already carry their own Python signal.
|
|
44
|
+
*/
|
|
30
45
|
export const BANNED: ReadonlyArray<[string, RegExp]> = [
|
|
31
|
-
['twin-of', /\btwin of\b/i],
|
|
46
|
+
['twin-of', /\btwin of\b[^\n]*\b(?:python|py2ts|\.py)\b|\b(?:python|py2ts|\.py)\b[^\n]*\btwin of\b/i],
|
|
32
47
|
['latent-quirks', /latent (?:python )?(?:quirks|bugs) replicated/i],
|
|
33
48
|
['byte-identical-python', /byte-identical to the python/i],
|
|
34
49
|
['python-original', /\bthe python original\b/i],
|
|
@@ -373,7 +373,7 @@ function _changed(files: string[]): { pairs: Pair[]; fails: number } {
|
|
|
373
373
|
const seen = new Set<string>();
|
|
374
374
|
const record = (a: Artifact, b: Artifact): void => {
|
|
375
375
|
if (a.relpath === b.relpath) return;
|
|
376
|
-
const key = [a.relpath, b.relpath].sort().join('
|
|
376
|
+
const key = [a.relpath, b.relpath].sort().join('\0');
|
|
377
377
|
if (seen.has(key)) return;
|
|
378
378
|
const o = overlap(a, b);
|
|
379
379
|
if (o >= WARN) {
|
|
@@ -351,7 +351,7 @@ function _sortedSkillMds(root: string): string[] {
|
|
|
351
351
|
|
|
352
352
|
/** frozenset((a, b)) — order-independent membership key. */
|
|
353
353
|
function _frozenKey(a: string, b: string): string {
|
|
354
|
-
return a <= b ? `${a}
|
|
354
|
+
return a <= b ? `${a}\0${b}` : `${b}\0${a}`;
|
|
355
355
|
}
|
|
356
356
|
|
|
357
357
|
/** sorted(a & b) — codepoint-sorted intersection. */
|
|
@@ -97,10 +97,10 @@ export type ToolSideEffect = 'ro' | 'fs-write' | 'shell';
|
|
|
97
97
|
* each `tools/call`. `handler` is an async function that receives the
|
|
98
98
|
* validated arguments + the resolved `consumer_root` path.
|
|
99
99
|
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
100
|
+
* Shape is pinned by `consumer_tool_catalog.json`: `build_mcp_catalog` derives
|
|
101
|
+
* the catalog from `ALLOWLIST` here, and `build_mcp_catalog --strict` fails CI
|
|
102
|
+
* on any drift (`.github/workflows/tests.yml`). `side_effect` is consumed by that
|
|
103
|
+
* generator, so adding or reordering a field means regenerating the catalog.
|
|
104
104
|
*/
|
|
105
105
|
export interface BuiltinTool {
|
|
106
106
|
readonly name: string;
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* C-3 measurement harness — scope de-duplication of the rule projection.
|
|
4
|
+
*
|
|
5
|
+
* Pre-registered in `road-to-cache-economy.md` § "C-3
|
|
6
|
+
* pre-registration" BEFORE this script produced a number. Metric, threshold and
|
|
7
|
+
* honest-null consequence are fixed there; this file only measures.
|
|
8
|
+
*
|
|
9
|
+
* What it does, deterministically and without touching the real HOME:
|
|
10
|
+
*
|
|
11
|
+
* 1. Builds a two-scope FIXTURE: a temp home whose `.claude/rules/` is a
|
|
12
|
+
* byte-identical copy of the projected rule source. That is the condition
|
|
13
|
+
* the reduction targets — a consumer carrying the same package version at
|
|
14
|
+
* user scope and project scope. (On a maintainer machine the two scopes
|
|
15
|
+
* hold different releases, so the dedup is correctly inert; that case is
|
|
16
|
+
* measured too, as the control.)
|
|
17
|
+
* 2. Censuses the payload with the dedup OFF, then ON.
|
|
18
|
+
* 3. Reports the delta against BOTH denominators: the measured median
|
|
19
|
+
* cold-start (what a spawn actually pays) and the file-measurable subtotal.
|
|
20
|
+
*
|
|
21
|
+
* It never writes into `~`, never regenerates the repo's own projection, and
|
|
22
|
+
* makes no network call.
|
|
23
|
+
*/
|
|
24
|
+
import * as fs from 'node:fs';
|
|
25
|
+
import * as os from 'node:os';
|
|
26
|
+
import * as path from 'node:path';
|
|
27
|
+
|
|
28
|
+
import { censusRuleDir } from './preamble_byte_census.js';
|
|
29
|
+
|
|
30
|
+
const REPO_ROOT = path.resolve(path.dirname(new URL(import.meta.url).pathname), '..', '..');
|
|
31
|
+
const RULES_SOURCE = path.join(REPO_ROOT, 'dist', 'agent-src', 'rules');
|
|
32
|
+
|
|
33
|
+
/** Estimated tokens, the same chars/4 basis the census uses. */
|
|
34
|
+
function tokens(chars: number): number {
|
|
35
|
+
return Math.round(chars / 4);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface ScopeSnapshot {
|
|
39
|
+
files: number;
|
|
40
|
+
chars: number;
|
|
41
|
+
tokens: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function snapshot(dir: string): ScopeSnapshot {
|
|
45
|
+
const c = censusRuleDir(dir);
|
|
46
|
+
return { files: c.files, chars: c.chars, tokens: tokens(c.chars) };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Copy every `*.md` byte-for-byte — the fixture must be byte-identical to matter. */
|
|
50
|
+
function copyRules(from: string, to: string): number {
|
|
51
|
+
fs.mkdirSync(to, { recursive: true });
|
|
52
|
+
let n = 0;
|
|
53
|
+
for (const entry of fs.readdirSync(from)) {
|
|
54
|
+
if (!entry.endsWith('.md')) continue;
|
|
55
|
+
fs.copyFileSync(path.join(from, entry), path.join(to, entry));
|
|
56
|
+
n += 1;
|
|
57
|
+
}
|
|
58
|
+
return n;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Which rules a byte-identity-gated dedup would skip at project scope. Mirrors
|
|
63
|
+
* `condense._dedupable_rules`'s predicate rather than importing it, so the
|
|
64
|
+
* measurement fails loudly if the two ever disagree instead of moving together.
|
|
65
|
+
*/
|
|
66
|
+
function dedupableCount(userDir: string, sourceDir: string): { skipped: number; chars: number } {
|
|
67
|
+
let skipped = 0;
|
|
68
|
+
let chars = 0;
|
|
69
|
+
if (!fs.existsSync(userDir)) return { skipped, chars };
|
|
70
|
+
for (const entry of fs.readdirSync(sourceDir)) {
|
|
71
|
+
if (!entry.endsWith('.md')) continue;
|
|
72
|
+
const twin = path.join(userDir, entry);
|
|
73
|
+
const source = path.join(sourceDir, entry);
|
|
74
|
+
if (!fs.existsSync(twin)) continue;
|
|
75
|
+
const a = fs.readFileSync(twin);
|
|
76
|
+
const b = fs.readFileSync(source);
|
|
77
|
+
if (a.equals(b)) {
|
|
78
|
+
skipped += 1;
|
|
79
|
+
chars += b.byteLength;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return { skipped, chars };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Why the real user scope misses the fixture condition. Version drift is the
|
|
87
|
+
* benign half; the structural half is that `install.ts` stamps ownership
|
|
88
|
+
* frontmatter into every installed rule (`_set_key(fm_lines, 'package', …)` at
|
|
89
|
+
* install.ts:2723, `source_path` at install.ts:2725) while the in-repo
|
|
90
|
+
* projection stamps nothing — so a provenance-only difference survives even a
|
|
91
|
+
* perfect version alignment. Classifying the two apart is what turns "0/110"
|
|
92
|
+
* from a puzzle into an answer: `provenanceOnly == total` means aligning
|
|
93
|
+
* versions would buy exactly nothing.
|
|
94
|
+
*/
|
|
95
|
+
const OWNERSHIP_KEYS = ['package', 'source_path'] as const;
|
|
96
|
+
|
|
97
|
+
function stripOwnershipKeys(buf: Buffer): string {
|
|
98
|
+
return buf
|
|
99
|
+
.toString('utf-8')
|
|
100
|
+
.split('\n')
|
|
101
|
+
.filter((line) => !OWNERSHIP_KEYS.some((k) => line.startsWith(`${k}:`)))
|
|
102
|
+
.join('\n');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
interface ReachabilitySplit {
|
|
106
|
+
total: number;
|
|
107
|
+
identical: number;
|
|
108
|
+
provenanceOnly: number;
|
|
109
|
+
bodyDiff: number;
|
|
110
|
+
missing: number;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function classifyReachability(userDir: string, sourceDir: string): ReachabilitySplit {
|
|
114
|
+
const split: ReachabilitySplit = {
|
|
115
|
+
total: 0,
|
|
116
|
+
identical: 0,
|
|
117
|
+
provenanceOnly: 0,
|
|
118
|
+
bodyDiff: 0,
|
|
119
|
+
missing: 0,
|
|
120
|
+
};
|
|
121
|
+
for (const entry of fs.readdirSync(sourceDir)) {
|
|
122
|
+
if (!entry.endsWith('.md')) continue;
|
|
123
|
+
split.total += 1;
|
|
124
|
+
const twin = path.join(userDir, entry);
|
|
125
|
+
let a: Buffer;
|
|
126
|
+
try {
|
|
127
|
+
a = fs.readFileSync(twin);
|
|
128
|
+
} catch {
|
|
129
|
+
split.missing += 1;
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const b = fs.readFileSync(path.join(sourceDir, entry));
|
|
133
|
+
if (a.equals(b)) split.identical += 1;
|
|
134
|
+
else if (stripOwnershipKeys(a) === stripOwnershipKeys(b)) split.provenanceOnly += 1;
|
|
135
|
+
else split.bodyDiff += 1;
|
|
136
|
+
}
|
|
137
|
+
return split;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function main(argv: readonly string[]): number {
|
|
141
|
+
const medianArg = argv.find((a) => a.startsWith('--measured-median='));
|
|
142
|
+
// The measured median cold-start payload, from the transcript census. Passed
|
|
143
|
+
// in rather than re-derived so this harness stays byte-only and offline.
|
|
144
|
+
const measuredMedian = medianArg ? Number(medianArg.split('=')[1]) : 230556;
|
|
145
|
+
|
|
146
|
+
const fixtureHome = fs.mkdtempSync(path.join(os.tmpdir(), 'scope-dedup-'));
|
|
147
|
+
const fixtureUserRules = path.join(fixtureHome, '.claude', 'rules');
|
|
148
|
+
const copied = copyRules(RULES_SOURCE, fixtureUserRules);
|
|
149
|
+
|
|
150
|
+
const source = snapshot(RULES_SOURCE);
|
|
151
|
+
const fixtureUser = snapshot(fixtureUserRules);
|
|
152
|
+
|
|
153
|
+
// --- the two conditions ---------------------------------------------------
|
|
154
|
+
const fixture = dedupableCount(fixtureUserRules, RULES_SOURCE);
|
|
155
|
+
const realUserRules = path.join(process.env['HOME'] ?? os.homedir(), '.claude', 'rules');
|
|
156
|
+
const control = dedupableCount(realUserRules, RULES_SOURCE);
|
|
157
|
+
const reach = fs.existsSync(realUserRules)
|
|
158
|
+
? classifyReachability(realUserRules, RULES_SOURCE)
|
|
159
|
+
: { total: 0, identical: 0, provenanceOnly: 0, bodyDiff: 0, missing: 0 };
|
|
160
|
+
|
|
161
|
+
const before = fixtureUser.tokens + source.tokens; // both scopes load
|
|
162
|
+
const after = fixtureUser.tokens + (source.tokens - tokens(fixture.chars));
|
|
163
|
+
const removed = before - after;
|
|
164
|
+
|
|
165
|
+
const pct = (part: number, whole: number): string => `${((part / whole) * 100).toFixed(1)}%`;
|
|
166
|
+
|
|
167
|
+
const lines: string[] = [];
|
|
168
|
+
lines.push('C-3 measurement — scope de-duplication of the rule projection');
|
|
169
|
+
lines.push(` metric basis: chars/4 token estimate; rule source ${RULES_SOURCE}`);
|
|
170
|
+
lines.push('');
|
|
171
|
+
lines.push(`FIXTURE (consumer condition — same version at both scopes, ${copied} files copied)`);
|
|
172
|
+
lines.push(` user scope: ${fixtureUser.files} files, ${fixtureUser.tokens} tok`);
|
|
173
|
+
lines.push(` project scope: ${source.files} files, ${source.tokens} tok`);
|
|
174
|
+
lines.push(` byte-identical twins: ${fixture.skipped}/${source.files}`);
|
|
175
|
+
lines.push(` rules payload before: ${before} tok`);
|
|
176
|
+
lines.push(` rules payload after: ${after} tok`);
|
|
177
|
+
lines.push(` removed: ${removed} tok`);
|
|
178
|
+
lines.push('');
|
|
179
|
+
lines.push('REDUCTION vs the pre-registered denominators');
|
|
180
|
+
lines.push(` of measured median cold-start (${measuredMedian} tok): ${pct(removed, measuredMedian)}`);
|
|
181
|
+
lines.push(` of the two-scope rules payload (${before} tok): ${pct(removed, before)}`);
|
|
182
|
+
lines.push('');
|
|
183
|
+
lines.push('CONTROL (this machine — the dedup must be inert unless both scopes match)');
|
|
184
|
+
lines.push(` byte-identical twins: ${control.skipped}/${source.files}`);
|
|
185
|
+
lines.push(` removed: ${tokens(control.chars)} tok`);
|
|
186
|
+
lines.push('');
|
|
187
|
+
lines.push(`threshold: >= 15% of the measured median -> ${
|
|
188
|
+
removed / measuredMedian >= 0.15 ? 'MET' : 'NOT MET'
|
|
189
|
+
}`);
|
|
190
|
+
lines.push('');
|
|
191
|
+
lines.push('REACHABILITY of the fixture condition (why the control is not the fixture)');
|
|
192
|
+
lines.push(` identical: ${reach.identical}/${reach.total}`);
|
|
193
|
+
lines.push(` differ in body: ${reach.bodyDiff}/${reach.total} (closed by aligning versions)`);
|
|
194
|
+
lines.push(` differ ONLY in the ownership stamp: ${reach.provenanceOnly}/${reach.total}`);
|
|
195
|
+
lines.push(` absent at user scope: ${reach.missing}/${reach.total}`);
|
|
196
|
+
if (reach.identical === 0 && reach.bodyDiff + reach.provenanceOnly === reach.total) {
|
|
197
|
+
lines.push('');
|
|
198
|
+
lines.push(' -> Aligning versions would close the body diffs and leave the ownership');
|
|
199
|
+
lines.push(' stamp, so the reachable twin count is 0, NOT the fixture\'s figure.');
|
|
200
|
+
lines.push(' install.ts:2723/2725 stamp package:/source_path: into every installed');
|
|
201
|
+
lines.push(' rule unconditionally; the in-repo projection stamps nothing. Two');
|
|
202
|
+
lines.push(' writers, deliberately different output. Making this reachable was');
|
|
203
|
+
lines.push(' DECIDED AGAINST on 2026-07-31 (real install-path risk, empty recipient');
|
|
204
|
+
lines.push(' set) — see contexts/dedup-reachability-refusal.md for the analysis and');
|
|
205
|
+
lines.push(' the five reopen conditions. This 0 is expected, not a defect.');
|
|
206
|
+
lines.push(' Do NOT relax the byte predicate to make this number move: that');
|
|
207
|
+
lines.push(' predicate IS the content-neutrality argument.');
|
|
208
|
+
}
|
|
209
|
+
lines.push('');
|
|
210
|
+
lines.push('Content safety: only byte-identical twins are removed, so the host still');
|
|
211
|
+
lines.push('loads the same rule text in full — once instead of twice. No rule becomes');
|
|
212
|
+
lines.push('trigger-gated, which is what separates this from the disabled thin projection.');
|
|
213
|
+
|
|
214
|
+
process.stdout.write(lines.join('\n') + '\n');
|
|
215
|
+
fs.rmSync(fixtureHome, { recursive: true, force: true });
|
|
216
|
+
return 0;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (process.argv[1] !== undefined && import.meta.url === `file://${process.argv[1]}`) {
|
|
220
|
+
process.exit(main(process.argv.slice(2)));
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export { classifyReachability, dedupableCount, main };
|
|
224
|
+
export type { ReachabilitySplit };
|
|
Binary file
|
|
@@ -34,6 +34,8 @@ import * as os from 'node:os';
|
|
|
34
34
|
import * as path from 'node:path';
|
|
35
35
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
36
36
|
|
|
37
|
+
import { appendGlobalObservation, applySharedFactCap } from './_lib/user_global_observations.js';
|
|
38
|
+
|
|
37
39
|
const _HERE = fileURLToPath(import.meta.url);
|
|
38
40
|
// src/scripts/mine_session.py → parent.parent.parent == repo root.
|
|
39
41
|
export const ROOT = path.resolve(path.dirname(_HERE), '..', '..');
|
|
@@ -296,6 +298,64 @@ function _nowIsoSeconds(): string {
|
|
|
296
298
|
return new Date().toISOString().replace(/\.\d{3}Z$/, '+00:00');
|
|
297
299
|
}
|
|
298
300
|
|
|
301
|
+
/** One candidate the user-scoped channel below may propose to the global observation buffer. */
|
|
302
|
+
export interface UserObservationSignal {
|
|
303
|
+
readonly ts: string;
|
|
304
|
+
readonly suggest: string;
|
|
305
|
+
readonly evidence: string;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* The second, user-scoped channel (road-to-global-user-memory Phase 2).
|
|
310
|
+
* Scans the SAME entries `mine()` scans for the Preference family
|
|
311
|
+
* (`SIGNAL_FAMILIES`'s `'convention'` entry) and, for every match `mine()`
|
|
312
|
+
* would have silently discarded — because `_normalise` found no
|
|
313
|
+
* project-scoped path/symbol token, i.e. the match is about the USER, not
|
|
314
|
+
* the project — shapes a candidate observation instead of dropping it.
|
|
315
|
+
*
|
|
316
|
+
* Deliberately independent of `mine()`: it does not read or mutate `mine()`'s
|
|
317
|
+
* `facts` array, does not change `mine()`'s signature, return shape, or
|
|
318
|
+
* output, and does not touch disk. `mine()`'s byte-parity contract with the
|
|
319
|
+
* retired Python implementation is therefore untouched by this addition —
|
|
320
|
+
* this is a wholly new, additive export.
|
|
321
|
+
*
|
|
322
|
+
* The caller is responsible for the shared ≤5-per-cycle cap
|
|
323
|
+
* (`user_global_observations.applySharedFactCap`, counting THIS output
|
|
324
|
+
* together with `mine()`'s `facts.length`) and for guard evaluation +
|
|
325
|
+
* writing (`user_global_observations.appendGlobalObservation`) — this
|
|
326
|
+
* function only detects and shapes candidates.
|
|
327
|
+
*/
|
|
328
|
+
export function mineUserObservationCandidates(
|
|
329
|
+
entries: Iterable<Record<string, Json>>,
|
|
330
|
+
since: Date,
|
|
331
|
+
): UserObservationSignal[] {
|
|
332
|
+
const preferenceFamily = SIGNAL_FAMILIES.find(([tag]) => tag === 'convention')?.[1];
|
|
333
|
+
if (!preferenceFamily) {
|
|
334
|
+
return [];
|
|
335
|
+
}
|
|
336
|
+
const out: UserObservationSignal[] = [];
|
|
337
|
+
for (const turn of entries) {
|
|
338
|
+
const tsStr = _turnTs(turn);
|
|
339
|
+
if (!_withinWindow(tsStr, since)) {
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
const text = _turnText(turn);
|
|
343
|
+
if (!text || !_search(preferenceFamily, text)) {
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
// Project-scoped → mine()'s job, not this channel.
|
|
347
|
+
if (_search(PATH_TOKEN, text) || _search(SYMBOL_TOKEN, text)) {
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
const cleaned = _redact(text, []).replace(/\s+/g, ' ').trim().slice(0, 240);
|
|
351
|
+
if (!cleaned) {
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
out.push({ ts: tsStr || _nowIsoSeconds(), suggest: cleaned, evidence: cleaned });
|
|
355
|
+
}
|
|
356
|
+
return out;
|
|
357
|
+
}
|
|
358
|
+
|
|
299
359
|
export function renderPreview(
|
|
300
360
|
facts: Array<Record<string, Json>>,
|
|
301
361
|
project: string,
|
|
@@ -619,6 +679,44 @@ export function main(argv: string[] | null = null): number {
|
|
|
619
679
|
'files.\n Next: /memory promote to lift validated lines ' +
|
|
620
680
|
'into curated YAML.\n',
|
|
621
681
|
);
|
|
682
|
+
// Second channel (road-to-global-user-memory Phase 2): the preference
|
|
683
|
+
// signals `mine()` discards because they are about the USER, not the
|
|
684
|
+
// project, reach the global buffer instead of /dev/null. The ≤5 cap is
|
|
685
|
+
// SHARED — the project channel's facts are counted first, so this channel
|
|
686
|
+
// only ever uses the leftover headroom.
|
|
687
|
+
//
|
|
688
|
+
// `entries` is a consumed generator by now, so the source is re-read.
|
|
689
|
+
// Appending still goes through every capture guard and the redaction gate;
|
|
690
|
+
// nothing here can write `profile.md` — only a human `accept` does that.
|
|
691
|
+
const observationEntries =
|
|
692
|
+
kind === 'chat-history' ? _iterChatHistory(srcPath) : _iterClaudeCodeJsonl(srcPath);
|
|
693
|
+
const candidates = applySharedFactCap(
|
|
694
|
+
facts.length,
|
|
695
|
+
mineUserObservationCandidates(observationEntries, since),
|
|
696
|
+
);
|
|
697
|
+
let appended = 0;
|
|
698
|
+
const refused: string[] = [];
|
|
699
|
+
for (const candidate of candidates) {
|
|
700
|
+
const result = appendGlobalObservation({
|
|
701
|
+
ts: candidate.ts,
|
|
702
|
+
field: 'notes',
|
|
703
|
+
suggest: candidate.suggest,
|
|
704
|
+
source: 'mine_session',
|
|
705
|
+
evidence: candidate.evidence,
|
|
706
|
+
});
|
|
707
|
+
if (result.written) {
|
|
708
|
+
appended += 1;
|
|
709
|
+
} else if (result.category !== undefined) {
|
|
710
|
+
refused.push(result.category);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
if (candidates.length > 0) {
|
|
714
|
+
const detail = refused.length > 0 ? ` (${refused.length} refused: ${refused.join(', ')})` : '';
|
|
715
|
+
process.stdout.write(
|
|
716
|
+
`✅ Appended ${appended} user observation(s) to the global buffer${detail}.\n` +
|
|
717
|
+
' Next: /agents user review to accept or drop them.\n',
|
|
718
|
+
);
|
|
719
|
+
}
|
|
622
720
|
return 0;
|
|
623
721
|
}
|
|
624
722
|
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Payload-hash × cache-hit drift report — CLI.
|
|
4
|
+
*
|
|
5
|
+
* `road-to-cache-economy.md` Phase 3, steps 6-7. Reads the
|
|
6
|
+
* accumulated audit-log-v1 telemetry (reuses `readAuditLines` from
|
|
7
|
+
* `orchestration_savings_report.ts` — the same reader, not a reimplementation)
|
|
8
|
+
* and joins `orchestration.payload_hash` against `orchestration.cache_hit`
|
|
9
|
+
* per {@link aggregatePayloadHashDrift}'s cohort split, so prefix-stability
|
|
10
|
+
* drift becomes visible.
|
|
11
|
+
*
|
|
12
|
+
* REFUSAL (step 7 — report it, never act on it): `cache_hit` is a
|
|
13
|
+
* provider-reported proxy for HOST-controlled cache behaviour, not a metric
|
|
14
|
+
* this package causes or controls. Per ADR-118's automation threshold (§1:
|
|
15
|
+
* a direct measure, a low false-positive rate, and no unique human
|
|
16
|
+
* judgement required — all three, or it stays manual), a host-controlled
|
|
17
|
+
* proxy fails condition 1 outright. This report NEVER wires a measure→adjust
|
|
18
|
+
* step off these two fields — no default flip, no tier change, no dispatch
|
|
19
|
+
* throttle. It is read-only, always.
|
|
20
|
+
*
|
|
21
|
+
* Zero recorded lines with BOTH fields is the CURRENT expected state — both
|
|
22
|
+
* fields are lean-init extensions with no caller wiring a real value into
|
|
23
|
+
* them yet (per the roadmap's own defect list). This report says so
|
|
24
|
+
* explicitly rather than presenting empty input as a green result.
|
|
25
|
+
*
|
|
26
|
+
* Usage:
|
|
27
|
+
* ./scripts-run src/scripts/orchestration_payload_hash_drift [--dir <path>] [--format text|json]
|
|
28
|
+
*
|
|
29
|
+
* Default dir: agents/runtime/state/audit (the audit-log-v1 path, matching
|
|
30
|
+
* `orchestration_savings_report.ts`'s default).
|
|
31
|
+
*/
|
|
32
|
+
import * as path from 'node:path';
|
|
33
|
+
import { pathToFileURL } from 'node:url';
|
|
34
|
+
|
|
35
|
+
import { aggregatePayloadHashDrift, type PayloadHashDriftReport, type PayloadHashLine } from './_lib/payload_hash_drift.js';
|
|
36
|
+
import { readAuditLines } from './orchestration_savings_report.js';
|
|
37
|
+
|
|
38
|
+
const DEFAULT_DIR = 'agents/runtime/state/audit';
|
|
39
|
+
|
|
40
|
+
export interface Options {
|
|
41
|
+
dir: string;
|
|
42
|
+
format: 'text' | 'json';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function parseArgs(argv: string[]): Options {
|
|
46
|
+
const opts: Options = { dir: DEFAULT_DIR, format: 'text' };
|
|
47
|
+
for (let i = 0; i < argv.length; i++) {
|
|
48
|
+
const a = argv[i];
|
|
49
|
+
if (a === undefined) continue;
|
|
50
|
+
if (a === '--dir') opts.dir = argv[++i] ?? opts.dir;
|
|
51
|
+
else if (a.startsWith('--dir=')) opts.dir = a.slice('--dir='.length);
|
|
52
|
+
else if (a === '--format') opts.format = (argv[++i] as Options['format']) ?? opts.format;
|
|
53
|
+
else if (a.startsWith('--format=')) opts.format = a.slice('--format='.length) as Options['format'];
|
|
54
|
+
}
|
|
55
|
+
if (opts.format !== 'text' && opts.format !== 'json') opts.format = 'text';
|
|
56
|
+
return opts;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
interface RawOrchestrationHashFields {
|
|
60
|
+
payload_hash?: unknown;
|
|
61
|
+
cache_hit?: unknown;
|
|
62
|
+
}
|
|
63
|
+
interface RawHashLine {
|
|
64
|
+
input_kind?: unknown;
|
|
65
|
+
orchestration?: RawOrchestrationHashFields;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Reads only the two fields this report needs, tolerant of any pre-extension line missing them. */
|
|
69
|
+
function toPayloadHashLine(raw: unknown): PayloadHashLine {
|
|
70
|
+
const line = (raw ?? {}) as RawHashLine;
|
|
71
|
+
if (line.input_kind !== 'orchestration' || !line.orchestration) {
|
|
72
|
+
return { payload_hash: null, cache_hit: null };
|
|
73
|
+
}
|
|
74
|
+
const hash = line.orchestration.payload_hash;
|
|
75
|
+
const hit = line.orchestration.cache_hit;
|
|
76
|
+
return {
|
|
77
|
+
payload_hash: typeof hash === 'string' && hash.length > 0 ? hash : null,
|
|
78
|
+
cache_hit: typeof hit === 'boolean' ? hit : null,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function buildReport(dir: string): PayloadHashDriftReport {
|
|
83
|
+
const rawLines: unknown[] = readAuditLines(dir);
|
|
84
|
+
const lines = rawLines.map(toPayloadHashLine);
|
|
85
|
+
return aggregatePayloadHashDrift(lines);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function pct(v: number): string {
|
|
89
|
+
return `${(v * 100).toFixed(1)}%`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function renderText(r: PayloadHashDriftReport): string {
|
|
93
|
+
const out: string[] = [];
|
|
94
|
+
out.push('Payload-hash × cache-hit drift report');
|
|
95
|
+
out.push(` total audit-log-v1 lines seen: ${r.total_lines}`);
|
|
96
|
+
out.push(` lines carrying BOTH payload_hash and cache_hit: ${r.lines_with_data}`);
|
|
97
|
+
out.push('');
|
|
98
|
+
|
|
99
|
+
if (r.lines_with_data === 0) {
|
|
100
|
+
out.push(
|
|
101
|
+
'No recorded lines carry both fields yet — this is the CURRENT expected state (both are lean-init',
|
|
102
|
+
);
|
|
103
|
+
out.push(
|
|
104
|
+
'extensions; no caller wires a real value into them today). The reader works; there is nothing to',
|
|
105
|
+
);
|
|
106
|
+
out.push('report on. This is NOT presented as a green pass — it is an honest empty state.');
|
|
107
|
+
} else {
|
|
108
|
+
out.push(
|
|
109
|
+
`stable cohort (repeat occurrences of a hash — the prior write should already be cached): n=${r.stable_cohort.n} ` +
|
|
110
|
+
`hit_rate=${r.stable_cohort.hit_rate !== null ? pct(r.stable_cohort.hit_rate) : 'n/a'}`,
|
|
111
|
+
);
|
|
112
|
+
out.push(
|
|
113
|
+
`unstable cohort (hashes seen exactly once — a payload that never repeats): n=${r.unstable_cohort.n} ` +
|
|
114
|
+
`hit_rate=${r.unstable_cohort.hit_rate !== null ? pct(r.unstable_cohort.hit_rate) : 'n/a'}`,
|
|
115
|
+
);
|
|
116
|
+
out.push(`drift_visible (stable hit_rate > unstable hit_rate): ${r.drift_visible ? 'YES' : 'no'}`);
|
|
117
|
+
out.push('');
|
|
118
|
+
out.push('Per-hash breakdown (most-occurrences first):');
|
|
119
|
+
for (const g of r.groups) {
|
|
120
|
+
out.push(` ${g.payload_hash}: occurrences=${g.occurrences} hit_rate=${pct(g.hit_rate)}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
out.push('');
|
|
125
|
+
out.push('REFUSAL (report, never act): cache_hit is a proxy for host-controlled cache behaviour, not a');
|
|
126
|
+
out.push('metric this package controls. Per ADR-118 §1, a host-controlled proxy fails the direct-measure');
|
|
127
|
+
out.push('condition outright — this report never wires a measure→adjust step off these two fields.');
|
|
128
|
+
return out.join('\n');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function main(argv: string[] = process.argv.slice(2)): number {
|
|
132
|
+
const opts = parseArgs(argv);
|
|
133
|
+
const report = buildReport(opts.dir);
|
|
134
|
+
if (opts.format === 'json') {
|
|
135
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
136
|
+
} else {
|
|
137
|
+
process.stdout.write(renderText(report) + '\n');
|
|
138
|
+
}
|
|
139
|
+
return 0;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (process.argv[1] !== undefined) {
|
|
143
|
+
const invokedUrl = pathToFileURL(path.resolve(process.argv[1])).href;
|
|
144
|
+
if (import.meta.url === invokedUrl) process.exit(main());
|
|
145
|
+
}
|