@event4u/agent-config 7.5.0 → 8.1.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 +8 -1
- package/AGENTS.md +9 -9
- package/CHANGELOG.md +317 -260
- package/README.md +35 -5
- package/dist/agent-src/commands/analytics/prune.md +1 -1
- package/dist/agent-src/commands/analytics/show.md +1 -1
- package/dist/agent-src/commands/analyze/decision.md +2 -2
- package/dist/agent-src/commands/analyze/incident.md +2 -2
- package/dist/agent-src/commands/analyze/near-miss.md +2 -2
- package/dist/agent-src/commands/analyze/postmortem.md +2 -2
- package/dist/agent-src/commands/analyze/premortem.md +2 -2
- package/dist/agent-src/commands/cost-report.md +25 -0
- package/dist/agent-src/commands/evals/analyze.json +30 -0
- package/dist/agent-src/commands/evals/mission-upgrade.json +30 -0
- package/dist/agent-src/commands/implement-ticket.md +1 -1
- package/dist/agent-src/commands/knowledge/forget.md +1 -1
- package/dist/agent-src/commands/knowledge/ingest.md +1 -1
- package/dist/agent-src/commands/knowledge/list.md +1 -1
- package/dist/agent-src/commands/memory/load.md +12 -11
- package/dist/agent-src/commands/memory/promote.md +30 -0
- package/dist/agent-src/commands/memory/propose.md +16 -2
- package/dist/agent-src/commands/mission/upgrade.md +1 -1
- package/dist/agent-src/commands/module/explore.md +11 -7
- package/dist/agent-src/commands/optimize-project.md +243 -0
- package/dist/agent-src/commands/optimize.md +5 -0
- package/dist/agent-src/commands/pr/create.md +37 -8
- package/dist/agent-src/commands/prediction-pool.md +2 -2
- package/dist/agent-src/commands/profile/activate.md +3 -3
- package/dist/agent-src/commands/profile/deactivate.md +2 -2
- package/dist/agent-src/commands/profile/show.md +3 -3
- package/dist/agent-src/commands/research/deep.md +5 -0
- package/dist/agent-src/commands/research/report.md +2 -1
- package/dist/agent-src/commands/roadmap/create.md +88 -10
- package/dist/agent-src/commands/roadmap/materialize.md +1 -1
- package/dist/agent-src/commands/roadmap/process-full.md +15 -2
- package/dist/agent-src/commands/roadmap/process-phase.md +18 -6
- package/dist/agent-src/commands/roadmap/process-step.md +4 -0
- package/dist/agent-src/commands/roadmap.md +1 -1
- package/dist/agent-src/commands/security-audit-config.md +1 -1
- package/dist/agent-src/commands/sync-agent-settings.md +1 -1
- package/dist/agent-src/commands/sync-gitignore/fix.md +42 -6
- package/dist/agent-src/commands/team-knowledge/bootstrap.md +106 -0
- package/dist/agent-src/commands/team-knowledge/consolidate.md +105 -0
- package/dist/agent-src/commands/team-knowledge.md +64 -0
- package/dist/agent-src/contexts/authority/commit-mechanics.md +8 -0
- package/dist/agent-src/contexts/authority/destructive-mechanics.md +11 -0
- package/dist/agent-src/contexts/authority/scope-mechanics.md +25 -0
- package/dist/agent-src/contexts/communication/rules-auto/reply-close-mechanics.md +43 -0
- package/dist/agent-src/contexts/contracts/agents-md-anatomy.md +1 -1
- package/dist/agent-src/contexts/contracts/artifact-engagement-flow.md +2 -2
- package/dist/agent-src/contexts/contracts/frugality-charter.md +1 -0
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +14 -4
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +11 -0
- package/dist/agent-src/contexts/execution/orchestration-telemetry.md +32 -8
- package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +107 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +71 -15
- package/dist/agent-src/contexts/execution/subagent-steering.md +41 -1
- package/dist/agent-src/contexts/override-system.md +1 -1
- package/dist/agent-src/personas/brand-strategist.md +0 -1
- package/dist/agent-src/personas/data-integrity.md +66 -0
- package/dist/agent-src/personas/design-director.md +0 -1
- package/dist/agent-src/personas/performance-engineer.md +66 -0
- package/dist/agent-src/personas/production-validator.md +73 -0
- package/dist/agent-src/rules/agent-authority.md +3 -4
- package/dist/agent-src/rules/analysis-skill-routing.md +3 -5
- package/dist/agent-src/rules/architecture.md +2 -4
- package/dist/agent-src/rules/artifact-drafting-protocol.md +35 -6
- package/dist/agent-src/rules/artifact-engagement-recording.md +2 -4
- package/dist/agent-src/rules/ask-when-uncertain.md +10 -14
- package/dist/agent-src/rules/augment-edit-discipline.md +3 -5
- package/dist/agent-src/rules/autonomous-execution.md +3 -5
- package/dist/agent-src/rules/brand-consistency.md +3 -5
- package/dist/agent-src/rules/brand-source-of-truth.md +3 -5
- package/dist/agent-src/rules/cli-output-handling.md +4 -6
- package/dist/agent-src/rules/command-suggestion-policy.md +3 -5
- package/dist/agent-src/rules/commit-conventions.md +3 -5
- package/dist/agent-src/rules/commit-policy.md +18 -10
- package/dist/agent-src/rules/content-quoting-floor.md +88 -0
- package/dist/agent-src/rules/context-hygiene.md +3 -5
- package/dist/agent-src/rules/copilot-routing.md +4 -6
- package/dist/agent-src/rules/decision-revisit-gate.md +120 -0
- package/dist/agent-src/rules/delegation-policy.md +10 -6
- package/dist/agent-src/rules/design-fidelity.md +3 -5
- package/dist/agent-src/rules/devcontainer-routing.md +4 -6
- package/dist/agent-src/rules/direct-answers.md +13 -17
- package/dist/agent-src/rules/docker-commands.md +3 -5
- package/dist/agent-src/rules/domain-adoption-policy.md +3 -5
- package/dist/agent-src/rules/domain-safety-disclaimer.md +3 -5
- package/dist/agent-src/rules/domain-safety-pii.md +3 -5
- package/dist/agent-src/rules/domain-safety-retention.md +3 -5
- package/dist/agent-src/rules/downstream-changes.md +3 -4
- package/dist/agent-src/rules/engineering-safety-floor.md +3 -5
- package/dist/agent-src/rules/external-reference-deep-dive.md +3 -5
- package/dist/agent-src/rules/fast-path-marker-visibility.md +3 -5
- package/dist/agent-src/rules/finance-safety-floor.md +3 -6
- package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +3 -5
- package/dist/agent-src/rules/git-history-discipline.md +3 -5
- package/dist/agent-src/rules/guidelines.md +2 -4
- package/dist/agent-src/rules/icon-consistency.md +3 -5
- package/dist/agent-src/rules/image-likeness-and-rights.md +3 -5
- package/dist/agent-src/rules/improve-before-implement.md +5 -5
- package/dist/agent-src/rules/invite-challenge.md +3 -5
- package/dist/agent-src/rules/language-and-tone.md +13 -15
- package/dist/agent-src/rules/laravel-routing.md +3 -5
- package/dist/agent-src/rules/laravel-translations.md +3 -5
- package/dist/agent-src/rules/legal-safety-floor.md +3 -5
- package/dist/agent-src/rules/lethal-trifecta-guard.md +3 -5
- package/dist/agent-src/rules/linked-projects-onboarding-gate.md +4 -7
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +3 -5
- package/dist/agent-src/rules/markdown-safe-codeblocks.md +2 -4
- package/dist/agent-src/rules/media-governance-routing.md +3 -5
- package/dist/agent-src/rules/media-sync-ground-truth.md +3 -5
- package/dist/agent-src/rules/minimal-safe-diff.md +5 -5
- package/dist/agent-src/rules/missing-tool-handling.md +3 -5
- package/dist/agent-src/rules/model-recommendation.md +4 -6
- package/dist/agent-src/rules/no-attribution-footers.md +3 -5
- package/dist/agent-src/rules/no-cheap-questions.md +5 -8
- package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +3 -6
- package/dist/agent-src/rules/no-pr-progress-comments.md +3 -6
- package/dist/agent-src/rules/no-roadmap-references.md +3 -5
- package/dist/agent-src/rules/non-destructive-by-default.md +11 -13
- package/dist/agent-src/rules/notes-first-reasoning.md +3 -5
- package/dist/agent-src/rules/onboarding-gate.md +4 -6
- package/dist/agent-src/rules/output-discipline.md +3 -5
- package/dist/agent-src/rules/package-ci-checks.md +3 -5
- package/dist/agent-src/rules/persona-governance.md +2 -4
- package/dist/agent-src/rules/php-coding.md +3 -5
- package/dist/agent-src/rules/preservation-guard.md +2 -4
- package/dist/agent-src/rules/provider-lifecycle-discipline.md +3 -5
- package/dist/agent-src/rules/reviewer-awareness.md +5 -6
- package/dist/agent-src/rules/roadmap-ci-steps-policy.md +3 -5
- package/dist/agent-src/rules/roadmap-progress-sync.md +5 -5
- package/dist/agent-src/rules/role-mode-adherence.md +2 -4
- package/dist/agent-src/rules/rule-type-governance.md +3 -5
- package/dist/agent-src/rules/runtime-safety.md +2 -4
- package/dist/agent-src/rules/scope-control.md +10 -11
- package/dist/agent-src/rules/security-sensitive-stop.md +4 -5
- package/dist/agent-src/rules/size-enforcement.md +2 -4
- package/dist/agent-src/rules/skill-improvement-trigger.md +3 -5
- package/dist/agent-src/rules/skill-quality.md +3 -5
- package/dist/agent-src/rules/slash-command-routing-policy.md +3 -5
- package/dist/agent-src/rules/source-confidentiality.md +3 -5
- package/dist/agent-src/rules/source-discovery-gate.md +3 -5
- package/dist/agent-src/rules/source-of-truth.md +3 -5
- package/dist/agent-src/rules/strategy-safety-floor.md +3 -5
- package/dist/agent-src/rules/symfony-routing.md +4 -6
- package/dist/agent-src/rules/telegraph-speak.md +4 -5
- package/dist/agent-src/rules/think-before-action.md +7 -4
- package/dist/agent-src/rules/token-budget-discipline.md +29 -5
- package/dist/agent-src/rules/token-efficiency.md +3 -5
- package/dist/agent-src/rules/token-optimizer-maintenance.md +3 -5
- package/dist/agent-src/rules/tool-safety.md +2 -4
- package/dist/agent-src/rules/ui-audit-gate.md +3 -6
- package/dist/agent-src/rules/untrusted-input-defense.md +3 -5
- package/dist/agent-src/rules/upstream-proposal.md +4 -6
- package/dist/agent-src/rules/user-interaction.md +7 -5
- package/dist/agent-src/rules/user-interrupt-priority.md +17 -8
- package/dist/agent-src/rules/verify-before-complete.md +12 -22
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +3 -3
- package/dist/agent-src/scripts/update_roadmap_progress.ts +197 -7
- package/dist/agent-src/skills/adr-create/SKILL.md +48 -42
- package/dist/agent-src/skills/agent-docs-writing/SKILL.md +18 -0
- package/dist/agent-src/skills/agent-security-review/SKILL.md +1 -1
- package/dist/agent-src/skills/ai-council/SKILL.md +14 -1
- package/dist/agent-src/skills/blameless-post-mortem/SKILL.md +0 -3
- package/dist/agent-src/skills/brand/SKILL.md +1 -1
- package/dist/agent-src/skills/brand-identity/SKILL.md +3 -3
- package/dist/agent-src/skills/brand-strategy/SKILL.md +1 -1
- package/dist/agent-src/skills/brand-to-tokens/SKILL.md +3 -3
- package/dist/agent-src/skills/canvas-design/SKILL.md +6 -0
- package/dist/agent-src/skills/check-refs/SKILL.md +7 -4
- package/dist/agent-src/skills/code-review/SKILL.md +1 -0
- package/dist/agent-src/skills/complexity-first-planning/SKILL.md +6 -5
- package/dist/agent-src/skills/condense-memory/SKILL.md +11 -11
- package/dist/agent-src/skills/context-document/SKILL.md +17 -0
- package/dist/agent-src/skills/corpus-grounding/SKILL.md +3 -3
- package/dist/agent-src/skills/decision-record/SKILL.md +6 -0
- package/dist/agent-src/skills/decision-review/SKILL.md +5 -3
- package/dist/agent-src/skills/deep-reading-analyst/SKILL.md +6 -1
- package/dist/agent-src/skills/design-intelligence/SKILL.md +5 -2
- package/dist/agent-src/skills/design-intelligence/references/design-languages.md +1 -1
- package/dist/agent-src/skills/design-tokens/SKILL.md +10 -4
- package/dist/agent-src/skills/design-variations/SKILL.md +127 -0
- package/dist/agent-src/skills/design-variations/evals/triggers.json +17 -0
- package/dist/agent-src/skills/emit-tickets/SKILL.md +4 -4
- package/dist/agent-src/skills/fe-design/SKILL.md +20 -0
- package/dist/agent-src/skills/html-deck/SKILL.md +123 -0
- package/dist/agent-src/skills/html-deck/evals/triggers.json +17 -0
- package/dist/agent-src/skills/html-deck/templates/deck-shell.html +77 -0
- package/dist/agent-src/skills/judge-code-quality/SKILL.md +1 -0
- package/dist/agent-src/skills/laravel/SKILL.md +0 -1
- package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +46 -0
- package/dist/agent-src/skills/lint-skills/SKILL.md +6 -6
- package/dist/agent-src/skills/md-language-check/SKILL.md +3 -3
- package/dist/agent-src/skills/memory-consolidation/SKILL.md +66 -1
- package/dist/agent-src/skills/migration-architect/SKILL.md +1 -0
- package/dist/agent-src/skills/module-detect-on-the-fly/SKILL.md +2 -2
- package/dist/agent-src/skills/performance-analysis/SKILL.md +2 -0
- package/dist/agent-src/skills/prediction-pool-optimizer/SKILL.md +4 -4
- package/dist/agent-src/skills/premortem/SKILL.md +0 -3
- package/dist/agent-src/skills/project-analysis-core/SKILL.md +16 -0
- package/dist/agent-src/skills/reasoning-orchestrator/SKILL.md +3 -1
- package/dist/agent-src/skills/release-comms/SKILL.md +46 -45
- package/dist/agent-src/skills/roadmap-management/SKILL.md +21 -0
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +32 -2
- package/dist/agent-src/skills/root-cause-frameworks/SKILL.md +0 -3
- package/dist/agent-src/skills/security-audit/SKILL.md +1 -0
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +4 -0
- package/dist/agent-src/skills/source-discovery/SKILL.md +22 -3
- package/dist/agent-src/skills/subagent-orchestration/SKILL.md +33 -14
- package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +11 -0
- package/dist/agent-src/skills/subagent-orchestration/prompts/do-in-steps.md +8 -0
- package/dist/agent-src/skills/systematic-debugging/SKILL.md +29 -0
- package/dist/agent-src/skills/threat-modeling/SKILL.md +2 -2
- package/dist/agent-src/skills/typography-system/SKILL.md +2 -2
- package/dist/agent-src/skills/verify-completion-evidence/SKILL.md +2 -0
- package/dist/agent-src/skills/wireframe/SKILL.md +118 -0
- package/dist/agent-src/skills/wireframe/evals/triggers.json +17 -0
- package/dist/agent-src/templates/agent-settings.md +22 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/command.md +2 -2
- package/dist/agent-src/templates/contexts/knowledge-pages.md +116 -0
- package/dist/agent-src/templates/hooks/pre-commit-frontmatter +1 -1
- package/dist/agent-src/templates/roadmaps.md +70 -2
- package/dist/agent-src/templates/rule.md +1 -1
- package/dist/agent-src/templates/scripts/README.md +3 -3
- package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +109 -0
- package/dist/agent-src/templates/tickets.md +8 -8
- package/dist/cli/commands/recordTriggerEval.test.js +1 -1
- package/dist/cli/commands/recordTriggerEval.test.js.map +1 -1
- package/dist/cli/initRouting.js +4 -2
- package/dist/cli/initRouting.js.map +1 -1
- package/dist/cli/registry.js +1 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +718 -240
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +8 -8
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +43 -28
- package/dist/discovery/trust-report.md +12 -11
- package/dist/discovery/workspaces.json +29 -18
- package/dist/install/preflight.js +173 -0
- package/dist/install/preflight.js.map +1 -0
- package/dist/mcp/registry-manifest.json +4 -4
- package/dist/router.json +1 -1
- package/dist/server/routes/settings.js +4 -0
- package/dist/server/routes/settings.js.map +1 -1
- package/dist/server/schemas/settings.js +3 -1
- package/dist/server/schemas/settings.js.map +1 -1
- package/docs/CLAIMS.md +108 -0
- package/docs/MIGRATION.md +3 -3
- package/docs/architecture.md +5 -5
- package/docs/archive/CHANGELOG-pre-8.0.0.md +301 -0
- package/docs/benchmark.md +133 -2
- package/docs/benchmark.pinned.yml +31 -0
- package/docs/capability-matrix.md +1 -0
- package/docs/catalog.md +70 -60
- package/docs/command-flows.md +15 -3
- package/docs/comparison.yaml +35 -0
- package/docs/contracts/agents-layout.md +148 -0
- package/docs/contracts/brand-token-consumption.md +5 -0
- package/docs/contracts/capability-boundary.md +5 -0
- package/docs/contracts/command-category-governance.md +5 -0
- package/docs/contracts/command-clusters.md +1 -0
- package/docs/contracts/command-surface-tiers.md +1 -1
- package/docs/contracts/conformance.md +84 -0
- package/docs/contracts/creative-pack-boundary.md +5 -0
- package/docs/contracts/discovery-manifest.schema.json +5 -4
- package/docs/contracts/file-ownership-matrix.json +4605 -985
- package/docs/contracts/governance-enforcement-projection.md +5 -0
- package/docs/contracts/gui-wizard.md +1 -1
- package/docs/contracts/hook-architecture-v1.md +2 -2
- package/docs/contracts/implement-ticket-flow.md +1 -1
- package/docs/contracts/kernel-membership.md +13 -0
- package/docs/contracts/mcp-tool-inventory.md +23 -23
- package/docs/contracts/no-runtime-boundary.md +6 -1
- package/docs/contracts/review-lens-schema.md +5 -0
- package/docs/contracts/rule-router.md +102 -8
- package/docs/contracts/skill-bundled-assets.md +1 -1
- package/docs/contracts/skill-dry-run.md +1 -1
- package/docs/contracts/subagent-boundary.md +5 -0
- package/docs/contracts/ticket-bundle-format.md +9 -4
- package/docs/contracts/tier-3-contrib-plugin.md +2 -2
- package/docs/contracts/write-engine.md +3 -0
- package/docs/customization.md +87 -15
- package/docs/decisions/ADR-107-legal-domain-pack-adoption.md +1 -1
- package/docs/decisions/ADR-109-subagent-v1-contract.md +246 -0
- package/docs/decisions/ADR-110-discipline-profile-resolution-locus.md +105 -0
- package/docs/decisions/INDEX.md +2 -0
- package/docs/distribution/awesome-list-submission.md +46 -0
- package/docs/distribution/launch-story-draft.md +58 -0
- package/docs/end-to-end-walkthroughs.md +2 -2
- package/docs/getting-started.md +2 -2
- package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +24 -0
- package/docs/guidelines/agent-infra/corpus-grounding-authoring.md +1 -1
- package/docs/guidelines/agent-infra/linked-projects-onboarding-gate.md +2 -2
- package/docs/guidelines/agent-infra/missing-tool-handling.md +3 -3
- package/docs/guidelines/agent-infra/verify-before-complete-demos.md +2 -2
- package/docs/guidelines/augment-portability-patterns.md +1 -1
- package/docs/guidelines/code-clarity.md +19 -0
- package/docs/guidelines/design-antipatterns-triggers.json +2 -1
- package/docs/guidelines/design-antipatterns.md +10 -1
- package/docs/guidelines/design-modes.md +6 -0
- package/docs/guidelines/php/general.md +9 -1
- package/docs/guidelines/php/php-coding-patterns.md +7 -0
- package/docs/guides/cross-repo-retrieval.md +1 -1
- package/docs/guides/frontend-design-corpus-refresh.md +2 -2
- package/docs/guides/local-analytics.md +4 -4
- package/docs/guides/skill-discovery.md +1 -1
- package/docs/guides/skill-preview.md +1 -1
- package/docs/hook-payload-capture.md +6 -6
- package/docs/install-friction-report.md +66 -0
- package/docs/installation.md +1 -1
- package/docs/maintainers/optional-media-deps.md +50 -0
- package/docs/mcp-server.md +11 -12
- package/docs/media/proof-demo.cast +14 -0
- package/docs/media/proof-demo.gif +0 -0
- package/docs/migration/consumer-template-consumption-model.md +1 -1
- package/docs/migration/divergences/bench-stats-float-precision.md +1 -1
- package/docs/migration/node-floor.md +1 -1
- package/docs/migration/yaml-roundtrip-spike.md +1 -1
- package/docs/personas.md +16 -5
- package/docs/positioning-evidence.md +86 -0
- package/docs/proof.md +86 -0
- package/docs/skills-catalog.md +1 -1
- package/docs/troubleshooting.md +8 -8
- package/docs/wedge/production-validator/README.md +57 -0
- package/docs/wedge/production-validator/production-validator.md +56 -0
- package/docs/wizard.md +2 -2
- package/package.json +1 -1
- package/src/config/agent-settings.template.yml +59 -4
- package/src/config/agents-paths.yml +254 -0
- package/src/config/budgets.yml +16 -0
- package/src/config/discovery/packs.yml +1 -0
- package/src/config/discovery/unassigned-artefacts.yml +2 -0
- package/src/config/gitignore-block.txt +25 -0
- package/src/config/host-capabilities.yml +31 -0
- package/src/config/profiles/balanced.ini +4 -0
- package/src/config/profiles/full.ini +4 -0
- package/src/config/profiles/minimal.ini +4 -0
- package/src/scripts/_cli/cmd_conformance.ts +716 -0
- package/src/scripts/_cli/cmd_doctor.ts +23 -2
- package/src/scripts/_cli/cmd_fleet.ts +401 -0
- package/src/scripts/_cli/cmd_preflight.ts +159 -0
- package/src/scripts/_dispatch.bash +10 -0
- package/src/scripts/_lib/knowledge_events.ts +193 -0
- package/src/scripts/_lib/subagent_steering.ts +115 -3
- package/src/scripts/_lib/text_similarity.ts +75 -0
- package/src/scripts/ai-video/test-pipeline.sh +1 -1
- package/src/scripts/ai_council/clients.ts +19 -3
- package/src/scripts/append_contested.ts +112 -0
- package/src/scripts/audit_auto_rules.ts +11 -1
- package/src/scripts/audit_mcp_tools.ts +25 -11
- package/src/scripts/bench_ab_v2_run.ts +527 -40
- package/src/scripts/bench_ab_v2_stats.ts +6 -0
- package/src/scripts/bench_matrix.ts +266 -0
- package/src/scripts/bootstrap_knowledge.ts +267 -0
- package/src/scripts/build_discovery_manifest.ts +42 -2
- package/src/scripts/build_proof.ts +214 -0
- package/src/scripts/check_always_budget.ts +3 -0
- package/src/scripts/check_augment_description_cap.ts +2 -2
- package/src/scripts/check_claims.ts +270 -0
- package/src/scripts/check_comparison.ts +79 -0
- package/src/scripts/check_generated_artefact_headers.ts +109 -0
- package/src/scripts/check_generator_output_coverage.ts +142 -0
- package/src/scripts/check_gitignore_freshness.ts +127 -0
- package/src/scripts/check_knowledge_pages.ts +210 -0
- package/src/scripts/check_knowledge_sharing.ts +162 -0
- package/src/scripts/check_media_deps.ts +91 -0
- package/src/scripts/check_memory_contradiction.ts +280 -0
- package/src/scripts/check_memory_similarity.ts +134 -0
- package/src/scripts/check_quality_regression.ts +56 -10
- package/src/scripts/check_references.ts +3 -1
- package/src/scripts/check_release_pr_shape.ts +4 -0
- package/src/scripts/check_site_links.ts +135 -0
- package/src/scripts/check_skill_gaps.ts +99 -0
- package/src/scripts/check_token_quality_golden.ts +197 -11
- package/src/scripts/check_tracked_but_ignored.ts +67 -0
- package/src/scripts/cluster_near_miss_patterns.ts +0 -0
- package/src/scripts/compile_router.ts +30 -3
- package/src/scripts/condense.ts +350 -14
- package/src/scripts/consolidate_knowledge_events.ts +192 -0
- package/src/scripts/degrade_to_pointer.ts +136 -0
- package/src/scripts/design_slop_rules.test.ts +15 -0
- package/src/scripts/design_slop_rules.ts +28 -0
- package/src/scripts/emit_knowledge_event.ts +158 -0
- package/src/scripts/export_replay_corpus.ts +187 -0
- package/src/scripts/external_sources_denylist.json +7 -2
- package/src/scripts/fold_intake.ts +281 -0
- package/src/scripts/generate_capability_matrix.ts +9 -1
- package/src/scripts/generate_knowledge_index.ts +222 -0
- package/src/scripts/hook_manifest.yaml +26 -14
- package/src/scripts/hooks/dispatch_hook.ts +18 -0
- package/src/scripts/hot_context_hook.ts +372 -0
- package/src/scripts/install +47 -0
- package/src/scripts/install-hooks.sh +17 -0
- package/src/scripts/inventory_meta_layers.ts +11 -0
- package/src/scripts/janitor.ts +258 -0
- package/src/scripts/lint_agents_layout.ts +74 -15
- package/src/scripts/lint_bench_ab.ts +4 -1
- package/src/scripts/lint_featured_skills.ts +0 -0
- package/src/scripts/lint_framework_leakage_allowlist.json +26 -3
- package/src/scripts/lint_knowledge_scale.ts +250 -0
- package/src/scripts/lint_legal_pack.ts +67 -0
- package/src/scripts/lint_persona_governance.ts +8 -3
- package/src/scripts/lint_regression.ts +15 -0
- package/src/scripts/lint_roadmap_blockers.ts +202 -0
- package/src/scripts/lint_roadmap_complexity.ts +81 -2
- package/src/scripts/lint_subagent_determinism.ts +125 -0
- package/src/scripts/measure_augment_budget.ts +46 -6
- package/src/scripts/measure_patterns.ts +4 -3
- package/src/scripts/measure_skill_reduction.ts +6 -6
- package/src/scripts/migration_status.ts +6 -2
- package/src/scripts/mine_missing_guardrails.ts +189 -0
- package/src/scripts/parity/phase_gate.ts +1 -1
- package/src/scripts/parity/replay.ts +21 -0
- package/src/scripts/project_thin_rules.ts +120 -16
- package/src/scripts/release.ts +39 -1
- package/src/scripts/render_benchmark_composite.ts +378 -0
- package/src/scripts/roadmap_progress_hook.ts +101 -43
- package/src/scripts/schemas/skill.schema.json +27 -0
- package/src/scripts/schemas/subagent.schema.json +106 -0
- package/src/scripts/skill_linter.ts +1 -0
- package/src/scripts/smoke/kernel.sh +5 -4
- package/src/scripts/surface-tiers.yml +1 -0
- package/src/scripts/sync_gitignore.ts +4 -0
- package/src/scripts/update_skill_candidates.ts +172 -0
- package/src/scripts/validate_frontmatter.ts +1 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed observation-event schema — road-to-knowledge-system Phase 5
|
|
3
|
+
* (living-context capture). During normal task work, an agent that
|
|
4
|
+
* observes one of these four conditions appends an event to the
|
|
5
|
+
* gitignored `agents/knowledge/intake/events-YYYY-MM.jsonl` stream —
|
|
6
|
+
* never a tracked page mid-task. Consolidation (`/team-knowledge
|
|
7
|
+
* consolidate`) reads this stream and proposes tracked-page
|
|
8
|
+
* creates/updates as a reviewable batch.
|
|
9
|
+
*
|
|
10
|
+
* Four event types, one per capture trigger:
|
|
11
|
+
* - convention_detected — a coding standard/pattern observed with evidence
|
|
12
|
+
* - mistake_made — an error traced to a followed (possibly stale) context
|
|
13
|
+
* - api_shape_learned — a request/response shape observed on a real call
|
|
14
|
+
* - context_stale — observed reality contradicts a documented page
|
|
15
|
+
*/
|
|
16
|
+
import * as fs from 'node:fs';
|
|
17
|
+
import * as path from 'node:path';
|
|
18
|
+
|
|
19
|
+
export interface ConventionDetectedEvent {
|
|
20
|
+
type: 'convention_detected';
|
|
21
|
+
ts: string; // ISO-8601
|
|
22
|
+
pattern: string;
|
|
23
|
+
evidence: string[]; // file:line references
|
|
24
|
+
sampleSize: number;
|
|
25
|
+
scope: 'project' | 'global';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface MistakeMadeEvent {
|
|
29
|
+
type: 'mistake_made';
|
|
30
|
+
ts: string;
|
|
31
|
+
errorCategory: string;
|
|
32
|
+
contextSource: string | null; // which knowledge page (if any) was followed
|
|
33
|
+
correction: string;
|
|
34
|
+
recurrenceKey: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface ApiShapeLearnedEvent {
|
|
38
|
+
type: 'api_shape_learned';
|
|
39
|
+
ts: string;
|
|
40
|
+
endpoint: string;
|
|
41
|
+
method: string;
|
|
42
|
+
requestSchema: unknown;
|
|
43
|
+
responseSchema: unknown;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ContextStaleEvent {
|
|
47
|
+
type: 'context_stale';
|
|
48
|
+
ts: string;
|
|
49
|
+
pagePath: string;
|
|
50
|
+
field: string;
|
|
51
|
+
expected: unknown;
|
|
52
|
+
actual: unknown;
|
|
53
|
+
evidence: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export type KnowledgeEvent = ConventionDetectedEvent | MistakeMadeEvent | ApiShapeLearnedEvent | ContextStaleEvent;
|
|
57
|
+
|
|
58
|
+
export type ValidationResult = { valid: true; event: KnowledgeEvent } | { valid: false; errors: string[] };
|
|
59
|
+
|
|
60
|
+
function isPlainObject(v: unknown): v is Record<string, unknown> {
|
|
61
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function isNonEmptyString(v: unknown): v is string {
|
|
65
|
+
return typeof v === 'string' && v.length > 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const ISO_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/;
|
|
69
|
+
|
|
70
|
+
/** Validates the shape for the declared `type`. Does not require the event to be well-formed JSON — call after JSON.parse. */
|
|
71
|
+
export function validateEvent(raw: unknown): ValidationResult {
|
|
72
|
+
const errors: string[] = [];
|
|
73
|
+
if (!isPlainObject(raw)) {
|
|
74
|
+
return { valid: false, errors: ['event must be a JSON object'] };
|
|
75
|
+
}
|
|
76
|
+
if (!isNonEmptyString(raw.ts) || !ISO_RE.test(raw.ts)) {
|
|
77
|
+
errors.push('ts must be an ISO-8601 timestamp string');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
switch (raw.type) {
|
|
81
|
+
case 'convention_detected': {
|
|
82
|
+
if (!isNonEmptyString(raw.pattern)) errors.push('pattern is required');
|
|
83
|
+
if (!Array.isArray(raw.evidence) || raw.evidence.length === 0 || !raw.evidence.every((e) => typeof e === 'string')) {
|
|
84
|
+
errors.push('evidence must be a non-empty string array');
|
|
85
|
+
}
|
|
86
|
+
if (typeof raw.sampleSize !== 'number' || raw.sampleSize < 1) errors.push('sampleSize must be a positive number');
|
|
87
|
+
if (raw.scope !== 'project' && raw.scope !== 'global') errors.push('scope must be "project" or "global"');
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
case 'mistake_made': {
|
|
91
|
+
if (!isNonEmptyString(raw.errorCategory)) errors.push('errorCategory is required');
|
|
92
|
+
if (raw.contextSource !== null && !isNonEmptyString(raw.contextSource)) {
|
|
93
|
+
errors.push('contextSource must be a string or null');
|
|
94
|
+
}
|
|
95
|
+
if (!isNonEmptyString(raw.correction)) errors.push('correction is required');
|
|
96
|
+
if (!isNonEmptyString(raw.recurrenceKey)) errors.push('recurrenceKey is required');
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
case 'api_shape_learned': {
|
|
100
|
+
if (!isNonEmptyString(raw.endpoint)) errors.push('endpoint is required');
|
|
101
|
+
if (!isNonEmptyString(raw.method)) errors.push('method is required');
|
|
102
|
+
if (!('requestSchema' in raw)) errors.push('requestSchema is required');
|
|
103
|
+
if (!('responseSchema' in raw)) errors.push('responseSchema is required');
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
case 'context_stale': {
|
|
107
|
+
if (!isNonEmptyString(raw.pagePath)) errors.push('pagePath is required');
|
|
108
|
+
if (!isNonEmptyString(raw.field)) errors.push('field is required');
|
|
109
|
+
if (!('expected' in raw)) errors.push('expected is required');
|
|
110
|
+
if (!('actual' in raw)) errors.push('actual is required');
|
|
111
|
+
if (!isNonEmptyString(raw.evidence)) errors.push('evidence is required');
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
default:
|
|
115
|
+
errors.push(
|
|
116
|
+
`unknown type "${String(raw.type)}" (expected one of convention_detected|mistake_made|api_shape_learned|context_stale)`,
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (errors.length > 0) {
|
|
121
|
+
return { valid: false, errors };
|
|
122
|
+
}
|
|
123
|
+
return { valid: true, event: raw as unknown as KnowledgeEvent };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const INTAKE_DIR = path.join('agents', 'knowledge', 'intake');
|
|
127
|
+
|
|
128
|
+
/** sorted(events-*.jsonl) under the intake dir — absolute-or-relative per `dir`. */
|
|
129
|
+
export function intakeFiles(dir: string = INTAKE_DIR): string[] {
|
|
130
|
+
let names: string[];
|
|
131
|
+
try {
|
|
132
|
+
names = fs.readdirSync(dir);
|
|
133
|
+
} catch {
|
|
134
|
+
return [];
|
|
135
|
+
}
|
|
136
|
+
return names
|
|
137
|
+
.filter((n) => n.startsWith('events-') && n.endsWith('.jsonl'))
|
|
138
|
+
.sort()
|
|
139
|
+
.map((n) => path.join(dir, n));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function monthlyFile(dir: string, ts: string): string {
|
|
143
|
+
const ym = ts.slice(0, 7); // "YYYY-MM"
|
|
144
|
+
return path.join(dir, `events-${ym}.jsonl`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Appends a validated event as one JSONL line to the current month's intake file. Throws if the event fails validation. */
|
|
148
|
+
export function appendEvent(event: KnowledgeEvent, dir: string = INTAKE_DIR): void {
|
|
149
|
+
const result = validateEvent(event);
|
|
150
|
+
if (!result.valid) {
|
|
151
|
+
throw new Error(`invalid knowledge event: ${result.errors.join('; ')}`);
|
|
152
|
+
}
|
|
153
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
154
|
+
const file = monthlyFile(dir, event.ts);
|
|
155
|
+
fs.appendFileSync(file, JSON.stringify(event) + '\n', 'utf8');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** Deletes every `events-*.jsonl` file under `dir` — called by `/team-knowledge consolidate` once a batch has been proposed and approved. All-or-nothing by design: consolidation processes the FULL pending backlog in one pass, so there is no partial-consumption state to track. No-op (never throws) if the dir does not exist or is already empty. */
|
|
159
|
+
export function clearAllEvents(dir: string = INTAKE_DIR): void {
|
|
160
|
+
for (const file of intakeFiles(dir)) {
|
|
161
|
+
try {
|
|
162
|
+
fs.unlinkSync(file);
|
|
163
|
+
} catch {
|
|
164
|
+
// Already gone — fine.
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** Reads and validates every line across all intake files under `dir`. Malformed JSON lines are skipped (not thrown), matching the tolerant-reader convention used by memory_signal.ts's own intake scan. */
|
|
170
|
+
export function readAllEvents(dir: string = INTAKE_DIR): KnowledgeEvent[] {
|
|
171
|
+
const out: KnowledgeEvent[] = [];
|
|
172
|
+
for (const file of intakeFiles(dir)) {
|
|
173
|
+
let text: string;
|
|
174
|
+
try {
|
|
175
|
+
text = fs.readFileSync(file, 'utf8');
|
|
176
|
+
} catch {
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
for (const rawLine of text.split('\n')) {
|
|
180
|
+
const line = rawLine.trim();
|
|
181
|
+
if (!line) continue;
|
|
182
|
+
let parsed: unknown;
|
|
183
|
+
try {
|
|
184
|
+
parsed = JSON.parse(line);
|
|
185
|
+
} catch {
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
const result = validateEvent(parsed);
|
|
189
|
+
if (result.valid) out.push(result.event);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return out;
|
|
193
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Subagent steering & guardrails (Phase 5).
|
|
3
3
|
*
|
|
4
|
-
* Pure
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Pure helpers (isLayerDisabled, budgetHalt, breachedGuardrails) + one
|
|
5
|
+
* I/O reader (readOrchestrationMetrics) that aggregates telemetry from
|
|
6
|
+
* the audit-log-v1 JSONL to feed into breachedGuardrails. Contract:
|
|
7
7
|
* `src/agent-src/contexts/execution/subagent-steering.md`.
|
|
8
8
|
*
|
|
9
9
|
* Automatic cohort-level disable is OUT OF SCOPE — a config package runs no
|
|
@@ -41,6 +41,53 @@ export function budgetHalt(consecutiveFailures: number): boolean {
|
|
|
41
41
|
return consecutiveFailures >= MAX_ATTEMPTS_PER_TARGET;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Failure-type stop (road-to-flow-learnings Phase 2) — an APPLICATION of the
|
|
46
|
+
* N=3 budget at subagent-type granularity, never a new mechanism: two
|
|
47
|
+
* consecutive verification-failed returns from the same subagent type plus
|
|
48
|
+
* the escalation step exhaust the three-attempt budget. When this fires the
|
|
49
|
+
* orchestrator stops dispatching that type for the session, surfaces both
|
|
50
|
+
* failures to the human, and runs the remaining slices in-session. There is
|
|
51
|
+
* still NO automatic cohort-disable — the Iron Law above stands unchanged.
|
|
52
|
+
*/
|
|
53
|
+
export const MAX_CONSECUTIVE_TYPE_FAILURES = MAX_ATTEMPTS_PER_TARGET - 1;
|
|
54
|
+
|
|
55
|
+
/** True when a subagent type has exhausted its in-session dispatch budget. */
|
|
56
|
+
export function typeStop(consecutiveVerificationFailures: number): boolean {
|
|
57
|
+
return consecutiveVerificationFailures >= MAX_CONSECUTIVE_TYPE_FAILURES;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Decision returned by {@link sliceDispatchAllowed}. */
|
|
61
|
+
export interface SliceDispatchDecision {
|
|
62
|
+
readonly allowed: boolean;
|
|
63
|
+
readonly reason: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Ordered-slice dependency gate (road-to-flow-learnings Phase 2) — makes the
|
|
68
|
+
* `do-in-steps` contract deterministic: a slice that declares a parent MUST
|
|
69
|
+
* NOT dispatch before the parent's return has been verified by the
|
|
70
|
+
* orchestrator. Slices without a declared parent (roots / independent
|
|
71
|
+
* slices) always pass this gate.
|
|
72
|
+
*/
|
|
73
|
+
export function sliceDispatchAllowed(
|
|
74
|
+
declaredParent: string | null,
|
|
75
|
+
verifiedReturns: ReadonlySet<string>,
|
|
76
|
+
): SliceDispatchDecision {
|
|
77
|
+
if (declaredParent === null || declaredParent.length === 0) {
|
|
78
|
+
return { allowed: true, reason: 'no declared parent — root or independent slice' };
|
|
79
|
+
}
|
|
80
|
+
if (verifiedReturns.has(declaredParent)) {
|
|
81
|
+
return { allowed: true, reason: `parent '${declaredParent}' has a verified return` };
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
allowed: false,
|
|
85
|
+
reason:
|
|
86
|
+
`parent '${declaredParent}' has no verified return in session state — ` +
|
|
87
|
+
'verify (or revise) the parent before dispatching this slice',
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
44
91
|
export interface GuardrailMetrics {
|
|
45
92
|
/** Observed token spend / single-agent baseline (e.g. 2.4 = 2.4x). */
|
|
46
93
|
token_ratio: number;
|
|
@@ -62,3 +109,68 @@ export function breachedGuardrails(m: GuardrailMetrics): string[] {
|
|
|
62
109
|
if (m.user_override_rate > GUARDRAILS.user_override_rate) breached.push('user_override');
|
|
63
110
|
return breached;
|
|
64
111
|
}
|
|
112
|
+
|
|
113
|
+
/** Raw orchestration entry parsed from an audit-log-v1 JSONL line. */
|
|
114
|
+
export interface OrchEntry {
|
|
115
|
+
task_size_estimate: number;
|
|
116
|
+
spawn_count: number;
|
|
117
|
+
token_delta: number;
|
|
118
|
+
outcome: string;
|
|
119
|
+
verify_mode: string;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Read orchestration telemetry lines from audit-log JSONL and aggregate into
|
|
124
|
+
* GuardrailMetrics. Uses dependency-injected line reader for testability.
|
|
125
|
+
*
|
|
126
|
+
* token_ratio approximation: (task_size_estimate + token_delta) /
|
|
127
|
+
* task_size_estimate (proxy for orchestrated/single-agent ratio; 1.0 when
|
|
128
|
+
* task_size_estimate == 0). Positive token_delta = orchestration cost more.
|
|
129
|
+
*
|
|
130
|
+
* user_override_rate cannot be measured from telemetry alone — returns 0.
|
|
131
|
+
*/
|
|
132
|
+
export function readOrchestrationMetrics(
|
|
133
|
+
lines: string[],
|
|
134
|
+
): GuardrailMetrics {
|
|
135
|
+
const entries: OrchEntry[] = [];
|
|
136
|
+
for (const line of lines) {
|
|
137
|
+
const trimmed = line.trim();
|
|
138
|
+
if (!trimmed) continue;
|
|
139
|
+
try {
|
|
140
|
+
const parsed = JSON.parse(trimmed) as Record<string, unknown>;
|
|
141
|
+
if (parsed['input_kind'] !== 'orchestration') continue;
|
|
142
|
+
const orch = parsed['orchestration'] as Record<string, unknown> | undefined;
|
|
143
|
+
if (!orch) continue;
|
|
144
|
+
entries.push({
|
|
145
|
+
task_size_estimate: Number(orch['task_size_estimate'] ?? 0),
|
|
146
|
+
spawn_count: Number(orch['spawn_count'] ?? 0),
|
|
147
|
+
token_delta: Number(orch['token_delta'] ?? 0),
|
|
148
|
+
outcome: String(orch['outcome'] ?? ''),
|
|
149
|
+
verify_mode: String(orch['verify_mode'] ?? ''),
|
|
150
|
+
});
|
|
151
|
+
} catch {
|
|
152
|
+
// skip malformed lines
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (entries.length === 0) {
|
|
157
|
+
return { token_ratio: 1, spawn_failure_rate: 0, verify_skip_rate: 0, user_override_rate: 0 };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const token_ratios = entries.map(e =>
|
|
161
|
+
e.task_size_estimate > 0
|
|
162
|
+
? (e.task_size_estimate + e.token_delta) / e.task_size_estimate
|
|
163
|
+
: 1,
|
|
164
|
+
);
|
|
165
|
+
const token_ratio = token_ratios.reduce((a, b) => a + b, 0) / token_ratios.length;
|
|
166
|
+
|
|
167
|
+
const failures = entries.filter(e => e.outcome === 'BLOCKED' || e.outcome === 'killed').length;
|
|
168
|
+
const verify_skips = entries.filter(e => e.verify_mode === 'none').length;
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
token_ratio,
|
|
172
|
+
spawn_failure_rate: failures / entries.length,
|
|
173
|
+
verify_skip_rate: verify_skips / entries.length,
|
|
174
|
+
user_override_rate: 0, // cannot measure from telemetry alone
|
|
175
|
+
};
|
|
176
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token-based Jaccard similarity — the dedup primitive for the
|
|
3
|
+
* road-to-knowledge-system capture-hygiene layer (Phase 2).
|
|
4
|
+
*
|
|
5
|
+
* Deterministic, no embeddings, no network. Thresholds per the
|
|
6
|
+
* 2026-07-05 council verdict (AutoSci dedup discipline, adapted):
|
|
7
|
+
* >= MERGE_THRESHOLD → treat as a duplicate, suggest the matched entry
|
|
8
|
+
* >= WARN_THRESHOLD → surface the nearest match, let the human decide
|
|
9
|
+
* below WARN_THRESHOLD → no conflict, proceed to create
|
|
10
|
+
*
|
|
11
|
+
* Deliberately does NOT touch `memory_signal.ts` — that script is a
|
|
12
|
+
* byte-faithful parity twin of its retired Python original ("no
|
|
13
|
+
* behaviour changes" is a load-bearing contract of that file). This
|
|
14
|
+
* module is consumed as an ADDITIONAL, advisory check layered on top,
|
|
15
|
+
* from `check_memory_similarity.ts` and later the knowledge-page
|
|
16
|
+
* consolidation flow (Phase 5).
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export const MERGE_THRESHOLD = 0.8;
|
|
20
|
+
export const WARN_THRESHOLD = 0.4;
|
|
21
|
+
|
|
22
|
+
export type SimilarityClass = 'merge' | 'warn' | 'create';
|
|
23
|
+
|
|
24
|
+
const TOKEN_RE = /[a-z0-9]+/g;
|
|
25
|
+
|
|
26
|
+
/** Lowercase, split on non-alphanumeric runs, drop empties. Order-independent by design (Jaccard is set-based). */
|
|
27
|
+
export function tokenize(text: string): Set<string> {
|
|
28
|
+
const tokens = (text.toLowerCase().match(TOKEN_RE) ?? []).filter((t) => t.length > 0);
|
|
29
|
+
return new Set(tokens);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Jaccard(A, B) = |A ∩ B| / |A ∪ B|. Two empty inputs are defined as identical (1.0); one empty vs. non-empty is 0. */
|
|
33
|
+
export function jaccardSimilarity(a: string, b: string): number {
|
|
34
|
+
const setA = tokenize(a);
|
|
35
|
+
const setB = tokenize(b);
|
|
36
|
+
if (setA.size === 0 && setB.size === 0) return 1.0;
|
|
37
|
+
if (setA.size === 0 || setB.size === 0) return 0.0;
|
|
38
|
+
|
|
39
|
+
let intersection = 0;
|
|
40
|
+
for (const tok of setA) {
|
|
41
|
+
if (setB.has(tok)) intersection++;
|
|
42
|
+
}
|
|
43
|
+
const union = setA.size + setB.size - intersection;
|
|
44
|
+
return union === 0 ? 1.0 : intersection / union;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function classifySimilarity(score: number): SimilarityClass {
|
|
48
|
+
if (score >= MERGE_THRESHOLD) return 'merge';
|
|
49
|
+
if (score >= WARN_THRESHOLD) return 'warn';
|
|
50
|
+
return 'create';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface Candidate {
|
|
54
|
+
id: string;
|
|
55
|
+
text: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface SimilarityMatch {
|
|
59
|
+
id: string;
|
|
60
|
+
text: string;
|
|
61
|
+
score: number;
|
|
62
|
+
classification: SimilarityClass;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Best (highest-score) match across candidates, or null when candidates is empty. Ties resolve to the first candidate in iteration order (deterministic given a deterministic input order). */
|
|
66
|
+
export function findMostSimilar(target: string, candidates: Iterable<Candidate>): SimilarityMatch | null {
|
|
67
|
+
let best: SimilarityMatch | null = null;
|
|
68
|
+
for (const candidate of candidates) {
|
|
69
|
+
const score = jaccardSimilarity(target, candidate.text);
|
|
70
|
+
if (best === null || score > best.score) {
|
|
71
|
+
best = { id: candidate.id, text: candidate.text, score, classification: classifySimilarity(score) };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return best;
|
|
75
|
+
}
|
|
@@ -384,9 +384,25 @@ export class AnthropicClient extends ExternalAIClient {
|
|
|
384
384
|
const latency_ms = _elapsedMs(t0);
|
|
385
385
|
let text = '';
|
|
386
386
|
const content = _getattr(response, 'content', null);
|
|
387
|
-
if (_pyTruthy(content)) {
|
|
388
|
-
|
|
389
|
-
|
|
387
|
+
if (_pyTruthy(content) && Array.isArray(content)) {
|
|
388
|
+
// Join every text-type block. Extended-thinking models (e.g.
|
|
389
|
+
// claude-fable-5) return a `thinking`/`reasoning` block FIRST, so the
|
|
390
|
+
// legacy `content[0].text` extraction yielded '' despite real output
|
|
391
|
+
// (observed: 3191 output_tokens, text len 0). Collect text from all
|
|
392
|
+
// `type === 'text'` (or untyped) blocks; skip thinking / tool_use.
|
|
393
|
+
const parts: string[] = [];
|
|
394
|
+
for (const block of content as unknown[]) {
|
|
395
|
+
const btype = _getattr(block, 'type', null);
|
|
396
|
+
const btext = _getattr(block, 'text', '') as string;
|
|
397
|
+
if ((btype === null || btype === 'text') && typeof btext === 'string' && btext) {
|
|
398
|
+
parts.push(btext);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
text = parts.join('');
|
|
402
|
+
if (!text) {
|
|
403
|
+
const first = (content as unknown[])[0];
|
|
404
|
+
text = (_getattr(first, 'text', '') as string) || '';
|
|
405
|
+
}
|
|
390
406
|
}
|
|
391
407
|
const usage = _getattr(response, 'usage', null);
|
|
392
408
|
return new CouncilResponse({
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Contested-annotation writer — road-to-knowledge-system Phase 5. When a
|
|
4
|
+
* live contradiction is found between a knowledge page and observed
|
|
5
|
+
* reality and the user declines an immediate fix (see the hybrid
|
|
6
|
+
* immediate-fix flow in `knowledge-pages.md`), this appends an
|
|
7
|
+
* append-only `contested:` entry to the page's frontmatter — never a
|
|
8
|
+
* silent rewrite of the claimed content. `check_knowledge_pages.ts`
|
|
9
|
+
* already warns once a page carries 2+ unresolved entries; this script
|
|
10
|
+
* is the writer half of that contract.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* append_contested.ts --page <path> --trigger <trigger> --evidence "<text>" --session <id> --timestamp <ISO-8601>
|
|
14
|
+
*
|
|
15
|
+
* Exit codes: 0 = appended, 1 = usage error / page not found, 3 = internal error.
|
|
16
|
+
*/
|
|
17
|
+
import * as fs from 'node:fs';
|
|
18
|
+
import * as path from 'node:path';
|
|
19
|
+
import process from 'node:process';
|
|
20
|
+
import { fileURLToPath } from 'node:url';
|
|
21
|
+
import YAML from 'yaml';
|
|
22
|
+
|
|
23
|
+
const PROG = 'append_contested.ts';
|
|
24
|
+
const FRONTMATTER_RE = /^---[ \t]*\r?\n([\s\S]*?)\r?\n---[ \t]*\r?\n/;
|
|
25
|
+
|
|
26
|
+
export interface ContestedEntry {
|
|
27
|
+
timestamp: string;
|
|
28
|
+
trigger: string;
|
|
29
|
+
evidence: string;
|
|
30
|
+
session: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function isPlainObject(v: unknown): v is Record<string, unknown> {
|
|
34
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Appends `entry` to the page's frontmatter `contested:` array (creating the array/frontmatter block if absent). The page body is never touched. */
|
|
38
|
+
export function appendContestedEntry(content: string, entry: ContestedEntry): string {
|
|
39
|
+
const match = FRONTMATTER_RE.exec(content);
|
|
40
|
+
const body = match ? content.slice(match[0].length) : content;
|
|
41
|
+
|
|
42
|
+
let fm: Record<string, unknown> = {};
|
|
43
|
+
if (match?.[1] !== undefined) {
|
|
44
|
+
const parsed = YAML.parse(match[1]);
|
|
45
|
+
if (isPlainObject(parsed)) fm = parsed;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const existing = Array.isArray(fm.contested) ? fm.contested : [];
|
|
49
|
+
fm.contested = [...existing, entry];
|
|
50
|
+
|
|
51
|
+
const rendered = YAML.stringify(fm).trimEnd();
|
|
52
|
+
return `---\n${rendered}\n---\n${body}`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function printUsage(): void {
|
|
56
|
+
process.stdout.write(
|
|
57
|
+
`usage: ${PROG} --page PATH --trigger TRIGGER --evidence TEXT --session ID --timestamp ISO8601\n`,
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function main(argv: string[]): number {
|
|
62
|
+
let page: string | null = null;
|
|
63
|
+
let trigger: string | null = null;
|
|
64
|
+
let evidence: string | null = null;
|
|
65
|
+
let session: string | null = null;
|
|
66
|
+
let timestamp: string | null = null;
|
|
67
|
+
|
|
68
|
+
for (let i = 0; i < argv.length; i++) {
|
|
69
|
+
const arg = argv[i];
|
|
70
|
+
if (arg === '-h' || arg === '--help') {
|
|
71
|
+
printUsage();
|
|
72
|
+
return 0;
|
|
73
|
+
} else if (arg === '--page') {
|
|
74
|
+
page = argv[++i] ?? null;
|
|
75
|
+
} else if (arg === '--trigger') {
|
|
76
|
+
trigger = argv[++i] ?? null;
|
|
77
|
+
} else if (arg === '--evidence') {
|
|
78
|
+
evidence = argv[++i] ?? null;
|
|
79
|
+
} else if (arg === '--session') {
|
|
80
|
+
session = argv[++i] ?? null;
|
|
81
|
+
} else if (arg === '--timestamp') {
|
|
82
|
+
timestamp = argv[++i] ?? null;
|
|
83
|
+
} else {
|
|
84
|
+
process.stderr.write(`${PROG}: error: unrecognized argument: ${arg}\n`);
|
|
85
|
+
printUsage();
|
|
86
|
+
return 1;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (!page || !trigger || !evidence || !session || !timestamp) {
|
|
91
|
+
process.stderr.write(`${PROG}: error: --page, --trigger, --evidence, --session, and --timestamp are all required\n`);
|
|
92
|
+
printUsage();
|
|
93
|
+
return 1;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let content: string;
|
|
97
|
+
try {
|
|
98
|
+
content = fs.readFileSync(page, 'utf8');
|
|
99
|
+
} catch {
|
|
100
|
+
process.stderr.write(`${PROG}: error: page not found: ${page}\n`);
|
|
101
|
+
return 1;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const updated = appendContestedEntry(content, { timestamp, trigger, evidence, session });
|
|
105
|
+
fs.writeFileSync(page, updated, 'utf8');
|
|
106
|
+
process.stdout.write(`${PROG}: appended contested entry to ${page}.\n`);
|
|
107
|
+
return 0;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (fileURLToPath(import.meta.url) === path.resolve(process.argv[1] ?? '')) {
|
|
111
|
+
process.exit(main(process.argv.slice(2)));
|
|
112
|
+
}
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
* - `agents/reports/auto-rules-audit.json` — deterministic, machine-readable.
|
|
22
22
|
* - `agents/reports/auto-rules-audit.md` — ranked summary for review.
|
|
23
23
|
*/
|
|
24
|
+
import { spawnSync } from 'node:child_process';
|
|
24
25
|
import * as fs from 'node:fs';
|
|
25
26
|
import * as path from 'node:path';
|
|
26
27
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
@@ -256,7 +257,16 @@ export function render_markdown(rules: RuleEntry[]): string {
|
|
|
256
257
|
const total_stub = rules.reduce((s, r) => s + r.stub_chars, 0);
|
|
257
258
|
const total_body = rules.reduce((s, r) => s + r.body_chars, 0);
|
|
258
259
|
const total_desc = rules.reduce((s, r) => s + r.description_chars, 0);
|
|
260
|
+
// Freshness marker — required by check_generated_artefact_headers (Phase 8.2)
|
|
261
|
+
const commitShort = (() => {
|
|
262
|
+
try {
|
|
263
|
+
const r = spawnSync('git', ['rev-parse', '--short', 'HEAD'], { encoding: 'utf-8' });
|
|
264
|
+
return r.stdout.trim() || 'unknown';
|
|
265
|
+
} catch { return 'unknown'; }
|
|
266
|
+
})();
|
|
267
|
+
const dateStr = new Date().toISOString().slice(0, 10);
|
|
259
268
|
const lines: string[] = [
|
|
269
|
+
`<!-- analyzed: ${dateStr} | commit: ${commitShort} | files: ${rules.length} -->`,
|
|
260
270
|
'# Auto-Rule Audit',
|
|
261
271
|
'',
|
|
262
272
|
'Generated by `scripts/audit_auto_rules.py` for Phase 5 of',
|
|
@@ -266,7 +276,7 @@ export function render_markdown(rules: RuleEntry[]): string {
|
|
|
266
276
|
'## Totals',
|
|
267
277
|
'',
|
|
268
278
|
`- auto-rules: **${rules.length}**`,
|
|
269
|
-
`- registry-stub cost (counts against
|
|
279
|
+
`- registry-stub cost (counts against the budgets.yml cap): **${_comma(total_stub)}** chars`,
|
|
270
280
|
`- description chars (subset of stub cost): **${_comma(total_desc)}** chars`,
|
|
271
281
|
`- body chars (informational, NOT in budget): **${_comma(total_body)}** chars`,
|
|
272
282
|
'',
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* Reads the source-of-truth catalog at
|
|
12
12
|
* `src/scripts/mcp_server/consumer_tool_catalog.json` and the handler
|
|
13
|
-
* registry at `src/scripts/mcp_server/tools.
|
|
13
|
+
* registry at `src/scripts/mcp_server/tools.ts`, emits
|
|
14
14
|
* `docs/contracts/mcp-tool-inventory.md` with every tool cited by
|
|
15
15
|
* `<file>:<line>`.
|
|
16
16
|
*
|
|
@@ -26,11 +26,12 @@ const _HERE = fileURLToPath(import.meta.url);
|
|
|
26
26
|
// src/scripts/audit_mcp_tools.ts → parent.parent.parent of the .py file = repo root.
|
|
27
27
|
export const ROOT = path.resolve(path.dirname(_HERE), '..', '..');
|
|
28
28
|
export const CATALOG = path.join(ROOT, 'src/scripts/mcp_server/consumer_tool_catalog.json');
|
|
29
|
-
export const
|
|
29
|
+
export const TOOLS_TS = path.join(ROOT, 'src/scripts/mcp_server/tools.ts');
|
|
30
30
|
export const OUT = path.join(ROOT, 'docs/contracts/mcp-tool-inventory.md');
|
|
31
31
|
|
|
32
|
-
// Match
|
|
33
|
-
|
|
32
|
+
// Match `<name>: {` entries at 4-space indent inside the TS ALLOWLIST record
|
|
33
|
+
// (deeper keys like `input_schema: {` sit at 8+ spaces and never match).
|
|
34
|
+
const HANDLER_RE = /^ {4}([a-z_]+): \{$/;
|
|
34
35
|
// Match `"name": "<name>",` in the catalog json (for catalog citations).
|
|
35
36
|
const CATALOG_NAME_RE = /^\s*"name"\s*:\s*"([a-z_]+)"\s*,?\s*$/;
|
|
36
37
|
|
|
@@ -70,11 +71,24 @@ function _relativeToRoot(p: string): string {
|
|
|
70
71
|
|
|
71
72
|
function _index_handlers(): Map<string, number> {
|
|
72
73
|
const out = new Map<string, number>();
|
|
73
|
-
const lines = _splitlines(fs.readFileSync(
|
|
74
|
-
//
|
|
74
|
+
const lines = _splitlines(fs.readFileSync(TOOLS_TS, 'utf-8'));
|
|
75
|
+
// Only index entries inside the `export const ALLOWLIST` block.
|
|
76
|
+
let inAllowlist = false;
|
|
75
77
|
for (let idx = 0; idx < lines.length; idx += 1) {
|
|
76
78
|
const i = idx + 1;
|
|
77
|
-
const
|
|
79
|
+
const line = lines[idx] as string;
|
|
80
|
+
if (line.startsWith('export const ALLOWLIST')) {
|
|
81
|
+
inAllowlist = true;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (inAllowlist && line.startsWith('};')) {
|
|
85
|
+
inAllowlist = false;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (!inAllowlist) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
const m = HANDLER_RE.exec(line);
|
|
78
92
|
if (m) {
|
|
79
93
|
out.set(m[1] as string, i);
|
|
80
94
|
}
|
|
@@ -129,9 +143,9 @@ function _render(catalog: Catalog, handlers: Map<string, number>, cat_lines: Map
|
|
|
129
143
|
lines.push('');
|
|
130
144
|
lines.push('# MCP tool inventory');
|
|
131
145
|
lines.push('');
|
|
132
|
-
lines.push('> Generated by [`scripts/audit_mcp_tools.
|
|
146
|
+
lines.push('> Generated by [`src/scripts/audit_mcp_tools.ts`](../../src/scripts/audit_mcp_tools.ts)');
|
|
133
147
|
lines.push('> from the source-of-truth catalog');
|
|
134
|
-
lines.push('> [`scripts/mcp_server/consumer_tool_catalog.json`](../../scripts/mcp_server/consumer_tool_catalog.json).');
|
|
148
|
+
lines.push('> [`src/scripts/mcp_server/consumer_tool_catalog.json`](../../src/scripts/mcp_server/consumer_tool_catalog.json).');
|
|
135
149
|
lines.push('> Do **not** hand-edit; rerun `./scripts-run src/scripts/audit_mcp_tools --write`.');
|
|
136
150
|
lines.push('>');
|
|
137
151
|
lines.push('> Step-11 Phase 5 Step 3 (an internal parity roadmap (local-only)).');
|
|
@@ -154,12 +168,12 @@ function _render(catalog: Catalog, handlers: Map<string, number>, cat_lines: Map
|
|
|
154
168
|
const cat_line = cat_lines.get(name);
|
|
155
169
|
const cat_cite =
|
|
156
170
|
cat_line !== undefined
|
|
157
|
-
? `[\`consumer_tool_catalog.json:${cat_line}\`](../../scripts/mcp_server/consumer_tool_catalog.json#L${cat_line})`
|
|
171
|
+
? `[\`consumer_tool_catalog.json:${cat_line}\`](../../src/scripts/mcp_server/consumer_tool_catalog.json#L${cat_line})`
|
|
158
172
|
: '_missing_';
|
|
159
173
|
const h_line = handlers.get(name);
|
|
160
174
|
const h_cite =
|
|
161
175
|
h_line !== undefined
|
|
162
|
-
? `[\`tools.
|
|
176
|
+
? `[\`tools.ts:${h_line}\`](../../src/scripts/mcp_server/tools.ts#L${h_line})`
|
|
163
177
|
: '_stub-only_';
|
|
164
178
|
lines.push(`| \`${name}\` | \`${side}\` | ${transports} | ${cat_cite} | ${h_cite} |`);
|
|
165
179
|
}
|