@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
|
@@ -1888,6 +1888,10 @@ function _run_no_manifest(
|
|
|
1888
1888
|
}
|
|
1889
1889
|
return fail_check ? 1 : 0;
|
|
1890
1890
|
}
|
|
1891
|
+
if (opts.ci && bridge_present) {
|
|
1892
|
+
// Same fold as the manifest path: check failures are red under --ci.
|
|
1893
|
+
return fail_check ? 1 : 0;
|
|
1894
|
+
}
|
|
1891
1895
|
return bridge_present ? 0 : 2;
|
|
1892
1896
|
}
|
|
1893
1897
|
|
|
@@ -1972,6 +1976,7 @@ function _emit_text(
|
|
|
1972
1976
|
interface Options {
|
|
1973
1977
|
project: string | null;
|
|
1974
1978
|
json: boolean;
|
|
1979
|
+
ci: boolean;
|
|
1975
1980
|
check: string | null;
|
|
1976
1981
|
trace_root: boolean;
|
|
1977
1982
|
context: boolean;
|
|
@@ -1984,11 +1989,12 @@ const PROG = 'agent-config doctor';
|
|
|
1984
1989
|
// per-flag `--help` BODY is a documented divergence — argparse re-wraps it to
|
|
1985
1990
|
// terminal width; golden tests assert the `usage:` token + exit code only.
|
|
1986
1991
|
const USAGE =
|
|
1987
|
-
`usage: ${PROG} [-h] [--project PROJECT] [--json] [--check ID]\n` +
|
|
1992
|
+
`usage: ${PROG} [-h] [--project PROJECT] [--json] [--ci] [--check ID]\n` +
|
|
1988
1993
|
' [--trace-root] [--context] [--repair ID]\n';
|
|
1989
1994
|
|
|
1990
1995
|
const _STORE_TRUE_FLAGS: Record<string, keyof Options> = {
|
|
1991
1996
|
'--json': 'json',
|
|
1997
|
+
'--ci': 'ci',
|
|
1992
1998
|
'--trace-root': 'trace_root',
|
|
1993
1999
|
'--context': 'context',
|
|
1994
2000
|
};
|
|
@@ -2009,6 +2015,7 @@ function _parse(argv: string[]): Options {
|
|
|
2009
2015
|
const opts: Record<string, unknown> = {
|
|
2010
2016
|
project: null,
|
|
2011
2017
|
json: false,
|
|
2018
|
+
ci: false,
|
|
2012
2019
|
check: null,
|
|
2013
2020
|
trace_root: false,
|
|
2014
2021
|
context: false,
|
|
@@ -2178,6 +2185,12 @@ function _run_repair(opts: Options): number {
|
|
|
2178
2185
|
|
|
2179
2186
|
function main(argv: string[] | null = null): number {
|
|
2180
2187
|
const opts = _parse(argv !== null ? Array.from(argv) : process.argv.slice(2));
|
|
2188
|
+
if (opts.ci) {
|
|
2189
|
+
// `--ci` = machine-readable consumer-CI contract: JSON payload on
|
|
2190
|
+
// stdout, zero interactive output, and check failures fold into the
|
|
2191
|
+
// exit code (the default full run keys the exit off drift only).
|
|
2192
|
+
opts.json = true;
|
|
2193
|
+
}
|
|
2181
2194
|
if (opts.repair !== null) {
|
|
2182
2195
|
return _run_repair(opts);
|
|
2183
2196
|
}
|
|
@@ -2232,7 +2245,15 @@ function main(argv: string[] | null = null): number {
|
|
|
2232
2245
|
if (opts.check !== null) {
|
|
2233
2246
|
return fail_check ? 1 : 0;
|
|
2234
2247
|
}
|
|
2235
|
-
|
|
2248
|
+
const drift_present = Boolean(
|
|
2249
|
+
missing.length || modified.length || foreign.length || tag_drift.length,
|
|
2250
|
+
);
|
|
2251
|
+
if (opts.ci) {
|
|
2252
|
+
// Exit contract under --ci: 0 clean · 1 any drift OR any check fail
|
|
2253
|
+
// · 2 unresolvable environment (handled above via ProjectRootError).
|
|
2254
|
+
return drift_present || fail_check ? 1 : 0;
|
|
2255
|
+
}
|
|
2256
|
+
return drift_present ? 1 : 0;
|
|
2236
2257
|
}
|
|
2237
2258
|
|
|
2238
2259
|
// --- CLI entry ---
|
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `agent-config init --fleet fleet.yaml` — multi-repo rollout
|
|
3
|
+
* (road-to-flow-learnings Phase 1).
|
|
4
|
+
*
|
|
5
|
+
* Config-driven fleet install on the existing substrate:
|
|
6
|
+
*
|
|
7
|
+
* - `fleet.yaml` lists repo paths (each optionally with a tool
|
|
8
|
+
* selection); one global `max_concurrency` (default 3) bounds the
|
|
9
|
+
* rollout — a concurrency bound only, no resource theater.
|
|
10
|
+
* - Per-repo isolation: every repo runs its own pre-flight →
|
|
11
|
+
* install → conformance pipeline in its own child process; one
|
|
12
|
+
* repo failing NEVER aborts the siblings.
|
|
13
|
+
* - Aggregate report: one JSON summary (per repo: status, findings,
|
|
14
|
+
* duration, conformance result) + a human table on stdout.
|
|
15
|
+
*
|
|
16
|
+
* ADR-020 / ADR-088 framing: this installs agent-config itself across
|
|
17
|
+
* repos. The default per-repo command is the global-only consumer
|
|
18
|
+
* bridge step (`agent-config refresh --project`); the fleet runner
|
|
19
|
+
* never bridges to or drives another tool's runtime.
|
|
20
|
+
*
|
|
21
|
+
* Exit contract: 0 = every repo ok · 1 = at least one repo failed ·
|
|
22
|
+
* 2 = config / environment error.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { spawn } from 'node:child_process';
|
|
26
|
+
import * as fs from 'node:fs';
|
|
27
|
+
import * as path from 'node:path';
|
|
28
|
+
import process from 'node:process';
|
|
29
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
30
|
+
|
|
31
|
+
import * as YAML from 'yaml';
|
|
32
|
+
|
|
33
|
+
import { runPreflight, hasBlockingFinding, type PreflightFinding } from '../../install/preflight.js';
|
|
34
|
+
import type { ConflictPolicy } from '../../install/types.js';
|
|
35
|
+
|
|
36
|
+
const _HERE = fileURLToPath(import.meta.url);
|
|
37
|
+
const PACKAGE_ROOT = path.resolve(path.dirname(_HERE), '..', '..', '..');
|
|
38
|
+
|
|
39
|
+
/** One fleet target, parsed from `fleet.yaml`. */
|
|
40
|
+
export interface FleetRepo {
|
|
41
|
+
readonly path: string;
|
|
42
|
+
/** Optional per-repo tool selection forwarded to the install command. */
|
|
43
|
+
readonly tools?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Parsed fleet config. */
|
|
47
|
+
export interface FleetSpec {
|
|
48
|
+
readonly repos: readonly FleetRepo[];
|
|
49
|
+
readonly maxConcurrency: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Terminal status of one repo's pipeline. */
|
|
53
|
+
export type FleetRepoStatus =
|
|
54
|
+
| 'ok'
|
|
55
|
+
| 'preflight-failed'
|
|
56
|
+
| 'install-failed'
|
|
57
|
+
| 'conformance-failed';
|
|
58
|
+
|
|
59
|
+
/** Per-repo result in the aggregate report. */
|
|
60
|
+
export interface FleetRepoResult {
|
|
61
|
+
readonly path: string;
|
|
62
|
+
readonly status: FleetRepoStatus;
|
|
63
|
+
readonly findings: readonly PreflightFinding[];
|
|
64
|
+
readonly durationMs: number;
|
|
65
|
+
/** Conformance summary — exit code + the JSONL-style note, when it ran. */
|
|
66
|
+
readonly conformance: { exit: number; note: string } | null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** The aggregate report — `schema_version` pins the JSON shape. */
|
|
70
|
+
export interface FleetReport {
|
|
71
|
+
readonly schema_version: 1;
|
|
72
|
+
readonly ts: string;
|
|
73
|
+
readonly max_concurrency: number;
|
|
74
|
+
readonly repos: readonly FleetRepoResult[];
|
|
75
|
+
readonly status: 'ok' | 'fail';
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export class FleetConfigError extends Error {}
|
|
79
|
+
|
|
80
|
+
/** Parse + validate `fleet.yaml`. Throws {@link FleetConfigError} on shape errors. */
|
|
81
|
+
export function parseFleetSpec(text: string, baseDir: string): FleetSpec {
|
|
82
|
+
let raw: unknown;
|
|
83
|
+
try {
|
|
84
|
+
raw = YAML.parse(text);
|
|
85
|
+
} catch (exc) {
|
|
86
|
+
throw new FleetConfigError(`fleet config does not parse: ${(exc as Error).message}`);
|
|
87
|
+
}
|
|
88
|
+
if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
89
|
+
throw new FleetConfigError('fleet config must be a mapping with a `repos:` list');
|
|
90
|
+
}
|
|
91
|
+
const obj = raw as Record<string, unknown>;
|
|
92
|
+
const reposRaw = obj['repos'];
|
|
93
|
+
if (!Array.isArray(reposRaw) || reposRaw.length === 0) {
|
|
94
|
+
throw new FleetConfigError('`repos:` must be a non-empty list');
|
|
95
|
+
}
|
|
96
|
+
const repos: FleetRepo[] = [];
|
|
97
|
+
for (const [i, entry] of reposRaw.entries()) {
|
|
98
|
+
if (typeof entry === 'string') {
|
|
99
|
+
repos.push({ path: path.resolve(baseDir, entry) });
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (entry !== null && typeof entry === 'object' && !Array.isArray(entry)) {
|
|
103
|
+
const e = entry as Record<string, unknown>;
|
|
104
|
+
const p = e['path'];
|
|
105
|
+
if (typeof p !== 'string' || p.length === 0) {
|
|
106
|
+
throw new FleetConfigError(`repos[${i}] is missing a non-empty \`path\``);
|
|
107
|
+
}
|
|
108
|
+
const tools = e['tools'];
|
|
109
|
+
if (tools !== undefined && typeof tools !== 'string') {
|
|
110
|
+
throw new FleetConfigError(`repos[${i}].tools must be a comma-separated string`);
|
|
111
|
+
}
|
|
112
|
+
repos.push({
|
|
113
|
+
path: path.resolve(baseDir, p),
|
|
114
|
+
...(typeof tools === 'string' ? { tools } : {}),
|
|
115
|
+
});
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
throw new FleetConfigError(`repos[${i}] must be a path string or a {path, tools} mapping`);
|
|
119
|
+
}
|
|
120
|
+
const mcRaw = obj['max_concurrency'];
|
|
121
|
+
let maxConcurrency = 3;
|
|
122
|
+
if (mcRaw !== undefined) {
|
|
123
|
+
if (typeof mcRaw !== 'number' || !Number.isInteger(mcRaw) || mcRaw < 1) {
|
|
124
|
+
throw new FleetConfigError('`max_concurrency` must be a positive integer');
|
|
125
|
+
}
|
|
126
|
+
maxConcurrency = mcRaw;
|
|
127
|
+
}
|
|
128
|
+
return { repos, maxConcurrency };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Validate a parsed aggregate report against the schema (used by tests + CI). */
|
|
132
|
+
export function validateFleetReport(obj: unknown): string[] {
|
|
133
|
+
const problems: string[] = [];
|
|
134
|
+
if (obj === null || typeof obj !== 'object') return ['report is not an object'];
|
|
135
|
+
const r = obj as Record<string, unknown>;
|
|
136
|
+
if (r['schema_version'] !== 1) problems.push('schema_version must be 1');
|
|
137
|
+
if (typeof r['ts'] !== 'string' || Number.isNaN(Date.parse(String(r['ts'])))) {
|
|
138
|
+
problems.push('ts must be an ISO timestamp');
|
|
139
|
+
}
|
|
140
|
+
if (typeof r['max_concurrency'] !== 'number') problems.push('max_concurrency must be a number');
|
|
141
|
+
if (r['status'] !== 'ok' && r['status'] !== 'fail') problems.push("status must be 'ok'|'fail'");
|
|
142
|
+
if (!Array.isArray(r['repos'])) {
|
|
143
|
+
problems.push('repos must be an array');
|
|
144
|
+
return problems;
|
|
145
|
+
}
|
|
146
|
+
const statuses = new Set(['ok', 'preflight-failed', 'install-failed', 'conformance-failed']);
|
|
147
|
+
for (const [i, item] of (r['repos'] as unknown[]).entries()) {
|
|
148
|
+
const e = item as Record<string, unknown>;
|
|
149
|
+
if (typeof e['path'] !== 'string') problems.push(`repos[${i}].path must be a string`);
|
|
150
|
+
if (!statuses.has(String(e['status']))) problems.push(`repos[${i}].status invalid`);
|
|
151
|
+
if (!Array.isArray(e['findings'])) problems.push(`repos[${i}].findings must be an array`);
|
|
152
|
+
if (typeof e['durationMs'] !== 'number') problems.push(`repos[${i}].durationMs must be a number`);
|
|
153
|
+
if (e['conformance'] !== null) {
|
|
154
|
+
const c = e['conformance'] as Record<string, unknown> | null;
|
|
155
|
+
if (c === null || typeof c !== 'object' || typeof c['exit'] !== 'number') {
|
|
156
|
+
problems.push(`repos[${i}].conformance must be null or {exit, note}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return problems;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Command factory — injectable so tests never spawn the real installer. */
|
|
164
|
+
export interface FleetCommands {
|
|
165
|
+
/** argv for the per-repo install step (cwd = repo path). */
|
|
166
|
+
installArgv(repo: FleetRepo): string[];
|
|
167
|
+
/** argv for the per-repo conformance step (cwd = repo path). */
|
|
168
|
+
conformanceArgv(repo: FleetRepo): string[];
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** Default commands — the ADR-020 global-only consumer pipeline. */
|
|
172
|
+
export function defaultFleetCommands(packageRoot: string = PACKAGE_ROOT): FleetCommands {
|
|
173
|
+
const entry = path.join(packageRoot, 'src', 'scripts', 'agent-config');
|
|
174
|
+
return {
|
|
175
|
+
installArgv: () => ['bash', entry, 'refresh', '--project'],
|
|
176
|
+
conformanceArgv: () => ['bash', entry, 'conformance'],
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function spawnInRepo(
|
|
181
|
+
argv: readonly string[],
|
|
182
|
+
cwd: string,
|
|
183
|
+
timeoutMs: number,
|
|
184
|
+
): Promise<{ exit: number; stdout: string; stderr: string }> {
|
|
185
|
+
return new Promise((resolvePromise) => {
|
|
186
|
+
const child = spawn(argv[0] as string, argv.slice(1), {
|
|
187
|
+
cwd,
|
|
188
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
189
|
+
timeout: timeoutMs,
|
|
190
|
+
});
|
|
191
|
+
let stdout = '';
|
|
192
|
+
let stderr = '';
|
|
193
|
+
child.stdout.on('data', (d: Buffer) => {
|
|
194
|
+
stdout += d.toString('utf8');
|
|
195
|
+
});
|
|
196
|
+
child.stderr.on('data', (d: Buffer) => {
|
|
197
|
+
stderr += d.toString('utf8');
|
|
198
|
+
});
|
|
199
|
+
child.on('error', (err) => {
|
|
200
|
+
resolvePromise({ exit: 127, stdout, stderr: `${stderr}${err.message}` });
|
|
201
|
+
});
|
|
202
|
+
child.on('close', (code) => {
|
|
203
|
+
resolvePromise({ exit: code ?? 1, stdout, stderr });
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const PREFLIGHT_POLICY: ConflictPolicy = {
|
|
209
|
+
force: false,
|
|
210
|
+
interactive: false,
|
|
211
|
+
knownPaths: new Set<string>(),
|
|
212
|
+
knownPointers: new Set<string>(),
|
|
213
|
+
defaultStrategy: 'skip',
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
async function runOneRepo(
|
|
217
|
+
repo: FleetRepo,
|
|
218
|
+
commands: FleetCommands,
|
|
219
|
+
timeoutMs: number,
|
|
220
|
+
): Promise<FleetRepoResult> {
|
|
221
|
+
const started = Date.now();
|
|
222
|
+
// Stage 1 — pre-flight (typed findings; blocking finding stops THIS repo only).
|
|
223
|
+
let findings: PreflightFinding[];
|
|
224
|
+
if (!fs.existsSync(repo.path) || !fs.statSync(repo.path).isDirectory()) {
|
|
225
|
+
findings = [
|
|
226
|
+
{
|
|
227
|
+
id: 'permissions',
|
|
228
|
+
severity: 'blocking',
|
|
229
|
+
path: repo.path,
|
|
230
|
+
message: 'repo path does not exist or is not a directory',
|
|
231
|
+
remedy: 'fix the path in fleet.yaml (or clone the repo first)',
|
|
232
|
+
},
|
|
233
|
+
];
|
|
234
|
+
} else {
|
|
235
|
+
findings = runPreflight({
|
|
236
|
+
target: 'project',
|
|
237
|
+
root: repo.path,
|
|
238
|
+
sources: [],
|
|
239
|
+
policy: PREFLIGHT_POLICY,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
if (hasBlockingFinding(findings)) {
|
|
243
|
+
return {
|
|
244
|
+
path: repo.path,
|
|
245
|
+
status: 'preflight-failed',
|
|
246
|
+
findings,
|
|
247
|
+
durationMs: Date.now() - started,
|
|
248
|
+
conformance: null,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
// Stage 2 — install (own child process; failure isolated to this repo).
|
|
252
|
+
const install = await spawnInRepo(commands.installArgv(repo), repo.path, timeoutMs);
|
|
253
|
+
if (install.exit !== 0) {
|
|
254
|
+
return {
|
|
255
|
+
path: repo.path,
|
|
256
|
+
status: 'install-failed',
|
|
257
|
+
findings,
|
|
258
|
+
durationMs: Date.now() - started,
|
|
259
|
+
conformance: null,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
// Stage 3 — conformance (Phase-0 contract; its note feeds the aggregate).
|
|
263
|
+
const conf = await spawnInRepo(commands.conformanceArgv(repo), repo.path, timeoutMs);
|
|
264
|
+
const lastLine = conf.stdout.trim().split('\n').filter(Boolean).slice(-1)[0] ?? '';
|
|
265
|
+
return {
|
|
266
|
+
path: repo.path,
|
|
267
|
+
status: conf.exit === 0 ? 'ok' : 'conformance-failed',
|
|
268
|
+
findings,
|
|
269
|
+
durationMs: Date.now() - started,
|
|
270
|
+
conformance: { exit: conf.exit, note: lastLine.slice(0, 200) },
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** Bounded-concurrency pool — the only "resource management" a rollout needs. */
|
|
275
|
+
async function pool<T, R>(
|
|
276
|
+
items: readonly T[],
|
|
277
|
+
limit: number,
|
|
278
|
+
fn: (item: T) => Promise<R>,
|
|
279
|
+
): Promise<R[]> {
|
|
280
|
+
const results: R[] = new Array(items.length);
|
|
281
|
+
let next = 0;
|
|
282
|
+
async function worker(): Promise<void> {
|
|
283
|
+
while (next < items.length) {
|
|
284
|
+
const i = next;
|
|
285
|
+
next += 1;
|
|
286
|
+
results[i] = await fn(items[i] as T);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
const workers = Array.from({ length: Math.min(limit, items.length) }, () => worker());
|
|
290
|
+
await Promise.all(workers);
|
|
291
|
+
return results;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export interface RunFleetOptions {
|
|
295
|
+
readonly commands?: FleetCommands;
|
|
296
|
+
readonly timeoutMs?: number;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/** Run the whole fleet. Never throws for per-repo problems. */
|
|
300
|
+
export async function runFleet(spec: FleetSpec, opts: RunFleetOptions = {}): Promise<FleetReport> {
|
|
301
|
+
const commands = opts.commands ?? defaultFleetCommands();
|
|
302
|
+
const timeoutMs = opts.timeoutMs ?? 10 * 60 * 1000;
|
|
303
|
+
const results = await pool(spec.repos, spec.maxConcurrency, (repo) =>
|
|
304
|
+
runOneRepo(repo, commands, timeoutMs),
|
|
305
|
+
);
|
|
306
|
+
return {
|
|
307
|
+
schema_version: 1,
|
|
308
|
+
ts: new Date().toISOString(),
|
|
309
|
+
max_concurrency: spec.maxConcurrency,
|
|
310
|
+
repos: results,
|
|
311
|
+
status: results.every((r) => r.status === 'ok') ? 'ok' : 'fail',
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function humanTable(report: FleetReport): string {
|
|
316
|
+
const lines: string[] = [];
|
|
317
|
+
lines.push(`fleet: ${report.repos.length} repo(s) · max_concurrency ${report.max_concurrency}`);
|
|
318
|
+
for (const r of report.repos) {
|
|
319
|
+
const sym = r.status === 'ok' ? '✅' : '❌';
|
|
320
|
+
const dur = `${Math.round(r.durationMs / 100) / 10}s`;
|
|
321
|
+
lines.push(` ${sym} ${r.path} — ${r.status} (${dur})`);
|
|
322
|
+
for (const f of r.findings.filter((x) => x.severity === 'blocking')) {
|
|
323
|
+
lines.push(` ${f.id}: ${f.message}`);
|
|
324
|
+
}
|
|
325
|
+
if (r.conformance && r.status === 'conformance-failed') {
|
|
326
|
+
lines.push(` conformance exit ${r.conformance.exit}: ${r.conformance.note}`);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
lines.push(report.status === 'ok' ? '✅ fleet: all green' : '❌ fleet: at least one repo failed');
|
|
330
|
+
return lines.join('\n');
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const USAGE = 'usage: cmd_fleet [-h] --config fleet.yaml [--json]\n';
|
|
334
|
+
|
|
335
|
+
export async function main(argv: string[] | null = null): Promise<number> {
|
|
336
|
+
const args = argv !== null ? Array.from(argv) : process.argv.slice(2);
|
|
337
|
+
let configPath: string | null = null;
|
|
338
|
+
let json = false;
|
|
339
|
+
let i = 0;
|
|
340
|
+
while (i < args.length) {
|
|
341
|
+
const a = args[i] as string;
|
|
342
|
+
if (a === '-h' || a === '--help') {
|
|
343
|
+
process.stdout.write(USAGE);
|
|
344
|
+
return 0;
|
|
345
|
+
}
|
|
346
|
+
if (a === '--json') {
|
|
347
|
+
json = true;
|
|
348
|
+
} else if (a === '--config' || a.startsWith('--config=')) {
|
|
349
|
+
if (a.includes('=')) {
|
|
350
|
+
configPath = a.slice(a.indexOf('=') + 1);
|
|
351
|
+
} else {
|
|
352
|
+
configPath = String(args[i + 1] ?? '');
|
|
353
|
+
i += 1;
|
|
354
|
+
}
|
|
355
|
+
} else {
|
|
356
|
+
process.stderr.write(USAGE);
|
|
357
|
+
process.stderr.write(`cmd_fleet: error: unrecognized argument ${a}\n`);
|
|
358
|
+
return 2;
|
|
359
|
+
}
|
|
360
|
+
i += 1;
|
|
361
|
+
}
|
|
362
|
+
if (!configPath || !fs.existsSync(configPath)) {
|
|
363
|
+
process.stderr.write(USAGE);
|
|
364
|
+
process.stderr.write(`cmd_fleet: error: --config path missing or not found\n`);
|
|
365
|
+
return 2;
|
|
366
|
+
}
|
|
367
|
+
let spec: FleetSpec;
|
|
368
|
+
try {
|
|
369
|
+
spec = parseFleetSpec(fs.readFileSync(configPath, 'utf8'), path.dirname(path.resolve(configPath)));
|
|
370
|
+
} catch (exc) {
|
|
371
|
+
if (exc instanceof FleetConfigError) {
|
|
372
|
+
process.stderr.write(`cmd_fleet: error: ${exc.message}\n`);
|
|
373
|
+
return 2;
|
|
374
|
+
}
|
|
375
|
+
throw exc;
|
|
376
|
+
}
|
|
377
|
+
const report = await runFleet(spec);
|
|
378
|
+
if (json) {
|
|
379
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
380
|
+
} else {
|
|
381
|
+
process.stdout.write(`${humanTable(report)}\n`);
|
|
382
|
+
}
|
|
383
|
+
return report.status === 'ok' ? 0 : 1;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// --- CLI entry ---
|
|
387
|
+
|
|
388
|
+
const _isCliEntry =
|
|
389
|
+
process.argv[1] !== undefined &&
|
|
390
|
+
import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href;
|
|
391
|
+
if (_isCliEntry || process.argv[1] === _HERE) {
|
|
392
|
+
main(process.argv.slice(2)).then(
|
|
393
|
+
(code) => {
|
|
394
|
+
process.exitCode = code;
|
|
395
|
+
},
|
|
396
|
+
(err) => {
|
|
397
|
+
process.stderr.write(`cmd_fleet: fatal: ${(err as Error).message}\n`);
|
|
398
|
+
process.exitCode = 2;
|
|
399
|
+
},
|
|
400
|
+
);
|
|
401
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `agent-config init --validate-only` back-end — pre-flight-only run
|
|
3
|
+
* (road-to-flow-learnings Phase 0).
|
|
4
|
+
*
|
|
5
|
+
* Builds the same global-scope source expansion the installer uses
|
|
6
|
+
* (`expandWizardSources`), runs the typed pre-flight suite from
|
|
7
|
+
* `src/install/preflight.ts`, prints every finding, and exits:
|
|
8
|
+
*
|
|
9
|
+
* 0 — no blocking finding (warnings/info allowed)
|
|
10
|
+
* 1 — at least one blocking finding
|
|
11
|
+
* 2 — argument / environment error
|
|
12
|
+
*
|
|
13
|
+
* Nothing is written. This is the "can this environment take the
|
|
14
|
+
* install?" gate — the conformance command answers the post-install
|
|
15
|
+
* twin ("is it installed and firing?").
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import * as os from 'node:os';
|
|
19
|
+
import * as path from 'node:path';
|
|
20
|
+
import process from 'node:process';
|
|
21
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
22
|
+
|
|
23
|
+
import {
|
|
24
|
+
hasBlockingFinding,
|
|
25
|
+
runPreflight,
|
|
26
|
+
type PreflightFinding,
|
|
27
|
+
} from '../../install/preflight.js';
|
|
28
|
+
import { GLOBAL_DEPLOY_SOURCES, expandWizardSources } from '../../install/wizard-plan.js';
|
|
29
|
+
import type { ConflictPolicy } from '../../install/types.js';
|
|
30
|
+
|
|
31
|
+
const _HERE = fileURLToPath(import.meta.url);
|
|
32
|
+
|
|
33
|
+
/** Package root — three levels above `src/scripts/_cli/`. */
|
|
34
|
+
const PACKAGE_ROOT = path.resolve(path.dirname(_HERE), '..', '..', '..');
|
|
35
|
+
|
|
36
|
+
const USAGE =
|
|
37
|
+
'usage: cmd_preflight [-h] [--tools a,b,...] [--target DIR] [--json]\n';
|
|
38
|
+
|
|
39
|
+
const SEVERITY_SYMBOL: Record<PreflightFinding['severity'], string> = {
|
|
40
|
+
blocking: '❌',
|
|
41
|
+
warning: '⚠️ ',
|
|
42
|
+
info: 'ℹ️ ',
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
class ArgError extends Error {}
|
|
46
|
+
|
|
47
|
+
interface Options {
|
|
48
|
+
tools: string[];
|
|
49
|
+
target: string;
|
|
50
|
+
json: boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function parse(argv: string[]): Options {
|
|
54
|
+
const opts: Options = {
|
|
55
|
+
tools: Object.keys(GLOBAL_DEPLOY_SOURCES),
|
|
56
|
+
target: os.homedir(),
|
|
57
|
+
json: false,
|
|
58
|
+
};
|
|
59
|
+
let i = 0;
|
|
60
|
+
while (i < argv.length) {
|
|
61
|
+
const a = argv[i] as string;
|
|
62
|
+
if (a === '-h' || a === '--help') {
|
|
63
|
+
process.stdout.write(USAGE);
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
if (a === '--json') {
|
|
67
|
+
opts.json = true;
|
|
68
|
+
} else if (a === '--tools' || a.startsWith('--tools=')) {
|
|
69
|
+
let raw: string;
|
|
70
|
+
if (a.includes('=')) {
|
|
71
|
+
raw = a.slice(a.indexOf('=') + 1);
|
|
72
|
+
} else {
|
|
73
|
+
raw = String(argv[i + 1] ?? '');
|
|
74
|
+
i += 1;
|
|
75
|
+
}
|
|
76
|
+
const list = raw
|
|
77
|
+
.split(',')
|
|
78
|
+
.map((t) => t.trim())
|
|
79
|
+
.filter((t) => t.length > 0 && t !== 'all');
|
|
80
|
+
if (list.length > 0) {
|
|
81
|
+
opts.tools = list;
|
|
82
|
+
}
|
|
83
|
+
} else if (a === '--target' || a.startsWith('--target=')) {
|
|
84
|
+
if (a.includes('=')) {
|
|
85
|
+
opts.target = a.slice(a.indexOf('=') + 1);
|
|
86
|
+
} else {
|
|
87
|
+
opts.target = String(argv[i + 1] ?? '');
|
|
88
|
+
i += 1;
|
|
89
|
+
}
|
|
90
|
+
if (!opts.target) {
|
|
91
|
+
throw new ArgError('--target expects a value');
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
throw new ArgError(`unrecognized argument ${a}`);
|
|
95
|
+
}
|
|
96
|
+
i += 1;
|
|
97
|
+
}
|
|
98
|
+
return opts;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function main(argv: string[] | null = null): number {
|
|
102
|
+
let opts: Options;
|
|
103
|
+
try {
|
|
104
|
+
opts = parse(argv !== null ? Array.from(argv) : process.argv.slice(2));
|
|
105
|
+
} catch (exc) {
|
|
106
|
+
if (exc instanceof ArgError) {
|
|
107
|
+
process.stderr.write(USAGE);
|
|
108
|
+
process.stderr.write(`cmd_preflight: error: ${exc.message}\n`);
|
|
109
|
+
return 2;
|
|
110
|
+
}
|
|
111
|
+
throw exc;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const policy: ConflictPolicy = {
|
|
115
|
+
force: false,
|
|
116
|
+
interactive: false,
|
|
117
|
+
knownPaths: new Set<string>(),
|
|
118
|
+
knownPointers: new Set<string>(),
|
|
119
|
+
defaultStrategy: 'skip',
|
|
120
|
+
};
|
|
121
|
+
const sources = expandWizardSources({
|
|
122
|
+
toolIds: opts.tools,
|
|
123
|
+
packageRoot: PACKAGE_ROOT,
|
|
124
|
+
});
|
|
125
|
+
const findings = runPreflight({
|
|
126
|
+
target: 'global',
|
|
127
|
+
root: opts.target,
|
|
128
|
+
sources,
|
|
129
|
+
policy,
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
if (opts.json) {
|
|
133
|
+
process.stdout.write(
|
|
134
|
+
`${JSON.stringify({ target: opts.target, tools: opts.tools, findings }, null, 2)}\n`,
|
|
135
|
+
);
|
|
136
|
+
} else {
|
|
137
|
+
process.stdout.write(` 🔎 pre-flight: ${opts.tools.length} tool(s) against ${opts.target}\n`);
|
|
138
|
+
if (findings.length === 0) {
|
|
139
|
+
process.stdout.write(' ✅ no findings\n');
|
|
140
|
+
}
|
|
141
|
+
for (const f of findings) {
|
|
142
|
+
const sym = SEVERITY_SYMBOL[f.severity];
|
|
143
|
+
process.stdout.write(` ${sym} ${f.id}: ${f.message}\n`);
|
|
144
|
+
if (f.severity !== 'info' && f.remedy) {
|
|
145
|
+
process.stdout.write(` fix: ${f.remedy}\n`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return hasBlockingFinding(findings) ? 1 : 0;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// --- CLI entry ---
|
|
153
|
+
|
|
154
|
+
const _isCliEntry =
|
|
155
|
+
process.argv[1] !== undefined &&
|
|
156
|
+
import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href;
|
|
157
|
+
if (_isCliEntry || process.argv[1] === _HERE) {
|
|
158
|
+
process.exitCode = main(process.argv.slice(2));
|
|
159
|
+
}
|
|
@@ -918,6 +918,15 @@ cmd_doctor() {
|
|
|
918
918
|
exec_ts "$PACKAGE_ROOT/src/scripts/_cli/cmd_doctor.ts" "$@"
|
|
919
919
|
}
|
|
920
920
|
|
|
921
|
+
# `agent-config conformance` — consumer conformance contract
|
|
922
|
+
# (road-to-flow-learnings Phase 0). Doctor --ci semantics plus the five
|
|
923
|
+
# consumer checks (txlog tail, router pointers, dispatcher smoke,
|
|
924
|
+
# lean-projection consistency, host-capability manifest). Exit 0 green,
|
|
925
|
+
# 1 any fail/drift, 2 environment error. See docs/contracts/conformance.md.
|
|
926
|
+
cmd_conformance() {
|
|
927
|
+
exec_ts "$PACKAGE_ROOT/src/scripts/_cli/cmd_conformance.ts" "$@"
|
|
928
|
+
}
|
|
929
|
+
|
|
921
930
|
# `agent-config versions` — list available @event4u/agent-config versions
|
|
922
931
|
# on the npm registry. Marks the current pin (from .agent-settings.yml)
|
|
923
932
|
# and the latest published version. Offline-tolerant. See
|
|
@@ -996,6 +1005,7 @@ main() {
|
|
|
996
1005
|
uninstall) cmd_uninstall "$@" ;;
|
|
997
1006
|
prune) cmd_prune "$@" ;;
|
|
998
1007
|
doctor) cmd_doctor "$@" ;;
|
|
1008
|
+
conformance) cmd_conformance "$@" ;;
|
|
999
1009
|
versions) cmd_versions "$@" ;;
|
|
1000
1010
|
explain) cmd_explain "$@" ;;
|
|
1001
1011
|
analyze-session) cmd_analyze_session "$@" ;;
|