@event4u/agent-config 8.4.0 → 8.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +73 -0
- package/README.md +17 -5
- package/dist/agent-src/README.md +1 -1
- package/dist/agent-src/commands/{analyze-reference-repo.md → analyze/reference-repo.md} +3 -1
- package/dist/agent-src/commands/analyze.md +9 -6
- package/dist/agent-src/commands/{bug-fix.md → bug/fix.md} +3 -1
- package/dist/agent-src/commands/{bug-investigate.md → bug/investigate.md} +4 -2
- package/dist/agent-src/commands/bug.md +59 -0
- package/dist/agent-src/commands/{set-cost-profile.md → cost/profile.md} +9 -6
- package/dist/agent-src/commands/{cost-report.md → cost/report.md} +18 -17
- package/dist/agent-src/commands/cost.md +57 -0
- package/dist/agent-src/commands/evals/{review-changes.json → review.json} +12 -8
- package/dist/agent-src/commands/{quality-fix.md → fix/quality.md} +5 -2
- package/dist/agent-src/commands/fix.md +7 -4
- package/dist/agent-src/commands/optimize/project.md +250 -0
- package/dist/agent-src/commands/{optimize-prompt.md → optimize/prompt.md} +3 -2
- package/dist/agent-src/commands/optimize.md +17 -12
- package/dist/agent-src/commands/{package-reset.md → package/reset.md} +2 -0
- package/dist/agent-src/commands/{package-test.md → package/test.md} +3 -1
- package/dist/agent-src/commands/package.md +56 -0
- package/dist/agent-src/commands/{project-analyze.md → project/analyze.md} +10 -8
- package/dist/agent-src/commands/{project-health.md → project/health.md} +2 -0
- package/dist/agent-src/commands/project.md +60 -0
- package/dist/agent-src/commands/{review-changes.md → review/changes.md} +26 -24
- package/dist/agent-src/commands/{review-routing.md → review/routing.md} +21 -17
- package/dist/agent-src/commands/review.md +61 -0
- package/dist/agent-src/commands/security-audit-config.md +24 -23
- package/dist/agent-src/commands/{sync-agent-settings.md → sync/agent-settings.md} +11 -7
- package/dist/agent-src/commands/{sync-gitignore → sync/gitignore}/fix.md +36 -27
- package/dist/agent-src/commands/{sync-gitignore.md → sync/gitignore.md} +22 -21
- package/dist/agent-src/commands/sync.md +58 -0
- package/dist/agent-src/commands/{e2e-heal.md → tests/e2e-heal.md} +5 -2
- package/dist/agent-src/commands/{e2e-plan.md → tests/e2e-plan.md} +5 -2
- package/dist/agent-src/commands/tests.md +11 -5
- package/dist/agent-src/contexts/augment-infrastructure.md +3 -3
- package/dist/agent-src/contexts/execution/toolchain-resolver.md +1 -1
- package/dist/agent-src/contexts/skills-and-commands.md +2 -2
- package/dist/agent-src/rules/external-reference-deep-dive.md +1 -1
- package/dist/agent-src/skills/finishing-a-development-branch/SKILL.md +2 -2
- package/dist/agent-src/skills/judge-artifact-completeness/SKILL.md +1 -1
- package/dist/agent-src/skills/judge-bug-hunter/SKILL.md +1 -1
- package/dist/agent-src/skills/judge-code-quality/SKILL.md +1 -1
- package/dist/agent-src/skills/judge-security-auditor/SKILL.md +1 -1
- package/dist/agent-src/skills/judge-synthesis/SKILL.md +1 -1
- package/dist/agent-src/skills/judge-test-coverage/SKILL.md +1 -1
- package/dist/agent-src/skills/markitdown/SKILL.md +1 -1
- package/dist/agent-src/skills/mobile-e2e-strategy/SKILL.md +5 -5
- package/dist/agent-src/skills/prompt-optimizer/SKILL.md +2 -2
- package/dist/agent-src/skills/quality-tools/SKILL.md +1 -1
- package/dist/agent-src/skills/repomix-packer/SKILL.md +1 -1
- package/dist/agent-src/skills/requesting-code-review/SKILL.md +2 -2
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +2 -2
- package/dist/agent-src/templates/agent-settings.md +1 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +2 -2
- package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +1 -1
- package/dist/cli/commands/config.js +44 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/uiServe.js +1 -0
- package/dist/cli/commands/uiServe.js.map +1 -1
- package/dist/cli/help.js +38 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/initRouting.js +16 -1
- package/dist/cli/initRouting.js.map +1 -1
- package/dist/cli/main.js +43 -37
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/registry.js +45 -44
- package/dist/cli/registry.js.map +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +419 -210
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +4 -4
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +31 -25
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +30 -24
- package/dist/install/install.mjs +6064 -159
- package/dist/install/selectedTools.js +39 -10
- package/dist/install/selectedTools.js.map +1 -1
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/server/app.js +15 -3
- package/dist/server/app.js.map +1 -1
- package/dist/server/routes/ping.js +16 -0
- package/dist/server/routes/ping.js.map +1 -1
- package/dist/server/routes/settings.js +42 -6
- package/dist/server/routes/settings.js.map +1 -1
- package/dist/server/routes/settingsChanges.js +55 -0
- package/dist/server/routes/settingsChanges.js.map +1 -0
- package/dist/server/routes/userMd.js +7 -2
- package/dist/server/routes/userMd.js.map +1 -1
- package/dist/server/routes/wizard.js +76 -14
- package/dist/server/routes/wizard.js.map +1 -1
- package/dist/server/writeRoot.js +17 -0
- package/dist/server/writeRoot.js.map +1 -1
- package/dist/shared/settingsSurface.js +120 -0
- package/dist/shared/settingsSurface.js.map +1 -0
- package/dist/ui/assets/index-BPFMZWUs.css +1 -0
- package/dist/ui/assets/index-BiEZiZ31.js +40 -0
- package/dist/ui/assets/index-BiEZiZ31.js.map +1 -0
- package/dist/ui/index.html +15 -2
- package/docs/CLAIMS.md +20 -15
- package/docs/architecture.md +1 -1
- package/docs/catalog.md +37 -31
- package/docs/command-flows.md +22 -16
- package/docs/contracts/command-clusters.md +39 -9
- package/docs/contracts/file-ownership-matrix.json +21 -0
- package/docs/contracts/frontmatter-contract.md +1 -1
- package/docs/contracts/gui-wizard.md +16 -4
- package/docs/contracts/iron-law-overrides.txt +1 -0
- package/docs/contracts/rule-classification.md +2 -2
- package/docs/contracts/settings-api.md +58 -2
- package/docs/contracts/surface-matrix.md +5 -0
- package/docs/cookbook.md +7 -7
- package/docs/decisions/ADR-114-commit-policy-iron-law-override.md +74 -0
- package/docs/decisions/ADR-115-command-cluster-consolidation-phase-4.md +91 -0
- package/docs/decisions/INDEX.md +2 -0
- package/docs/featured-commands.md +1 -1
- package/docs/featured-skills.md +4 -4
- package/docs/flows.md +2 -2
- package/docs/getting-started-by-role.md +1 -1
- package/docs/getting-started-laravel.md +1 -1
- package/docs/getting-started.md +6 -3
- package/docs/governance-advantage.md +1 -1
- package/docs/guidelines/agent-infra/5w2h-analysis.md +1 -1
- package/docs/guidelines/agent-infra/ios-simulator-guide.md +1 -1
- package/docs/proof.md +11 -2
- package/package.json +6 -1
- package/src/agent-src/README.md +64 -0
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +497 -0
- package/src/agent-src/scripts/scan-seeder-violations.php +145 -0
- package/src/agent-src/scripts/update_roadmap_progress.ts +1087 -0
- package/src/agent-src/templates/AGENTS.md +34 -0
- package/src/agent-src/templates/scripts/README.md +195 -0
- package/src/agent-src/templates/scripts/check_memory.ts +662 -0
- package/src/agent-src/templates/scripts/check_memory_proposal.ts +370 -0
- package/src/agent-src/templates/scripts/historical-bug-patterns.example.yml +84 -0
- package/src/agent-src/templates/scripts/implement_ticket/__main__.ts +27 -0
- package/src/agent-src/templates/scripts/memory_hash.ts +355 -0
- package/src/agent-src/templates/scripts/memory_lookup.ts +1089 -0
- package/src/agent-src/templates/scripts/memory_report.ts +868 -0
- package/src/agent-src/templates/scripts/memory_signal.ts +444 -0
- package/src/agent-src/templates/scripts/memory_status.ts +215 -0
- package/src/agent-src/templates/scripts/ownership-map.example.yml +87 -0
- package/src/agent-src/templates/scripts/pr-risk-config.example.yml +76 -0
- package/src/agent-src/templates/scripts/pr_review_routing.ts +544 -0
- package/src/agent-src/templates/scripts/pr_risk_review.ts +0 -0
- package/src/agent-src/templates/scripts/telemetry/aggregator.ts +0 -0
- package/src/agent-src/templates/scripts/telemetry/boundary.ts +164 -0
- package/src/agent-src/templates/scripts/telemetry/engagement.ts +479 -0
- package/src/agent-src/templates/scripts/telemetry/report_renderer.ts +394 -0
- package/src/agent-src/templates/scripts/telemetry/settings.ts +210 -0
- package/src/agent-src/templates/scripts/telemetry_record.ts +276 -0
- package/src/agent-src/templates/scripts/telemetry_report.ts +211 -0
- package/src/agent-src/templates/scripts/telemetry_status.ts +333 -0
- package/src/agent-src/templates/scripts/tier_usage_report.ts +619 -0
- package/src/agent-src/templates/scripts/work_engine/__main__.ts +14 -0
- package/src/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +1261 -0
- package/src/agent-src/templates/scripts/work_engine/_lib/user_global_paths.ts +329 -0
- package/src/agent-src/templates/scripts/work_engine/cli.ts +206 -0
- package/src/agent-src/templates/scripts/work_engine/cli_args.ts +249 -0
- package/src/agent-src/templates/scripts/work_engine/delivery_state.ts +225 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/analyze.ts +125 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +189 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/index.ts +94 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/memory.ts +193 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/plan.ts +267 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/refine.ts +518 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/report.ts +379 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +268 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +258 -0
- package/src/agent-src/templates/scripts/work_engine/directives/index.ts +32 -0
- package/src/agent-src/templates/scripts/work_engine/directives/mixed/contract.ts +243 -0
- package/src/agent-src/templates/scripts/work_engine/directives/mixed/index.ts +108 -0
- package/src/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +259 -0
- package/src/agent-src/templates/scripts/work_engine/directives/mixed/ui.ts +216 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/_passthrough.ts +40 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +241 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +216 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +506 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/design.ts +325 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/index.ts +102 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +462 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/review.ts +474 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +352 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui_trivial/_skipped.ts +33 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui_trivial/apply.ts +213 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui_trivial/index.ts +111 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui_trivial/refine.ts +126 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui_trivial/report.ts +112 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui_trivial/test.ts +164 -0
- package/src/agent-src/templates/scripts/work_engine/dispatcher.ts +515 -0
- package/src/agent-src/templates/scripts/work_engine/emitters.ts +119 -0
- package/src/agent-src/templates/scripts/work_engine/errors.ts +24 -0
- package/src/agent-src/templates/scripts/work_engine/hook_bootstrap.ts +104 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/_chat_history_base.ts +189 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_append.ts +41 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_halt_append.ts +89 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/decision_gate.ts +193 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +304 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/directive_set_guard.ts +110 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/halt_surface_audit.ts +118 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/index.ts +17 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +161 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/state_shape_validation.ts +45 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/trace.ts +134 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/context.ts +94 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/events.ts +58 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/exceptions.ts +85 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/index.ts +27 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/registry.ts +66 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/runner.ts +90 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/settings.ts +260 -0
- package/src/agent-src/templates/scripts/work_engine/input_builders.ts +260 -0
- package/src/agent-src/templates/scripts/work_engine/intent/classify.ts +466 -0
- package/src/agent-src/templates/scripts/work_engine/migration/v0_to_v1.ts +531 -0
- package/src/agent-src/templates/scripts/work_engine/orchestration.ts +366 -0
- package/src/agent-src/templates/scripts/work_engine/persona_policy.ts +97 -0
- package/src/agent-src/templates/scripts/work_engine/resolvers/diff.ts +135 -0
- package/src/agent-src/templates/scripts/work_engine/resolvers/file.ts +175 -0
- package/src/agent-src/templates/scripts/work_engine/resolvers/prompt.ts +115 -0
- package/src/agent-src/templates/scripts/work_engine/scoring/confidence.ts +415 -0
- package/src/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +466 -0
- package/src/agent-src/templates/scripts/work_engine/scoring/decision_trace.ts +298 -0
- package/src/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +444 -0
- package/src/agent-src/templates/scripts/work_engine/stack/detect.ts +252 -0
- package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +745 -0
- package/src/agent-src/templates/scripts/work_engine/state.ts +1151 -0
- package/src/agent-src/templates/scripts/work_engine/state_io.ts +413 -0
- package/src/config/agent-settings.template.yml +1 -1
- package/src/install/atomic.ts +111 -0
- package/src/install/conflict.ts +226 -0
- package/src/install/detect.ts +280 -0
- package/src/install/paths.ts +90 -0
- package/src/install/plan.ts +205 -0
- package/src/install/preflight.ts +210 -0
- package/src/install/selectedTools.ts +80 -0
- package/src/install/toolDetection.ts +120 -0
- package/src/install/txlog.ts +161 -0
- package/src/install/types.ts +175 -0
- package/src/install/wizard-plan.ts +216 -0
- package/src/scripts/_cli/cmd_converge.ts +38 -0
- package/src/scripts/_cli/cmd_doctor.ts +113 -2
- package/src/scripts/_cli/cmd_explain.ts +2 -2
- package/src/scripts/_cli/cmd_export.ts +3 -3
- package/src/scripts/_cli/cmd_fleet.ts +13 -1
- package/src/scripts/_cli/cmd_migrate.ts +3 -3
- package/src/scripts/_cli/cmd_prune.ts +2 -2
- package/src/scripts/_cli/cmd_refresh.ts +4 -4
- package/src/scripts/_cli/cmd_settings_check.ts +2 -2
- package/src/scripts/_cli/cmd_settings_migrate.ts +2 -2
- package/src/scripts/_cli/cmd_sync.ts +2 -2
- package/src/scripts/_cli/cmd_uninstall.ts +2 -2
- package/src/scripts/_cli/cmd_update.ts +8 -8
- package/src/scripts/_cli/cmd_upgrade.ts +4 -3
- package/src/scripts/_cli/cmd_validate.ts +3 -3
- package/src/scripts/_cli/cmd_versions.ts +2 -2
- package/src/scripts/_cli/explain_last/assumptions.ts +2 -2
- package/src/scripts/_cli/explain_last/council.ts +2 -2
- package/src/scripts/_cli/explain_last/halt.ts +2 -2
- package/src/scripts/_cli/explain_last/index.ts +2 -2
- package/src/scripts/_cli/explain_last/inputs.ts +4 -4
- package/src/scripts/_cli/explain_last/memory.ts +2 -2
- package/src/scripts/_cli/explain_last/provider.ts +2 -2
- package/src/scripts/_cli/explain_last/render.ts +2 -2
- package/src/scripts/_cli/explain_last/route.ts +2 -2
- package/src/scripts/_cli/explain_last/scrubber.ts +2 -2
- package/src/scripts/_cli/explain_last/sections/assumptions.ts +2 -2
- package/src/scripts/_cli/explain_last/sections/council.ts +2 -2
- package/src/scripts/_cli/explain_last/sections/halt.ts +2 -2
- package/src/scripts/_cli/explain_last/sections/header.ts +2 -2
- package/src/scripts/_cli/explain_last/sections/index.ts +1 -1
- package/src/scripts/_cli/explain_last/sections/inputs.ts +2 -2
- package/src/scripts/_cli/explain_last/sections/memory.ts +2 -2
- package/src/scripts/_cli/explain_last/sections/pack.ts +2 -2
- package/src/scripts/_cli/explain_last/sections/provider.ts +2 -2
- package/src/scripts/_cli/explain_last/sections/route.ts +2 -2
- package/src/scripts/_cli/explain_last/state_loader.ts +2 -2
- package/src/scripts/_dispatch.bash +20 -1
- package/src/scripts/_lib/agent_settings.ts +1 -1
- package/src/scripts/_lib/agent_src.ts +7 -7
- package/src/scripts/_lib/agents_overlay.ts +1 -1
- package/src/scripts/_lib/bench_ab_cache.ts +1 -1
- package/src/scripts/_lib/bench_ab_scoring.ts +1 -1
- package/src/scripts/_lib/bench_ab_scoring_v2.ts +3 -3
- package/src/scripts/_lib/bench_cost.ts +1 -1
- package/src/scripts/_lib/bench_quality.ts +3 -3
- package/src/scripts/_lib/bench_report.ts +4 -4
- package/src/scripts/_lib/bench_telegraph.ts +1 -1
- package/src/scripts/_lib/bench_telegraph_report.ts +4 -4
- package/src/scripts/_lib/changelog_eras.ts +1 -1
- package/src/scripts/_lib/claude_desktop_bundler.ts +1 -1
- package/src/scripts/_lib/cli_wrapper.ts +1 -1
- package/src/scripts/_lib/fs_atomic.ts +1 -1
- package/src/scripts/_lib/global_deploy_inventory.ts +1 -1
- package/src/scripts/_lib/install_layout.ts +1 -1
- package/src/scripts/_lib/install_regenerator.ts +1 -1
- package/src/scripts/_lib/installed_lock.ts +1 -1
- package/src/scripts/_lib/installed_tools.ts +1 -1
- package/src/scripts/_lib/json_pointers.ts +1 -1
- package/src/scripts/_lib/knowledge_global.ts +1 -1
- package/src/scripts/_lib/knowledge_global_promote.ts +2 -2
- package/src/scripts/_lib/knowledge_global_redaction.ts +2 -2
- package/src/scripts/_lib/link_crypto.ts +4 -4
- package/src/scripts/_lib/linked_projects.ts +4 -4
- package/src/scripts/_lib/model_tier.ts +1 -1
- package/src/scripts/_lib/module_detection.ts +2 -2
- package/src/scripts/_lib/pin_resolver.ts +1 -1
- package/src/scripts/_lib/script_output.ts +1 -1
- package/src/scripts/_lib/security_lint.ts +1 -1
- package/src/scripts/_lib/surface_tiers.ts +1 -1
- package/src/scripts/_lib/text_similarity.ts +1 -1
- package/src/scripts/_lib/update_check.ts +2 -2
- package/src/scripts/_lib/user_global_paths.ts +1 -1
- package/src/scripts/_lib/value_ladder.ts +1 -1
- package/src/scripts/_lib/value_report.ts +1 -1
- package/src/scripts/_lib/zip_min.ts +2 -2
- package/src/scripts/adoption_report.ts +3 -3
- package/src/scripts/adoption_snapshot.ts +3 -3
- package/src/scripts/adoption_status.ts +2 -2
- package/src/scripts/adr/regenerate_index.ts +3 -3
- package/src/scripts/ai_council/_default_prices.ts +2 -3
- package/src/scripts/ai_council/advisors.ts +1 -1
- package/src/scripts/ai_council/airgap.ts +1 -1
- package/src/scripts/ai_council/budget_guard.ts +1 -1
- package/src/scripts/ai_council/bundler.ts +1 -1
- package/src/scripts/ai_council/cli_hints.ts +1 -1
- package/src/scripts/ai_council/clients.ts +5 -5
- package/src/scripts/ai_council/compile_corpus.ts +1 -1
- package/src/scripts/ai_council/confidence_gate.ts +1 -1
- package/src/scripts/ai_council/config.ts +1 -1
- package/src/scripts/ai_council/consensus.ts +1 -1
- package/src/scripts/ai_council/events_log.ts +1 -1
- package/src/scripts/ai_council/learn_low_impact_preview.ts +1 -1
- package/src/scripts/ai_council/low_impact_corpus.ts +1 -1
- package/src/scripts/ai_council/low_impact_intake.ts +1 -1
- package/src/scripts/ai_council/modes.ts +1 -1
- package/src/scripts/ai_council/orchestrator.ts +3 -3
- package/src/scripts/ai_council/pricing.ts +2 -2
- package/src/scripts/ai_council/probation_gate.ts +2 -2
- package/src/scripts/ai_council/project_context.ts +1 -1
- package/src/scripts/ai_council/prompts.ts +1 -1
- package/src/scripts/ai_council/redact_low_impact_entry.ts +2 -2
- package/src/scripts/ai_council/session.ts +1 -1
- package/src/scripts/ai_council/shadow_dispatch.ts +1 -1
- package/src/scripts/ai_council/solo_dispatch.ts +1 -1
- package/src/scripts/analysis_freshness.ts +2 -2
- package/src/scripts/annotate_discovery.ts +2 -2
- package/src/scripts/apply_modules_config.ts +2 -2
- package/src/scripts/audit_adr_coverage.ts +3 -3
- package/src/scripts/audit_auto_rules.ts +2 -2
- package/src/scripts/audit_cloud_compatibility.ts +3 -3
- package/src/scripts/audit_command_surface.ts +2 -2
- package/src/scripts/audit_initial_context.ts +7 -6
- package/src/scripts/audit_likelihood.ts +5 -5
- package/src/scripts/audit_mcp_tools.ts +3 -3
- package/src/scripts/audit_overlap.ts +2 -2
- package/src/scripts/audit_skill_descriptions.ts +2 -2
- package/src/scripts/audit_skill_overlap.ts +5 -5
- package/src/scripts/audit_user_type_axis.ts +4 -4
- package/src/scripts/backfill_model_tier.ts +1 -1
- package/src/scripts/bench_ab_cache_dispatch.ts +2 -2
- package/src/scripts/bench_ab_clone.ts +2 -2
- package/src/scripts/bench_ab_diff.ts +3 -3
- package/src/scripts/bench_ab_integrity.ts +2 -2
- package/src/scripts/bench_ab_run.ts +4 -4
- package/src/scripts/bench_ab_task_runner.ts +1 -1
- package/src/scripts/bench_ab_tracka_run.ts +2 -2
- package/src/scripts/bench_ab_v2_run.ts +1 -1
- package/src/scripts/bench_ab_v2_stats.ts +2 -2
- package/src/scripts/bench_baseline_ready.ts +1 -1
- package/src/scripts/bench_condense_memory.ts +4 -4
- package/src/scripts/bench_drift_check.ts +3 -3
- package/src/scripts/bench_per_tool.ts +1 -1
- package/src/scripts/bench_rtk_savings.ts +4 -4
- package/src/scripts/bench_run.ts +4 -4
- package/src/scripts/bench_runner.ts +1 -1
- package/src/scripts/build_cloud_bundle.ts +3 -3
- package/src/scripts/build_discovery_manifest.ts +13 -15
- package/src/scripts/build_linear_digest.ts +2 -2
- package/src/scripts/build_mcp_registry_manifest.ts +3 -3
- package/src/scripts/build_proof.ts +6 -0
- package/src/scripts/build_rule_trigger_matrix.ts +2 -2
- package/src/scripts/capture_showcase_session.ts +3 -3
- package/src/scripts/chat_history.ts +1 -1
- package/src/scripts/check_always_budget.ts +1 -1
- package/src/scripts/check_artefact_checksums.ts +4 -4
- package/src/scripts/check_artefact_count_messaging.ts +197 -0
- package/src/scripts/check_augment_description_cap.ts +3 -3
- package/src/scripts/check_augmentignore.ts +1 -1
- package/src/scripts/check_beta_review_markers.ts +3 -3
- package/src/scripts/check_bite_sized_granularity.ts +1 -1
- package/src/scripts/check_cluster_patterns.ts +47 -3
- package/src/scripts/check_command_count_messaging.ts +2 -2
- package/src/scripts/check_condensation.ts +2 -2
- package/src/scripts/check_condensed_paths.ts +6 -6
- package/src/scripts/check_context_paths.ts +1 -1
- package/src/scripts/check_council_config_location.ts +3 -3
- package/src/scripts/check_council_layout.ts +2 -2
- package/src/scripts/check_council_references.ts +2 -2
- package/src/scripts/check_discovery_determinism.ts +3 -3
- package/src/scripts/check_gate_paths.ts +4 -4
- package/src/scripts/check_iron_law_prominence.ts +2 -2
- package/src/scripts/check_kernel_rule_bundle.ts +3 -3
- package/src/scripts/check_knowledge_cards.ts +4 -4
- package/src/scripts/check_knowledge_pages.ts +1 -1
- package/src/scripts/check_md_language.ts +3 -3
- package/src/scripts/check_memory.ts +3 -3
- package/src/scripts/check_memory_proposal.ts +2 -2
- package/src/scripts/check_module_management_neutral.ts +1 -1
- package/src/scripts/check_no_conflict_markers.ts +1 -1
- package/src/scripts/check_no_external_sources.ts +1 -1
- package/src/scripts/check_no_local_settings_committed.ts +2 -2
- package/src/scripts/check_no_new_legacy_path.ts +3 -3
- package/src/scripts/check_no_roadmap_refs.ts +3 -3
- package/src/scripts/check_one_off_location.ts +3 -3
- package/src/scripts/check_overlay_cascade_subdirs.ts +3 -3
- package/src/scripts/check_portability.ts +3 -3
- package/src/scripts/check_proposal.ts +0 -0
- package/src/scripts/check_public_catalog_links.ts +1 -1
- package/src/scripts/check_public_links.ts +2 -2
- package/src/scripts/check_references.ts +3 -3
- package/src/scripts/check_release_includes_discovery.ts +2 -2
- package/src/scripts/check_release_pr_shape.ts +2 -2
- package/src/scripts/check_release_published.ts +1 -1
- package/src/scripts/check_release_trunk_sync.ts +3 -3
- package/src/scripts/check_reply_consistency.ts +1 -1
- package/src/scripts/check_roadmap_trackable.ts +2 -2
- package/src/scripts/check_role_doc_links.ts +2 -2
- package/src/scripts/check_safety_floor_untouched.ts +3 -3
- package/src/scripts/check_skill_requires.ts +2 -2
- package/src/scripts/check_structural_breaking.ts +2 -2
- package/src/scripts/check_surface_tiers.ts +2 -2
- package/src/scripts/check_template_pin_drift.ts +1 -1
- package/src/scripts/check_test_coverage_diff.ts +2 -2
- package/src/scripts/check_token_optimizer_freshness.ts +3 -3
- package/src/scripts/check_trigger_evals.ts +2 -2
- package/src/scripts/check_update_banner.ts +1 -1
- package/src/scripts/ci_status.ts +0 -0
- package/src/scripts/ci_summary.ts +3 -3
- package/src/scripts/ci_time_ratio.ts +1 -1
- package/src/scripts/command_suggester/cooldown.ts +1 -1
- package/src/scripts/command_suggester/index.ts +1 -1
- package/src/scripts/command_suggester/loader.ts +1 -1
- package/src/scripts/command_suggester/match.ts +1 -1
- package/src/scripts/command_suggester/rank.ts +1 -1
- package/src/scripts/command_suggester/render.ts +1 -1
- package/src/scripts/command_suggester/sanitize.ts +1 -1
- package/src/scripts/command_suggester/settings.ts +1 -1
- package/src/scripts/command_suggester/types.ts +0 -0
- package/src/scripts/compile_router.ts +4 -4
- package/src/scripts/condense.ts +3 -3
- package/src/scripts/condense_memory.ts +1 -1
- package/src/scripts/config/index.ts +1 -1
- package/src/scripts/config/packs.ts +1 -1
- package/src/scripts/config/presets.ts +1 -1
- package/src/scripts/config/profile_explain.ts +1 -1
- package/src/scripts/config/profiles.ts +1 -1
- package/src/scripts/config/session_profiles.ts +1 -1
- package/src/scripts/context_hygiene_hook.ts +2 -2
- package/src/scripts/cost_by_conversation.ts +1 -1
- package/src/scripts/cost_summary.ts +2 -2
- package/src/scripts/council_cli.ts +1 -1
- package/src/scripts/council_prune.ts +1 -1
- package/src/scripts/cross_repo_retrieve.ts +2 -2
- package/src/scripts/discovery_stats.ts +3 -3
- package/src/scripts/evidence_report.ts +4 -4
- package/src/scripts/extract_audit_patterns.ts +2 -2
- package/src/scripts/first_run_gate_hook.ts +1 -1
- package/src/scripts/gen_discovery_baseline.ts +2 -2
- package/src/scripts/generate_capabilities_index.ts +2 -2
- package/src/scripts/generate_capability_matrix.ts +2 -2
- package/src/scripts/generate_catalog.ts +2 -2
- package/src/scripts/generate_command_flows.ts +2 -2
- package/src/scripts/generate_cookbook.ts +1 -1
- package/src/scripts/generate_index.ts +3 -3
- package/src/scripts/generate_ownership_matrix.ts +2 -2
- package/src/scripts/generate_pack_manifests.ts +2 -2
- package/src/scripts/generate_role_experiences_catalog.ts +3 -3
- package/src/scripts/hooks/block_no_verify.ts +2 -2
- package/src/scripts/hooks/dispatch_hook.ts +2 -2
- package/src/scripts/hooks/dispatch_issues.ts +1 -1
- package/src/scripts/hooks/envelope.ts +1 -1
- package/src/scripts/hooks/replay_hook.ts +1 -1
- package/src/scripts/hooks/state_io.ts +1 -1
- package/src/scripts/hooks_doctor.ts +1 -1
- package/src/scripts/hooks_status.ts +1 -1
- package/src/scripts/injection_scan_hook.ts +1 -1
- package/src/scripts/install.ts +145 -3
- package/src/scripts/inventory_abstraction_budget.ts +5 -5
- package/src/scripts/inventory_frontmatter.ts +1 -1
- package/src/scripts/inventory_meta_layers.ts +1 -1
- package/src/scripts/iron_law_sha.ts +1 -1
- package/src/scripts/knowledge_global_cli.ts +3 -3
- package/src/scripts/linked_projects_list.ts +1 -1
- package/src/scripts/lint_agent_security.ts +4 -4
- package/src/scripts/lint_agent_skill_names.ts +1 -1
- package/src/scripts/lint_agents_layout.ts +2 -2
- package/src/scripts/lint_agents_md.ts +3 -3
- package/src/scripts/lint_archived_skills.ts +2 -2
- package/src/scripts/lint_artefact_frontmatter.ts +2 -2
- package/src/scripts/lint_bench_ab.ts +2 -2
- package/src/scripts/lint_bench_corpus.ts +1 -1
- package/src/scripts/lint_command_flow_coverage.ts +1 -1
- package/src/scripts/lint_command_routing.ts +2 -2
- package/src/scripts/lint_command_tiers.ts +1 -1
- package/src/scripts/lint_command_verbs.ts +4 -4
- package/src/scripts/lint_commit_subjects.ts +2 -2
- package/src/scripts/lint_context_spine_usage.ts +3 -3
- package/src/scripts/lint_discovery_manifest.ts +4 -4
- package/src/scripts/lint_discovery_vocabulary.ts +2 -2
- package/src/scripts/lint_empty_roadmaps.ts +3 -3
- package/src/scripts/lint_eval_freshness.ts +2 -2
- package/src/scripts/lint_examples.ts +2 -2
- package/src/scripts/lint_explain_trace.ts +2 -2
- package/src/scripts/lint_featured_skills.ts +0 -0
- package/src/scripts/lint_flows.ts +5 -5
- package/src/scripts/lint_framework_leakage.ts +1 -1
- package/src/scripts/lint_framework_leakage_allowlist.json +10 -2
- package/src/scripts/lint_frontmatter_boilerplate.ts +2 -2
- package/src/scripts/lint_ghostwriter_source.ts +3 -3
- package/src/scripts/lint_global_paths.ts +1 -1
- package/src/scripts/lint_handoffs.ts +1 -1
- package/src/scripts/lint_hidden_unicode.ts +1 -1
- package/src/scripts/lint_hook_concern_budget.ts +2 -2
- package/src/scripts/lint_hook_manifest.ts +2 -2
- package/src/scripts/lint_instruction_smuggling.ts +1 -1
- package/src/scripts/lint_load_context.ts +2 -2
- package/src/scripts/lint_marketplace.ts +1 -1
- package/src/scripts/lint_marketplace_install_completeness.ts +2 -2
- package/src/scripts/lint_mcp_config_security.ts +1 -1
- package/src/scripts/lint_mcp_registry_manifest.ts +1 -1
- package/src/scripts/lint_media_policy_linkage.ts +3 -3
- package/src/scripts/lint_missions.ts +3 -3
- package/src/scripts/lint_model_tier_coverage.ts +3 -3
- package/src/scripts/lint_namespace.ts +2 -2
- package/src/scripts/lint_namespace_collisions.ts +2 -2
- package/src/scripts/lint_new_skill_gate.ts +3 -3
- package/src/scripts/lint_no_new_atomic_commands.ts +9 -6
- package/src/scripts/lint_no_python_twin_rationale.ts +102 -0
- package/src/scripts/lint_one_off_age.ts +2 -2
- package/src/scripts/lint_orchestration_dsl.ts +3 -3
- package/src/scripts/lint_orchestrator_auto_detect.ts +1 -1
- package/src/scripts/lint_pack_boundaries.ts +2 -2
- package/src/scripts/lint_pack_dependencies.ts +2 -2
- package/src/scripts/lint_pack_first_win.ts +2 -2
- package/src/scripts/lint_persona_governance.ts +3 -3
- package/src/scripts/lint_positioning.ts +1 -1
- package/src/scripts/lint_profile_overlay_set_only.ts +2 -2
- package/src/scripts/lint_readme_jargon.ts +2 -2
- package/src/scripts/lint_readme_size.ts +2 -2
- package/src/scripts/lint_regression.ts +3 -3
- package/src/scripts/lint_roadmap_ci_steps.ts +3 -3
- package/src/scripts/lint_roadmap_complexity.ts +1 -1
- package/src/scripts/lint_roadmap_later_disposition.ts +2 -2
- package/src/scripts/lint_role_experiences.ts +2 -2
- package/src/scripts/lint_rule_interactions.ts +1 -1
- package/src/scripts/lint_rule_tiers.ts +1 -1
- package/src/scripts/lint_showcase_sessions.ts +2 -2
- package/src/scripts/lint_skill_frontmatter_safety.ts +1 -1
- package/src/scripts/lint_skill_originality.ts +1 -1
- package/src/scripts/lint_skill_tools.ts +3 -3
- package/src/scripts/lint_ticket_buildable.ts +2 -2
- package/src/scripts/lint_topics_yaml.ts +3 -3
- package/src/scripts/lint_trust_coherence.ts +3 -3
- package/src/scripts/lint_value_dashboard.ts +3 -3
- package/src/scripts/lint_workflow_security.ts +3 -3
- package/src/scripts/lint_workspace_boundary.ts +2 -2
- package/src/scripts/mcp_parity_smoke.ts +1 -1
- package/src/scripts/mcp_render.ts +1 -1
- package/src/scripts/mcp_server/catalog.ts +1 -1
- package/src/scripts/mcp_server/index.ts +1 -1
- package/src/scripts/mcp_server/metadata.ts +1 -1
- package/src/scripts/mcp_server/prompts.ts +1 -1
- package/src/scripts/mcp_server/resources.ts +1 -1
- package/src/scripts/mcp_server/server.ts +1 -1
- package/src/scripts/mcp_server/telemetry.ts +1 -1
- package/src/scripts/mcp_server/tools.ts +1 -1
- package/src/scripts/mcp_telemetry_health.ts +1 -1
- package/src/scripts/mcp_telemetry_query.ts +3 -3
- package/src/scripts/mcp_telemetry_store.ts +3 -3
- package/src/scripts/measure_augment_budget.ts +2 -2
- package/src/scripts/measure_density.ts +2 -2
- package/src/scripts/measure_frugality_savings.ts +3 -3
- package/src/scripts/measure_markitdown_lift.ts +1 -1
- package/src/scripts/measure_patterns.ts +1 -1
- package/src/scripts/measure_projection_bytes.ts +1 -1
- package/src/scripts/measure_rule_budget.ts +1 -1
- package/src/scripts/measure_skill_reduction.ts +1 -1
- package/src/scripts/memory_hash.ts +1 -1
- package/src/scripts/memory_lookup.ts +6 -6
- package/src/scripts/memory_report.ts +1 -1
- package/src/scripts/memory_signal.ts +1 -1
- package/src/scripts/memory_status.ts +2 -2
- package/src/scripts/migrate_command_suggestions.ts +1 -1
- package/src/scripts/migrate_frontmatter_defaults.ts +1 -1
- package/src/scripts/mine_session.ts +3 -3
- package/src/scripts/minimal_safe_diff_hook.ts +2 -2
- package/src/scripts/move_artefact.ts +3 -3
- package/src/scripts/new_skill.ts +3 -3
- package/src/scripts/onboarding_gate_hook.ts +2 -2
- package/src/scripts/pack_mcp_content.ts +1 -1
- package/src/scripts/parity/replay.ts +3 -2
- package/src/scripts/pattern_share.ts +2 -2
- package/src/scripts/plan_physical_move.ts +3 -3
- package/src/scripts/prediction-pool/poisson_sim.ts +2 -2
- package/src/scripts/prediction-pool/pool_winsim.ts +2 -2
- package/src/scripts/prediction-pool/score_ev.ts +2 -2
- package/src/scripts/prepack-check.mjs +108 -5
- package/src/scripts/print_required_checks.ts +2 -2
- package/src/scripts/probe_projection_fidelity.ts +2 -2
- package/src/scripts/probe_skill_registration.ts +2 -2
- package/src/scripts/profile_staleness_hook.ts +2 -2
- package/src/scripts/profile_use.ts +2 -2
- package/src/scripts/project_thin_rules.ts +3 -3
- package/src/scripts/propose_modules_config.ts +2 -2
- package/src/scripts/prototype_lint_contradictions.ts +2 -2
- package/src/scripts/prove_pack_extractable.ts +1 -1
- package/src/scripts/readme_linter.ts +4 -4
- package/src/scripts/redact_hook_capture.ts +2 -2
- package/src/scripts/refine_ticket_detect.ts +1 -1
- package/src/scripts/release.ts +30 -19
- package/src/scripts/render_benchmark_md.ts +2 -2
- package/src/scripts/render_value_md.ts +2 -2
- package/src/scripts/roadmap_progress_hook.ts +1 -1
- package/src/scripts/router_telemetry.ts +1 -1
- package/src/scripts/run_skill_evals.ts +2 -2
- package/src/scripts/runtime_dispatcher.ts +1 -1
- package/src/scripts/runtime_handler.ts +1 -1
- package/src/scripts/runtime_registry.ts +3 -3
- package/src/scripts/score_skill_selection.ts +1 -1
- package/src/scripts/security_audit_config.ts +2 -2
- package/src/scripts/skill_collision_clusters.ts +1 -1
- package/src/scripts/skill_discovery.ts +1 -1
- package/src/scripts/skill_linter.ts +8 -7
- package/src/scripts/skill_overlap.ts +2 -2
- package/src/scripts/skill_preview.ts +1 -1
- package/src/scripts/skill_tools/audit_persona_coverage.ts +3 -3
- package/src/scripts/skill_tools/audit_user_type_coverage.ts +3 -3
- package/src/scripts/skill_tools/index.ts +1 -1
- package/src/scripts/skill_tools/run_block_d_eval.ts +3 -3
- package/src/scripts/skill_tools/score_skill_relevance.ts +3 -3
- package/src/scripts/skill_tools/suggest_skill_for_task.ts +3 -3
- package/src/scripts/skill_trigger_eval.ts +2 -2
- package/src/scripts/skill_usage_collect.ts +2 -2
- package/src/scripts/skill_usage_report.ts +2 -2
- package/src/scripts/smoke_path_resolution.ts +2 -2
- package/src/scripts/smoke_quickstart.ts +4 -4
- package/src/scripts/snapshot_agent_outputs.ts +2 -2
- package/src/scripts/spotcheck_thin_root.ts +2 -2
- package/src/scripts/surface-tiers.yml +1 -0
- package/src/scripts/sync_agent_settings.ts +2 -2
- package/src/scripts/sync_github_metadata.ts +4 -4
- package/src/scripts/sync_gitignore.ts +3 -3
- package/src/scripts/sync_yaml_rt.ts +2 -2
- package/src/scripts/telegraph_stats.ts +1 -1
- package/src/scripts/tool_registry.ts +2 -2
- package/src/scripts/tools/adapter_errors.ts +1 -1
- package/src/scripts/tools/base_adapter.ts +1 -1
- package/src/scripts/tools/github_adapter.ts +1 -1
- package/src/scripts/tools/jira_adapter.ts +1 -1
- package/src/scripts/trigger_coverage.ts +2 -2
- package/src/scripts/update_counts.ts +68 -6
- package/src/scripts/update_prices.ts +3 -3
- package/src/scripts/validate_agent_settings.ts +3 -3
- package/src/scripts/validate_decision_engine.ts +2 -2
- package/src/scripts/validate_discovery_manifest.ts +3 -3
- package/src/scripts/validate_frontmatter.ts +5 -5
- package/src/scripts/validate_pack_yaml.ts +0 -0
- package/src/scripts/validate_safe_paths.ts +2 -2
- package/src/scripts/validate_telegraph_carveouts.ts +3 -3
- package/src/scripts/verify_before_complete_hook.ts +2 -2
- package/src/scripts/verify_physical_move.ts +2 -2
- package/src/scripts/wrapper_freshness_hook.ts +3 -3
- package/src/server/schemas/settings.ts +426 -0
- package/src/shared/settingsSurface.ts +184 -0
- package/src/shared/userMd/formAdapter.ts +86 -0
- package/src/shared/userMd/schema.ts +59 -0
- package/src/shared/userMd/utils.ts +91 -0
- package/dist/agent-src/commands/optimize-project.md +0 -243
- package/dist/ui/assets/index-BbWWuFrF.css +0 -1
- package/dist/ui/assets/index-UjcTG_9O.js +0 -40
- package/dist/ui/assets/index-UjcTG_9O.js.map +0 -1
|
@@ -0,0 +1,662 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Engineering Memory validator.
|
|
4
|
+
*
|
|
5
|
+
* TypeScript twin of `src/agent-src/templates/scripts/check_memory.py`
|
|
6
|
+
* (ADR-200, Phase 1 — consumer-shipped template). Adapted from the dev-side
|
|
7
|
+
* `src/scripts/check_memory.ts` twin: the template `.py` is the leaner
|
|
8
|
+
* consumer surface — it has NO `--shadow-report`, NO `priority`/date-discipline/
|
|
9
|
+
* critical-stale/tier-0-inflation checks. Those are stripped here so this twin
|
|
10
|
+
* matches the template `.py` exactly. The CLI contract mirrors the Python
|
|
11
|
+
* original EXACTLY — same flags (`--path`, `--format`, `--append-only`,
|
|
12
|
+
* `--base`), same exit codes, same stdout/stderr split, byte-identical finding
|
|
13
|
+
* messages, same scan scope and ordering. No behaviour changes — latent bugs
|
|
14
|
+
* are replicated and flagged in the porting report, not fixed.
|
|
15
|
+
*
|
|
16
|
+
* Validates YAML files under `agents/memory/<type>/**\/*.yml` against the
|
|
17
|
+
* schema documented in `guidelines/agent-infra/engineering-memory-data-format`.
|
|
18
|
+
*
|
|
19
|
+
* Checks:
|
|
20
|
+
* * Required shared frontmatter: id, status, confidence, source, owner,
|
|
21
|
+
* last_validated, review_after_days.
|
|
22
|
+
* * Duplicate `id` within the same type.
|
|
23
|
+
* * Basic redaction: obvious secrets, private URLs with credentials,
|
|
24
|
+
* IP addresses tied to internal ranges.
|
|
25
|
+
* * Staleness: entries where (today - last_validated) > review_after_days
|
|
26
|
+
* are reported (informational, never hard fail).
|
|
27
|
+
*
|
|
28
|
+
* * Append-only (--append-only): inspects `git diff` against a ref to
|
|
29
|
+
* ensure intake JSONL files (`agents/memory/intake/*.jsonl`) only gained
|
|
30
|
+
* lines at EOF. In-place edits, deletions, or reorderings fail the check.
|
|
31
|
+
* See `road-to-memory-merge-safety.md` Phase 0.
|
|
32
|
+
*
|
|
33
|
+
* Exit codes: 0 = clean, 1 = violations, 2 = PyYAML missing, 3 = internal error.
|
|
34
|
+
*
|
|
35
|
+
* Usage:
|
|
36
|
+
* check_memory # validate templates + agents/memory
|
|
37
|
+
* check_memory --path agents/memory
|
|
38
|
+
* check_memory --format json
|
|
39
|
+
* check_memory --append-only # CI: diff vs origin/main
|
|
40
|
+
* check_memory --append-only --base HEAD~1
|
|
41
|
+
*
|
|
42
|
+
* Note on YAML date typing: the Python original relies on PyYAML's
|
|
43
|
+
* `safe_load` converting unquoted `YYYY-MM-DD` scalars to `datetime.date`
|
|
44
|
+
* (and `YYYY-MM-DD HH:MM:SS` to `datetime.datetime`). The `yaml` npm
|
|
45
|
+
* package parses every scalar to a string, so this twin re-implements
|
|
46
|
+
* PyYAML's timestamp implicit-resolver to convert matching *plain*
|
|
47
|
+
* (unquoted) scalars into a `PyDate` marker — preserving the
|
|
48
|
+
* `isinstance(value, datetime.date)` semantics the staleness checks rely
|
|
49
|
+
* on. Quoted dates stay strings, exactly as in PyYAML.
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
import { spawnSync } from 'node:child_process';
|
|
53
|
+
import * as fs from 'node:fs';
|
|
54
|
+
import * as path from 'node:path';
|
|
55
|
+
import process from 'node:process';
|
|
56
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
57
|
+
import YAML, { parseDocument } from 'yaml';
|
|
58
|
+
|
|
59
|
+
type Severity = 'error' | 'warning' | 'info';
|
|
60
|
+
|
|
61
|
+
const REQUIRED_KEYS: ReadonlySet<string> = new Set([
|
|
62
|
+
'id',
|
|
63
|
+
'status',
|
|
64
|
+
'confidence',
|
|
65
|
+
'source',
|
|
66
|
+
'owner',
|
|
67
|
+
'last_validated',
|
|
68
|
+
'review_after_days',
|
|
69
|
+
]);
|
|
70
|
+
const VALID_STATUS: ReadonlySet<string> = new Set(['active', 'deprecated', 'archived']);
|
|
71
|
+
const VALID_CONFIDENCE: ReadonlySet<string> = new Set(['low', 'medium', 'high']);
|
|
72
|
+
const KNOWN_TYPES: ReadonlySet<string> = new Set([
|
|
73
|
+
'domain-invariants',
|
|
74
|
+
'incident-learnings',
|
|
75
|
+
'product-rules',
|
|
76
|
+
]);
|
|
77
|
+
|
|
78
|
+
// Redaction heuristics — plain-regex, deliberately conservative.
|
|
79
|
+
// False positives are fixed by quoting the line differently; false
|
|
80
|
+
// negatives are a curator responsibility.
|
|
81
|
+
const REDACTION_PATTERNS: ReadonlyArray<readonly [RegExp, string]> = [
|
|
82
|
+
// Key=value secret with a clear credential-word prefix. The value must
|
|
83
|
+
// be a single token (no spaces, no "/" — skips filepaths and URLs).
|
|
84
|
+
[
|
|
85
|
+
/\b(api[_-]?key|auth[_-]?token|access[_-]?token|bearer|secret|password|passwd|private[_-]?key)\b\s*[:=]\s*[A-Za-z0-9+/=_\-]{8,}(?![/.\w])/i,
|
|
86
|
+
'inline credential',
|
|
87
|
+
],
|
|
88
|
+
[/https?:\/\/[^\s"'/]*:[^\s"'/]*@/, 'url with credentials'],
|
|
89
|
+
[/\b10\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/, 'internal ipv4 range'],
|
|
90
|
+
[/\b192\.168\.\d{1,3}\.\d{1,3}\b/, 'internal ipv4 range'],
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
// PyYAML timestamp implicit-resolver. A *plain* (unquoted) scalar matching
|
|
94
|
+
// this is constructed as datetime.date / datetime.datetime — both pass
|
|
95
|
+
// `isinstance(value, datetime.date)`. Source: yaml/resolver.py.
|
|
96
|
+
const PYYAML_TIMESTAMP_RE =
|
|
97
|
+
/^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]|[0-9][0-9][0-9][0-9]-[0-9][0-9]?-[0-9][0-9]?(?:[Tt]|[ \t]+)[0-9][0-9]?:[0-9][0-9]:[0-9][0-9](?:\.[0-9]*)?(?:[ \t]*(?:Z|[-+][0-9][0-9]?(?::[0-9][0-9])?))?)$/;
|
|
98
|
+
const PYYAML_DATE_ONLY_RE = /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/;
|
|
99
|
+
|
|
100
|
+
class PyDate {
|
|
101
|
+
constructor(
|
|
102
|
+
readonly year: number,
|
|
103
|
+
readonly month: number,
|
|
104
|
+
readonly day: number,
|
|
105
|
+
) {}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
class Finding {
|
|
109
|
+
constructor(
|
|
110
|
+
readonly file: string,
|
|
111
|
+
readonly line: number,
|
|
112
|
+
readonly severity: Severity,
|
|
113
|
+
readonly message: string,
|
|
114
|
+
readonly entry_id: string = '',
|
|
115
|
+
) {}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
type EntryValue = unknown;
|
|
119
|
+
type Entry = Record<string, EntryValue>;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Python-compatible JSON serializer.
|
|
123
|
+
*
|
|
124
|
+
* `json.dumps(..., indent=2)` uses item separator `,` + newline and key
|
|
125
|
+
* separator `": "`, and escapes every non-ASCII character (`ensure_ascii=True`
|
|
126
|
+
* default). `json.dumps(obj)` (no indent) uses `", "` / `": "`. JS's
|
|
127
|
+
* `JSON.stringify` does neither, so this reproduces both.
|
|
128
|
+
*/
|
|
129
|
+
function pyJsonDumps(value: unknown, indent: number | null): string {
|
|
130
|
+
const raw = indent === null ? JSON.stringify(value) : JSON.stringify(value, null, indent);
|
|
131
|
+
// Reproduce the default-separator form for the non-indented path:
|
|
132
|
+
// Python emits `", "` between items and `": "` after keys. JS already
|
|
133
|
+
// emits `,` / `:` with no spaces. Re-introduce the spaces only for the
|
|
134
|
+
// non-indented case (the indented case uses newlines + indentation).
|
|
135
|
+
let out = raw;
|
|
136
|
+
if (indent === null) {
|
|
137
|
+
out = pyCompactSeparators(raw);
|
|
138
|
+
}
|
|
139
|
+
return escapeNonAscii(out);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Re-introduce Python's `", "` / `": "` separators into a compact JSON string. */
|
|
143
|
+
function pyCompactSeparators(json: string): string {
|
|
144
|
+
let result = '';
|
|
145
|
+
let inString = false;
|
|
146
|
+
let escaped = false;
|
|
147
|
+
for (let i = 0; i < json.length; i += 1) {
|
|
148
|
+
const ch = json[i] as string;
|
|
149
|
+
result += ch;
|
|
150
|
+
if (escaped) {
|
|
151
|
+
escaped = false;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
if (ch === '\\') {
|
|
155
|
+
escaped = true;
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (ch === '"') {
|
|
159
|
+
inString = !inString;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (!inString && (ch === ',' || ch === ':')) {
|
|
163
|
+
result += ' ';
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** Escape every non-ASCII char as \uXXXX, mirroring json.dumps ensure_ascii. */
|
|
170
|
+
function escapeNonAscii(s: string): string {
|
|
171
|
+
let out = '';
|
|
172
|
+
for (const ch of s) {
|
|
173
|
+
const code = ch.codePointAt(0) ?? 0;
|
|
174
|
+
if (code > 0x7f) {
|
|
175
|
+
// Emit UTF-16 code units (surrogate pairs for astral chars), as
|
|
176
|
+
// Python's json does.
|
|
177
|
+
for (let i = 0; i < ch.length; i += 1) {
|
|
178
|
+
out += `\\u${ch.charCodeAt(i).toString(16).padStart(4, '0')}`;
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
out += ch;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return out;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Parse a YAML document the way PyYAML's `safe_load` would, for the subset
|
|
189
|
+
* of typing the validator inspects: unquoted timestamp scalars become
|
|
190
|
+
* `PyDate`. Everything else falls through to the `yaml` core schema.
|
|
191
|
+
* Throws on parse error (mirrors PyYAML raising YAMLError).
|
|
192
|
+
*/
|
|
193
|
+
function pyYamlSafeLoad(text: string): unknown {
|
|
194
|
+
const doc = parseDocument(text, { prettyErrors: false });
|
|
195
|
+
if (doc.errors.length > 0) {
|
|
196
|
+
const err = doc.errors[0];
|
|
197
|
+
throw new Error(err ? err.message : 'YAML parse error');
|
|
198
|
+
}
|
|
199
|
+
YAML.visit(doc, {
|
|
200
|
+
Scalar(_key, node) {
|
|
201
|
+
if (node.type === 'PLAIN' && typeof node.value === 'string') {
|
|
202
|
+
const m = PYYAML_TIMESTAMP_RE.exec(node.value);
|
|
203
|
+
if (m) {
|
|
204
|
+
const dm = PYYAML_DATE_ONLY_RE.exec(node.value);
|
|
205
|
+
if (dm) {
|
|
206
|
+
const parts = node.value.split('-');
|
|
207
|
+
node.value = new PyDate(
|
|
208
|
+
Number(parts[0]),
|
|
209
|
+
Number(parts[1]),
|
|
210
|
+
Number(parts[2]),
|
|
211
|
+
);
|
|
212
|
+
} else {
|
|
213
|
+
// Full timestamp — date component is what matters.
|
|
214
|
+
const dateComponent = node.value.split(/[Tt \t]/)[0] as string;
|
|
215
|
+
const parts = dateComponent.split('-');
|
|
216
|
+
node.value = new PyDate(
|
|
217
|
+
Number(parts[0]),
|
|
218
|
+
Number(parts[1]),
|
|
219
|
+
Number(parts[2]),
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
return doc.toJS({ mapAsMap: false });
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** Days between two PyDate values, mirroring (date.today() - lv).days. */
|
|
230
|
+
function _dateDiffDays(today: PyDate, lv: PyDate): number {
|
|
231
|
+
const a = Date.UTC(today.year, today.month - 1, today.day);
|
|
232
|
+
const b = Date.UTC(lv.year, lv.month - 1, lv.day);
|
|
233
|
+
return Math.round((a - b) / 86_400_000);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function _today(): PyDate {
|
|
237
|
+
const now = new Date();
|
|
238
|
+
return new PyDate(now.getFullYear(), now.getMonth() + 1, now.getDate());
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function _isPlainObject(v: unknown): v is Record<string, unknown> {
|
|
242
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v) && !(v instanceof PyDate);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function _isInteger(v: unknown): v is number {
|
|
246
|
+
return typeof v === 'number' && Number.isInteger(v);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function _memoryType(p: string): string {
|
|
250
|
+
// Supports `memory/<type>.yml`, `memory/<type>/<hash>.yml`, and
|
|
251
|
+
// `memory/<type>.example.yml` template filenames.
|
|
252
|
+
const parts = p.split(path.sep);
|
|
253
|
+
if (!parts.includes('memory')) {
|
|
254
|
+
return _stem(parts[parts.length - 1] as string);
|
|
255
|
+
}
|
|
256
|
+
const idx = parts.indexOf('memory');
|
|
257
|
+
const nxt = idx + 1 < parts.length ? (parts[idx + 1] as string) : '';
|
|
258
|
+
const stem = _stem(nxt);
|
|
259
|
+
// Strip `.example` suffix used in template files.
|
|
260
|
+
return stem.endsWith('.example') ? stem.slice(0, -'.example'.length) : stem;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/** Mirror pathlib `Path(name).stem`: basename with the final suffix removed. */
|
|
264
|
+
function _stem(name: string): string {
|
|
265
|
+
const base = path.basename(name);
|
|
266
|
+
const dot = base.lastIndexOf('.');
|
|
267
|
+
if (dot <= 0) {
|
|
268
|
+
return base;
|
|
269
|
+
}
|
|
270
|
+
return base.slice(0, dot);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function _validateEntry(entry: Entry, p: string, seenIds: Set<string>, findings: Finding[]): void {
|
|
274
|
+
const eid = typeof entry['id'] === 'string' ? (entry['id'] as string) : entry['id'] != null ? String(entry['id']) : '';
|
|
275
|
+
const eidStr = entry['id'] == null ? '' : eid;
|
|
276
|
+
const present = new Set(Object.keys(entry));
|
|
277
|
+
const missing: string[] = [];
|
|
278
|
+
for (const key of REQUIRED_KEYS) {
|
|
279
|
+
if (!present.has(key)) {
|
|
280
|
+
missing.push(key);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
missing.sort();
|
|
284
|
+
for (const key of missing) {
|
|
285
|
+
findings.push(new Finding(p, 0, 'error', `missing required field: ${key}`, eidStr));
|
|
286
|
+
}
|
|
287
|
+
const status = entry['status'];
|
|
288
|
+
if (status && typeof status === 'string' && !VALID_STATUS.has(status)) {
|
|
289
|
+
findings.push(new Finding(p, 0, 'error', `invalid status '${status}'`, eidStr));
|
|
290
|
+
}
|
|
291
|
+
const confidence = entry['confidence'];
|
|
292
|
+
if (confidence && typeof confidence === 'string' && !VALID_CONFIDENCE.has(confidence)) {
|
|
293
|
+
findings.push(new Finding(p, 0, 'error', `invalid confidence '${confidence}'`, eidStr));
|
|
294
|
+
}
|
|
295
|
+
const sources = (entry['source'] ?? []) as unknown;
|
|
296
|
+
if (!Array.isArray(sources) || sources.length < 1) {
|
|
297
|
+
findings.push(new Finding(p, 0, 'error', 'source must be a list with ≥1 entry', eidStr));
|
|
298
|
+
}
|
|
299
|
+
if (eidStr && seenIds.has(eidStr)) {
|
|
300
|
+
findings.push(new Finding(p, 0, 'error', `duplicate id '${eidStr}'`, eidStr));
|
|
301
|
+
}
|
|
302
|
+
seenIds.add(eidStr);
|
|
303
|
+
// Staleness.
|
|
304
|
+
const lv = entry['last_validated'];
|
|
305
|
+
const days = entry['review_after_days'];
|
|
306
|
+
if (lv instanceof PyDate && _isInteger(days)) {
|
|
307
|
+
const age = _dateDiffDays(_today(), lv);
|
|
308
|
+
if (age > days && entry['status'] === 'active') {
|
|
309
|
+
findings.push(new Finding(p, 0, 'info', `stale: last_validated ${age} days ago (limit ${days})`, eidStr));
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function _checkRedaction(p: string, findings: Finding[]): void {
|
|
315
|
+
const text = fs.readFileSync(p, 'utf-8');
|
|
316
|
+
const lines = _splitlines(text);
|
|
317
|
+
lines.forEach((line, idx) => {
|
|
318
|
+
const lineNo = idx + 1;
|
|
319
|
+
// Skip comments — redaction warnings in example/commentary lines are noise.
|
|
320
|
+
if (line.trimStart().startsWith('#')) {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
for (const [pattern, label] of REDACTION_PATTERNS) {
|
|
324
|
+
if (pattern.test(line)) {
|
|
325
|
+
findings.push(new Finding(p, lineNo, 'error', `possible leak: ${label}`));
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/** Mirror Python str.splitlines() for the line-numbering used above. */
|
|
332
|
+
function _splitlines(text: string): string[] {
|
|
333
|
+
if (text === '') {
|
|
334
|
+
return [];
|
|
335
|
+
}
|
|
336
|
+
// Python splitlines splits on \n, \r, \r\n (and more) and drops a final
|
|
337
|
+
// trailing newline. For YAML/text files \n and \r\n cover the cases.
|
|
338
|
+
const lines = text.split(/\r\n|\r|\n/);
|
|
339
|
+
if (lines.length > 0 && lines[lines.length - 1] === '') {
|
|
340
|
+
lines.pop();
|
|
341
|
+
}
|
|
342
|
+
return lines;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function _validateFile(p: string, findings: Finding[]): void {
|
|
346
|
+
const mtype = _memoryType(p);
|
|
347
|
+
if (!KNOWN_TYPES.has(mtype)) {
|
|
348
|
+
findings.push(new Finding(p, 0, 'warning', `unknown memory type '${mtype}'`));
|
|
349
|
+
}
|
|
350
|
+
_checkRedaction(p, findings);
|
|
351
|
+
let data: unknown;
|
|
352
|
+
try {
|
|
353
|
+
data = pyYamlSafeLoad(fs.readFileSync(p, 'utf-8'));
|
|
354
|
+
if (data === null || data === undefined) {
|
|
355
|
+
data = {};
|
|
356
|
+
}
|
|
357
|
+
} catch (exc) {
|
|
358
|
+
// mirror Python `except Exception` → report class name. PyYAML raises
|
|
359
|
+
// a YAMLError; the `yaml` package surfaces a parse error.
|
|
360
|
+
findings.push(new Finding(p, 0, 'error', `YAML parse error: ${_excClassName(exc)}`));
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
if (!_isPlainObject(data) || !('entries' in data)) {
|
|
364
|
+
findings.push(new Finding(p, 0, 'error', "missing top-level 'entries' key"));
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
const seenIds: Set<string> = new Set();
|
|
368
|
+
const entries = (data['entries'] ?? []) as unknown;
|
|
369
|
+
if (Array.isArray(entries)) {
|
|
370
|
+
for (const entry of entries) {
|
|
371
|
+
if (_isPlainObject(entry)) {
|
|
372
|
+
_validateEntry(entry as Entry, p, seenIds, findings);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/** Mirror Python `exc.__class__.__name__` for the YAML-parse-error message. */
|
|
379
|
+
function _excClassName(_exc: unknown): string {
|
|
380
|
+
// PyYAML errors surface as YAMLError. The TS twin always reports the same
|
|
381
|
+
// class name so the byte-identical "YAML parse error: <Name>" message holds
|
|
382
|
+
// for malformed YAML inputs.
|
|
383
|
+
return 'YAMLError';
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const INTAKE_GLOB = 'agents/memory/intake/*.jsonl';
|
|
387
|
+
|
|
388
|
+
function _git(cmd: string[]): [number, string] {
|
|
389
|
+
const result = spawnSync(cmd[0] as string, cmd.slice(1), { encoding: 'utf-8' });
|
|
390
|
+
if (result.error && (result.error as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
391
|
+
return [127, 'git not found'];
|
|
392
|
+
}
|
|
393
|
+
const code = result.status ?? 1;
|
|
394
|
+
return [code, (result.stdout || '') + (result.stderr || '')];
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
function _resolveBase(explicit: string | null): string | null {
|
|
398
|
+
// CI: GITHUB_BASE_REF is set on PRs → origin/<base>.
|
|
399
|
+
if (explicit) {
|
|
400
|
+
return explicit;
|
|
401
|
+
}
|
|
402
|
+
const baseRef = process.env['GITHUB_BASE_REF'];
|
|
403
|
+
if (baseRef) {
|
|
404
|
+
return `origin/${baseRef}`;
|
|
405
|
+
}
|
|
406
|
+
// Local fallback: origin/main if it exists.
|
|
407
|
+
const [rc] = _git(['git', 'rev-parse', '--verify', 'origin/main']);
|
|
408
|
+
if (rc === 0) {
|
|
409
|
+
return 'origin/main';
|
|
410
|
+
}
|
|
411
|
+
return null;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function _checkAppendOnly(base: string | null, findings: Finding[]): void {
|
|
415
|
+
const ref = _resolveBase(base);
|
|
416
|
+
if (ref === null) {
|
|
417
|
+
findings.push(
|
|
418
|
+
new Finding(
|
|
419
|
+
INTAKE_GLOB,
|
|
420
|
+
0,
|
|
421
|
+
'warning',
|
|
422
|
+
'append-only: no base ref resolved (set --base or GITHUB_BASE_REF)',
|
|
423
|
+
),
|
|
424
|
+
);
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
const [rc, diff] = _git([
|
|
428
|
+
'git',
|
|
429
|
+
'diff',
|
|
430
|
+
'--unified=0',
|
|
431
|
+
'--no-color',
|
|
432
|
+
ref,
|
|
433
|
+
'--',
|
|
434
|
+
'agents/memory/intake/',
|
|
435
|
+
]);
|
|
436
|
+
if (rc !== 0) {
|
|
437
|
+
findings.push(new Finding(INTAKE_GLOB, 0, 'warning', `append-only: git diff failed vs ${ref}`));
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
if (diff.trim() === '') {
|
|
441
|
+
return; // nothing changed, nothing to check
|
|
442
|
+
}
|
|
443
|
+
let currentFile = '';
|
|
444
|
+
let oldPath = '';
|
|
445
|
+
for (const line of diff.split('\n')) {
|
|
446
|
+
if (line.startsWith('diff --git')) {
|
|
447
|
+
const parts = line.split(/\s+/);
|
|
448
|
+
currentFile = parts.length >= 4 ? (parts[parts.length - 1] as string).slice(2) : '';
|
|
449
|
+
oldPath = '';
|
|
450
|
+
} else if (line.startsWith('--- ')) {
|
|
451
|
+
oldPath = line.slice(4).trim();
|
|
452
|
+
} else if (line.startsWith('@@')) {
|
|
453
|
+
// Hunk header: @@ -oldStart,oldCount +newStart,newCount @@
|
|
454
|
+
const m = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/.exec(line);
|
|
455
|
+
if (!m) {
|
|
456
|
+
continue;
|
|
457
|
+
}
|
|
458
|
+
const oldStart = parseInt(m[1] as string, 10);
|
|
459
|
+
const oldCount = parseInt(m[2] ?? '1', 10);
|
|
460
|
+
// Any hunk that removes >0 lines from the old file = in-place edit.
|
|
461
|
+
if (oldCount > 0 && oldPath !== '/dev/null') {
|
|
462
|
+
findings.push(
|
|
463
|
+
new Finding(
|
|
464
|
+
currentFile || INTAKE_GLOB,
|
|
465
|
+
oldStart,
|
|
466
|
+
'error',
|
|
467
|
+
`append-only violation: ${oldCount} existing line(s) removed or modified (ref=${ref})`,
|
|
468
|
+
),
|
|
469
|
+
);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
interface ParsedArgs {
|
|
476
|
+
path: string;
|
|
477
|
+
format: string;
|
|
478
|
+
append_only: boolean;
|
|
479
|
+
base: string | null;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/** Minimal argparse-compatible parser for this script's surface. */
|
|
483
|
+
function _parseArgs(argv: string[]): ParsedArgs {
|
|
484
|
+
const args: ParsedArgs = {
|
|
485
|
+
path: 'agents/memory',
|
|
486
|
+
format: 'text',
|
|
487
|
+
append_only: false,
|
|
488
|
+
base: null,
|
|
489
|
+
};
|
|
490
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
491
|
+
const a = argv[i] as string;
|
|
492
|
+
if (a === '--path') {
|
|
493
|
+
args.path = argv[++i] as string;
|
|
494
|
+
} else if (a.startsWith('--path=')) {
|
|
495
|
+
args.path = a.slice('--path='.length);
|
|
496
|
+
} else if (a === '--format') {
|
|
497
|
+
args.format = _checkChoice(argv[++i] as string, ['text', 'json'], '--format');
|
|
498
|
+
} else if (a.startsWith('--format=')) {
|
|
499
|
+
args.format = _checkChoice(a.slice('--format='.length), ['text', 'json'], '--format');
|
|
500
|
+
} else if (a === '--append-only') {
|
|
501
|
+
args.append_only = true;
|
|
502
|
+
} else if (a === '--base') {
|
|
503
|
+
args.base = argv[++i] as string;
|
|
504
|
+
} else if (a.startsWith('--base=')) {
|
|
505
|
+
args.base = a.slice('--base='.length);
|
|
506
|
+
} else if (a === '-h' || a === '--help') {
|
|
507
|
+
_printUsage();
|
|
508
|
+
process.exit(0);
|
|
509
|
+
} else {
|
|
510
|
+
process.stderr.write(`check_memory: error: unrecognized arguments: ${a}\n`);
|
|
511
|
+
process.exit(2);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
return args;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
function _checkChoice(value: string | undefined, choices: string[], flag: string): string {
|
|
518
|
+
if (value === undefined || !choices.includes(value)) {
|
|
519
|
+
process.stderr.write(
|
|
520
|
+
`check_memory: error: argument ${flag}: invalid choice: '${value ?? ''}' (choose from ${choices.map((c) => `'${c}'`).join(', ')})\n`,
|
|
521
|
+
);
|
|
522
|
+
process.exit(2);
|
|
523
|
+
}
|
|
524
|
+
return value;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
function _printUsage(): void {
|
|
528
|
+
process.stdout.write(
|
|
529
|
+
'usage: check_memory [-h] [--path PATH] [--format {text,json}] [--append-only] [--base BASE]\n',
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
function main(): number {
|
|
534
|
+
const args = _parseArgs(process.argv.slice(2));
|
|
535
|
+
const root = args.path;
|
|
536
|
+
const findings: Finding[] = [];
|
|
537
|
+
if (args.append_only) {
|
|
538
|
+
_checkAppendOnly(args.base, findings);
|
|
539
|
+
// Append-only mode is standalone by design: it inspects git state, not
|
|
540
|
+
// files on disk, and is meant to run as a fast CI gate. Skip YAML
|
|
541
|
+
// validation.
|
|
542
|
+
return _emit(findings, args.format);
|
|
543
|
+
}
|
|
544
|
+
if (!fs.existsSync(root)) {
|
|
545
|
+
if (args.format === 'json') {
|
|
546
|
+
process.stdout.write(`${pyJsonDumps({ findings: [], note: `${root} not found` }, null)}\n`);
|
|
547
|
+
} else {
|
|
548
|
+
process.stdout.write(`ℹ️ ${root} not found — nothing to validate\n`);
|
|
549
|
+
}
|
|
550
|
+
return 0;
|
|
551
|
+
}
|
|
552
|
+
for (const yml of _rglobYmlSorted(root)) {
|
|
553
|
+
_validateFile(yml, findings);
|
|
554
|
+
}
|
|
555
|
+
return _emit(findings, args.format);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/** Mirror `sorted(root.rglob("*.yml"))` — absolute paths, sorted by POSIX string. */
|
|
559
|
+
function _rglobYmlSorted(root: string): string[] {
|
|
560
|
+
const out: string[] = [];
|
|
561
|
+
const rootAbs = path.resolve(root);
|
|
562
|
+
const walk = (dir: string): void => {
|
|
563
|
+
let entries: fs.Dirent[];
|
|
564
|
+
try {
|
|
565
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
566
|
+
} catch {
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
for (const ent of entries) {
|
|
570
|
+
const full = path.join(dir, ent.name);
|
|
571
|
+
if (ent.name.endsWith('.yml')) {
|
|
572
|
+
out.push(full);
|
|
573
|
+
}
|
|
574
|
+
if (ent.isDirectory() || (ent.isSymbolicLink() && _isDirSafe(full))) {
|
|
575
|
+
walk(full);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
};
|
|
579
|
+
walk(rootAbs);
|
|
580
|
+
// Python's Path.rglob result is sorted by the Path objects; sorting the
|
|
581
|
+
// resolved absolute paths by string reproduces that order on POSIX hosts.
|
|
582
|
+
// But the original passes a relative root (e.g. "agents/memory") and
|
|
583
|
+
// emits str(Path) of those relative paths. Reproduce by re-relativizing.
|
|
584
|
+
const cwd = process.cwd();
|
|
585
|
+
const rel = out.map((p) => {
|
|
586
|
+
const r = path.relative(cwd, p);
|
|
587
|
+
// Match str(Path(root) / ...) which keeps the given root form. When the
|
|
588
|
+
// user passed an absolute root, keep absolute.
|
|
589
|
+
return path.isAbsolute(root) ? p : r;
|
|
590
|
+
});
|
|
591
|
+
rel.sort();
|
|
592
|
+
return rel;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
function _isDirSafe(p: string): boolean {
|
|
596
|
+
try {
|
|
597
|
+
return fs.statSync(p).isDirectory();
|
|
598
|
+
} catch {
|
|
599
|
+
return false;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
function _emit(findings: Finding[], fmt: string): number {
|
|
604
|
+
const errors = findings.filter((f) => f.severity === 'error');
|
|
605
|
+
if (fmt === 'json') {
|
|
606
|
+
process.stdout.write(
|
|
607
|
+
`${pyJsonDumps(
|
|
608
|
+
{
|
|
609
|
+
findings: findings.map((f) => ({
|
|
610
|
+
file: f.file,
|
|
611
|
+
line: f.line,
|
|
612
|
+
severity: f.severity,
|
|
613
|
+
message: f.message,
|
|
614
|
+
entry_id: f.entry_id,
|
|
615
|
+
})),
|
|
616
|
+
},
|
|
617
|
+
2,
|
|
618
|
+
)}\n`,
|
|
619
|
+
);
|
|
620
|
+
} else {
|
|
621
|
+
const icon: Record<Severity, string> = { error: '❌', warning: '⚠️', info: 'ℹ️' };
|
|
622
|
+
for (const f of findings) {
|
|
623
|
+
const loc = f.line ? `${f.file}:${f.line}` : f.file;
|
|
624
|
+
const suffix = f.entry_id ? ` [${f.entry_id}]` : '';
|
|
625
|
+
process.stdout.write(` ${icon[f.severity]} ${loc}${suffix} ${f.message}\n`);
|
|
626
|
+
}
|
|
627
|
+
const warnings = findings.filter((f) => f.severity === 'warning').length;
|
|
628
|
+
const infos = findings.filter((f) => f.severity === 'info').length;
|
|
629
|
+
process.stdout.write(`\nSummary: ${errors.length} error(s), ${warnings} warning(s), ${infos} info\n`);
|
|
630
|
+
}
|
|
631
|
+
return errors.length > 0 ? 1 : 0;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
function _isCliEntry(): boolean {
|
|
635
|
+
if (process.argv[1] === undefined) {
|
|
636
|
+
return false;
|
|
637
|
+
}
|
|
638
|
+
const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
|
|
639
|
+
if (import.meta.url === argvUrl) {
|
|
640
|
+
return true;
|
|
641
|
+
}
|
|
642
|
+
// A symlinked invocation (e.g. via an installed `.augment/` projection,
|
|
643
|
+
// or macOS /var → /private/var temp dirs) makes the raw URLs differ:
|
|
644
|
+
// import.meta.url is the resolved real path while argv[1] keeps the
|
|
645
|
+
// symlink path. Compare realpaths so the entry guard still fires
|
|
646
|
+
// (without this the CLI silently no-ops when run through a symlink).
|
|
647
|
+
try {
|
|
648
|
+
const here = fs.realpathSync(fileURLToPath(import.meta.url));
|
|
649
|
+
const argv = fs.realpathSync(path.resolve(process.argv[1]));
|
|
650
|
+
return here === argv;
|
|
651
|
+
} catch {
|
|
652
|
+
return false;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
const _isMain =
|
|
657
|
+
_isCliEntry();
|
|
658
|
+
if (_isMain) {
|
|
659
|
+
process.exit(main());
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
export { main };
|