@event4u/agent-config 6.0.0 → 6.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 +5 -5
- package/CHANGELOG.md +167 -440
- package/README.md +3 -3
- package/dist/agent-src/commands/agent-handoff.md +5 -4
- package/dist/agent-src/commands/agent-status.md +1 -0
- package/dist/agent-src/commands/agents/audit.md +1 -0
- package/dist/agent-src/commands/agents/init.md +3 -0
- package/dist/agent-src/commands/agents/optimize.md +1 -0
- package/dist/agent-src/commands/agents/user/accept.md +1 -0
- package/dist/agent-src/commands/agents/user/init.md +1 -0
- package/dist/agent-src/commands/agents/user/review.md +1 -0
- package/dist/agent-src/commands/agents/user/show.md +1 -0
- package/dist/agent-src/commands/agents/user/update.md +1 -0
- package/dist/agent-src/commands/agents/user.md +1 -0
- package/dist/agent-src/commands/agents.md +1 -0
- package/dist/agent-src/commands/analytics/prune.md +3 -2
- package/dist/agent-src/commands/analytics/show.md +3 -2
- package/dist/agent-src/commands/analytics.md +3 -2
- package/dist/agent-src/commands/analyze-reference-repo.md +1 -0
- package/dist/agent-src/commands/bug-fix.md +1 -0
- package/dist/agent-src/commands/bug-investigate.md +1 -0
- package/dist/agent-src/commands/challenge-me/vision.md +3 -2
- package/dist/agent-src/commands/challenge-me/with-docs.md +3 -2
- package/dist/agent-src/commands/challenge-me.md +3 -2
- package/dist/agent-src/commands/chat-history/import.md +9 -9
- package/dist/agent-src/commands/chat-history.md +32 -30
- package/dist/agent-src/commands/check-current-md.md +1 -0
- package/dist/agent-src/commands/commit/in-chunks.md +1 -0
- package/dist/agent-src/commands/commit.md +1 -0
- package/dist/agent-src/commands/condense.md +1 -0
- package/dist/agent-src/commands/context/create.md +1 -0
- package/dist/agent-src/commands/context/refactor.md +1 -0
- package/dist/agent-src/commands/context.md +1 -0
- package/dist/agent-src/commands/cost-report.md +5 -4
- package/dist/agent-src/commands/council/analysis.md +3 -2
- package/dist/agent-src/commands/council/debate.md +5 -4
- package/dist/agent-src/commands/council/default.md +3 -2
- package/dist/agent-src/commands/council/design.md +3 -2
- package/dist/agent-src/commands/council/optimize.md +3 -2
- package/dist/agent-src/commands/council/pr.md +3 -2
- package/dist/agent-src/commands/council.md +4 -3
- package/dist/agent-src/commands/e2e-heal.md +1 -0
- package/dist/agent-src/commands/e2e-plan.md +1 -0
- package/dist/agent-src/commands/estimate-ticket.md +1 -0
- package/dist/agent-src/commands/feature/dev.md +1 -0
- package/dist/agent-src/commands/feature/explore.md +1 -0
- package/dist/agent-src/commands/feature/plan.md +6 -6
- package/dist/agent-src/commands/feature/refactor.md +1 -0
- package/dist/agent-src/commands/feature/roadmap.md +1 -0
- package/dist/agent-src/commands/feature.md +1 -0
- package/dist/agent-src/commands/fix/ci.md +1 -0
- package/dist/agent-src/commands/fix/portability.md +1 -0
- package/dist/agent-src/commands/fix/pr-comments.md +147 -15
- package/dist/agent-src/commands/fix/refs.md +1 -0
- package/dist/agent-src/commands/fix/seeder.md +1 -0
- package/dist/agent-src/commands/fix.md +8 -8
- package/dist/agent-src/commands/ghostwriter/delete.md +1 -0
- package/dist/agent-src/commands/ghostwriter/fetch.md +1 -0
- package/dist/agent-src/commands/ghostwriter/list.md +1 -0
- package/dist/agent-src/commands/ghostwriter/show.md +1 -0
- package/dist/agent-src/commands/ghostwriter/write.md +1 -0
- package/dist/agent-src/commands/ghostwriter.md +1 -0
- package/dist/agent-src/commands/grill-me.md +3 -2
- package/dist/agent-src/commands/image/analyse.md +1 -0
- package/dist/agent-src/commands/image/create.md +1 -0
- package/dist/agent-src/commands/image/verify.md +1 -0
- package/dist/agent-src/commands/image.md +1 -0
- package/dist/agent-src/commands/implement-ticket.md +1 -0
- package/dist/agent-src/commands/jira-ticket.md +1 -0
- package/dist/agent-src/commands/judge/on-diff.md +1 -0
- package/dist/agent-src/commands/judge/solo.md +1 -0
- package/dist/agent-src/commands/judge/steps.md +1 -0
- package/dist/agent-src/commands/judge.md +1 -0
- package/dist/agent-src/commands/knowledge/cross-repo.md +1 -0
- package/dist/agent-src/commands/knowledge/forget.md +1 -0
- package/dist/agent-src/commands/knowledge/ingest.md +1 -0
- package/dist/agent-src/commands/knowledge/list.md +1 -0
- package/dist/agent-src/commands/knowledge.md +1 -0
- package/dist/agent-src/commands/memory/add.md +8 -6
- package/dist/agent-src/commands/memory/learn-low-impact.md +3 -2
- package/dist/agent-src/commands/memory/load.md +7 -7
- package/dist/agent-src/commands/memory/mine-session.md +39 -12
- package/dist/agent-src/commands/memory/promote.md +3 -2
- package/dist/agent-src/commands/memory/propose.md +7 -6
- package/dist/agent-src/commands/memory.md +3 -2
- package/dist/agent-src/commands/mode.md +1 -0
- package/dist/agent-src/commands/module/create.md +1 -0
- package/dist/agent-src/commands/module/explore.md +1 -0
- package/dist/agent-src/commands/module.md +1 -0
- package/dist/agent-src/commands/optimize/agents-dir.md +1 -0
- package/dist/agent-src/commands/optimize/augmentignore.md +1 -0
- package/dist/agent-src/commands/optimize/rtk.md +1 -0
- package/dist/agent-src/commands/optimize/skills.md +1 -0
- package/dist/agent-src/commands/optimize-prompt.md +1 -0
- package/dist/agent-src/commands/optimize.md +1 -0
- package/dist/agent-src/commands/orchestrate.md +1 -0
- package/dist/agent-src/commands/override/create.md +1 -0
- package/dist/agent-src/commands/override/manage.md +1 -0
- package/dist/agent-src/commands/override.md +1 -0
- package/dist/agent-src/commands/package-reset.md +1 -0
- package/dist/agent-src/commands/package-test.md +1 -0
- package/dist/agent-src/commands/post-as/ghostwriter.md +1 -0
- package/dist/agent-src/commands/post-as/me.md +1 -0
- package/dist/agent-src/commands/post-as.md +1 -0
- package/dist/agent-src/commands/pr/create/description-only.md +1 -0
- package/dist/agent-src/commands/pr/create.md +25 -0
- package/dist/agent-src/commands/prediction-pool.md +1 -0
- package/dist/agent-src/commands/prepare-for-review.md +1 -0
- package/dist/agent-src/commands/profile/activate.md +1 -0
- package/dist/agent-src/commands/profile/deactivate.md +1 -0
- package/dist/agent-src/commands/profile/show.md +1 -0
- package/dist/agent-src/commands/profile.md +1 -0
- package/dist/agent-src/commands/project-analyze.md +1 -0
- package/dist/agent-src/commands/project-health.md +1 -0
- package/dist/agent-src/commands/quality-fix.md +1 -0
- package/dist/agent-src/commands/refine-ticket.md +1 -0
- package/dist/agent-src/commands/research/deep.md +1 -0
- package/dist/agent-src/commands/research/report.md +1 -0
- package/dist/agent-src/commands/research.md +1 -0
- package/dist/agent-src/commands/review-changes.md +1 -0
- package/dist/agent-src/commands/review-routing.md +1 -0
- package/dist/agent-src/commands/roadmap/ai-council.md +1 -0
- package/dist/agent-src/commands/roadmap/create.md +1 -0
- package/dist/agent-src/commands/roadmap/process-full.md +1 -0
- package/dist/agent-src/commands/roadmap/process-phase.md +1 -0
- package/dist/agent-src/commands/roadmap/process-step.md +1 -0
- package/dist/agent-src/commands/roadmap.md +1 -0
- package/dist/agent-src/commands/rule-compliance-audit.md +1 -0
- package/dist/agent-src/commands/security-audit-config.md +84 -0
- package/dist/agent-src/commands/set-cost-profile.md +1 -0
- package/dist/agent-src/commands/skill/preview.md +1 -0
- package/dist/agent-src/commands/skill.md +1 -0
- package/dist/agent-src/commands/skills/discover.md +1 -0
- package/dist/agent-src/commands/skills.md +1 -0
- package/dist/agent-src/commands/sync-agent-settings.md +1 -0
- package/dist/agent-src/commands/sync-gitignore/fix.md +1 -0
- package/dist/agent-src/commands/sync-gitignore.md +1 -0
- package/dist/agent-src/commands/tests/create.md +1 -0
- package/dist/agent-src/commands/tests/execute.md +1 -0
- package/dist/agent-src/commands/tests.md +1 -0
- package/dist/agent-src/commands/threat-model.md +1 -0
- package/dist/agent-src/commands/update-form-request-messages.md +1 -0
- package/dist/agent-src/commands/upstream-contribute.md +1 -0
- package/dist/agent-src/commands/video/from-script.md +1 -0
- package/dist/agent-src/commands/video/from-song.md +1 -0
- package/dist/agent-src/commands/video/scene.md +1 -0
- package/dist/agent-src/commands/video/stitch.md +1 -0
- package/dist/agent-src/commands/video/storyboard.md +1 -0
- package/dist/agent-src/commands/video.md +1 -0
- package/dist/agent-src/commands/work.md +1 -0
- package/dist/agent-src/contexts/augment-infrastructure.md +1 -1
- package/dist/agent-src/contexts/communication/rules-auto/skill-quality-mechanics.md +1 -1
- package/dist/agent-src/contexts/communication/rules-auto/slash-command-routing-policy-mechanics.md +2 -2
- package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +6 -6
- package/dist/agent-src/contexts/contracts/consumer-agents-md-guide.md +2 -2
- package/dist/agent-src/contexts/execution/rdp-gate.md +75 -0
- package/dist/agent-src/contexts/subagent-configuration.md +1 -0
- package/dist/agent-src/personas/advisors/contrarian.md +1 -1
- package/dist/agent-src/personas/advisors/executor.md +1 -1
- package/dist/agent-src/personas/advisors/expansionist.md +1 -1
- package/dist/agent-src/personas/advisors/first-principles.md +1 -1
- package/dist/agent-src/personas/advisors/outsider.md +1 -1
- package/dist/agent-src/rules/autonomous-execution.md +12 -0
- package/dist/agent-src/rules/external-reference-deep-dive.md +1 -1
- package/dist/agent-src/rules/git-history-discipline.md +47 -1
- package/dist/agent-src/rules/improve-before-implement.md +12 -0
- package/dist/agent-src/rules/lethal-trifecta-guard.md +80 -0
- package/dist/agent-src/rules/no-pr-progress-comments.md +3 -4
- package/dist/agent-src/rules/notes-first-reasoning.md +71 -0
- package/dist/agent-src/rules/roadmap-progress-sync.md +48 -31
- package/dist/agent-src/rules/security-sensitive-stop.md +14 -1
- package/dist/agent-src/rules/source-confidentiality.md +97 -0
- package/dist/agent-src/rules/think-before-action.md +9 -1
- package/dist/agent-src/rules/untrusted-input-defense.md +76 -0
- package/dist/agent-src/scripts/archive_completed_roadmaps.py +171 -0
- package/dist/agent-src/skills/adversarial-review/SKILL.md +14 -0
- package/dist/agent-src/skills/agent-security-review/SKILL.md +113 -0
- package/dist/agent-src/skills/agent-security-review/evals/triggers.json +51 -0
- package/dist/agent-src/skills/ai-council/SKILL.md +3 -3
- package/dist/agent-src/skills/async-python-patterns/SKILL.md +1 -1
- package/dist/agent-src/skills/blast-radius-analyzer/SKILL.md +12 -11
- package/dist/agent-src/skills/command-routing/SKILL.md +1 -1
- package/dist/agent-src/skills/complexity-first-planning/SKILL.md +96 -0
- package/dist/agent-src/skills/complexity-first-planning/evals/triggers.json +16 -0
- package/dist/agent-src/skills/copilot-config/SKILL.md +3 -4
- package/dist/agent-src/skills/defense-in-depth/SKILL.md +1 -1
- package/dist/agent-src/skills/developer-like-execution/SKILL.md +5 -4
- package/dist/agent-src/skills/error-handling-patterns/SKILL.md +1 -1
- package/dist/agent-src/skills/feature-planning/SKILL.md +2 -2
- package/dist/agent-src/skills/mcp-builder/SKILL.md +1 -1
- package/dist/agent-src/skills/memory-consolidation/SKILL.md +63 -17
- package/dist/agent-src/skills/prompt-engineering-patterns/SKILL.md +1 -1
- package/dist/agent-src/skills/readme-writing-package/SKILL.md +1 -1
- package/dist/agent-src/skills/reasoning-orchestrator/SKILL.md +119 -0
- package/dist/agent-src/skills/reasoning-orchestrator/evals/triggers.json +16 -0
- package/dist/agent-src/skills/receiving-code-review/SKILL.md +6 -6
- package/dist/agent-src/skills/refine-prompt/SKILL.md +1 -1
- package/dist/agent-src/skills/refine-ticket/SKILL.md +1 -1
- package/dist/agent-src/skills/repomix-packer/SKILL.md +1 -1
- package/dist/agent-src/skills/secrets-management/SKILL.md +1 -1
- package/dist/agent-src/skills/subagent-orchestration/SKILL.md +10 -3
- package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
- package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +1 -1
- package/dist/agent-src/skills/token-optimizer/SKILL.md +1 -1
- package/dist/agent-src/templates/agents/.gitattributes.fragment +0 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +4 -4
- package/dist/agent-src/templates/scripts/check_memory.py +1 -2
- package/dist/agent-src/templates/scripts/check_memory_proposal.py +1 -1
- package/dist/agent-src/templates/scripts/memory_lookup.py +148 -289
- package/dist/agent-src/templates/scripts/memory_report.py +132 -2
- package/dist/agent-src/templates/scripts/memory_signal.py +7 -9
- package/dist/agent-src/templates/scripts/memory_status.py +25 -206
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/memory.py +6 -6
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/_passthrough.py +3 -3
- package/dist/agent-src/templates/scripts/work_engine/scoring/memory_visibility.py +0 -1
- package/dist/cli/agent-config.js +31 -300
- package/dist/cli/agent-config.js.map +1 -1
- package/dist/cli/commands/commands.js +10 -5
- package/dist/cli/commands/commands.js.map +1 -1
- package/dist/cli/discovery/loadManifest.js.map +1 -1
- package/dist/cli/main.js +309 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +645 -342
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +8 -5
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +149 -37
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +61 -36
- package/dist/mcp/registry-manifest.json +4 -4
- package/dist/router.json +1 -1
- package/dist/server/routes/wizard.js +4 -3
- package/dist/server/routes/wizard.js.map +1 -1
- package/dist/server/schemas/settings.js +18 -0
- package/dist/server/schemas/settings.js.map +1 -1
- package/docs/MIGRATION.md +1 -1
- package/docs/adrs/cost/0001-hard-stop-hook.md +5 -5
- package/docs/adrs/memory/0001-consumer-side-snapshot.md +15 -7
- package/docs/adrs/memory/README.md +6 -5
- package/docs/adrs/router/0001-three-tier-routing.md +2 -2
- package/docs/adrs/schema/0001-json-schema-frontmatter.md +2 -2
- package/docs/adrs/smoke/0001-per-tier-smoke-scripts.md +5 -5
- package/docs/adrs/telegraph/0001-default-off-until-bench.md +3 -3
- package/docs/architecture.md +9 -9
- package/docs/archive/CHANGELOG-pre-2.2.0.md +30 -30
- package/docs/archive/CHANGELOG-pre-2.25.0.md +1 -1
- package/docs/archive/CHANGELOG-pre-4.5.0.md +1 -1
- package/docs/archive/CHANGELOG-pre-6.0.0.md +473 -0
- package/docs/benchmark.md +54 -53
- package/docs/benchmarks.md +2 -2
- package/docs/case-studies/{frontend-design-vs-ui-ux-pro-max.md → frontend-design-positioning.md} +4 -4
- package/docs/catalog.md +20 -13
- package/docs/command-flows.md +90 -92
- package/docs/contracts/adr-layout.md +2 -3
- package/docs/contracts/adr-level-6-productization.md +1 -1
- package/docs/contracts/ai-council-config.md +42 -7
- package/docs/contracts/command-clusters.md +1 -1
- package/docs/contracts/cost-enforcement.md +1 -1
- package/docs/contracts/cost-summary-schema.md +1 -1
- package/docs/contracts/daily-workspace.md +1 -0
- package/docs/contracts/discovery-manifest.schema.json +4 -2
- package/docs/contracts/explain-modes.md +1 -1
- package/docs/contracts/implement-ticket-flow.md +6 -7
- package/docs/contracts/mcp-tool-inventory.md +10 -10
- package/docs/contracts/measurement-baseline.md +1 -1
- package/docs/contracts/memory-visibility-v1.md +1 -5
- package/docs/contracts/namespace.md +1 -1
- package/docs/contracts/persona-schema.md +1 -1
- package/docs/contracts/rule-interactions.md +1 -1
- package/docs/contracts/smoke-contracts.md +1 -1
- package/docs/contracts/universal-skills.md +0 -1
- package/docs/contracts/workspace-boundary.md +84 -0
- package/docs/customization.md +3 -3
- package/docs/decisions/ADR-009-event4u-namespace.md +1 -1
- package/docs/decisions/ADR-013-discovery-frontmatter-contract.md +1 -1
- package/docs/decisions/ADR-026-explain-mode-translation.md +1 -1
- package/docs/decisions/ADR-088-no-external-runtime-federation.md +26 -27
- package/docs/decisions/ADR-090-visibility-command-frontmatter-field.md +95 -0
- package/docs/decisions/ADR-091-split-meta-capability-packs.md +113 -0
- package/docs/decisions/ADR-092-defer-command-tier-alias-removal.md +93 -0
- package/docs/decisions/ADR-093-ai-council-config-user-global.md +111 -0
- package/docs/decisions/ADR-094-agent-memory-layer-removal.md +94 -0
- package/docs/decisions/ADR-095-workspace-boundary-contract.md +108 -0
- package/docs/decisions/INDEX.md +6 -0
- package/docs/development.md +5 -7
- package/docs/getting-started.md +4 -4
- package/docs/guidelines/agent-infra/5w2h-analysis.md +1 -1
- package/docs/guidelines/agent-infra/comparison-matrix.md +1 -1
- package/docs/guidelines/agent-infra/corpus-grounding-authoring.md +1 -1
- package/docs/guidelines/agent-infra/critical-thinking.md +1 -1
- package/docs/guidelines/agent-infra/engineering-memory-data-format.md +1 -5
- package/docs/guidelines/agent-infra/first-principles.md +1 -1
- package/docs/guidelines/agent-infra/frontier-reasoning-operating-profile.md +164 -0
- package/docs/guidelines/agent-infra/inversion-thinking.md +1 -1
- package/docs/guidelines/agent-infra/ios-simulator-guide.md +9 -14
- package/docs/guidelines/agent-infra/mcp-request-signing.md +19 -22
- package/docs/guidelines/agent-infra/memory-access.md +25 -31
- package/docs/guidelines/agent-infra/mental-models.md +1 -1
- package/docs/guidelines/agent-infra/model-recommendation.md +29 -0
- package/docs/guidelines/agent-infra/scqa-framework.md +3 -3
- package/docs/guidelines/agent-infra/security-lint-containment.md +81 -0
- package/docs/guidelines/agent-infra/six-hats.md +1 -1
- package/docs/guidelines/agent-infra/systems-thinking.md +1 -1
- package/docs/guidelines/agent-infra/untrusted-input-spotlighting.md +72 -0
- package/docs/installation.md +1 -1
- package/docs/mcp.md +2 -2
- package/docs/parity/{bench-ruflo.json → bench-external.json} +10 -10
- package/docs/parity/{ruflo.md → external-runtime.md} +9 -9
- package/docs/quality.md +3 -3
- package/docs/safety.md +3 -3
- package/docs/skills-catalog.md +4 -1
- package/llms.txt +3 -0
- package/package.json +1 -1
- package/src/config/agent-settings.template.yml +65 -3
- package/src/config/discovery/packs.yml +29 -0
- package/src/config/discovery/workspaces.yml +3 -1
- package/src/config/gitignore-block.txt +6 -0
- package/src/scripts/__pycache__/validate_frontmatter.cpython-312.pyc +0 -0
- package/src/scripts/_cli/cmd_doctor.py +99 -13
- package/src/scripts/_lib/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/scripts/_lib/__pycache__/agent_src.cpython-312.pyc +0 -0
- package/src/scripts/_lib/bench_ab_scoring_v2.py +227 -0
- package/src/scripts/_lib/global_deploy_inventory.py +39 -9
- package/src/scripts/_lib/link_crypto.py +206 -0
- package/src/scripts/_lib/security_lint.py +228 -0
- package/src/scripts/ai_council/clients.py +2 -2
- package/src/scripts/ai_council/config.py +55 -0
- package/src/scripts/audit_adr_coverage.py +0 -2
- package/src/scripts/audit_command_surface.py +18 -5
- package/src/scripts/audit_mcp_tools.py +2 -2
- package/src/scripts/audit_skill_descriptions.py +2 -2
- package/src/scripts/bench_ab_clone.py +62 -12
- package/src/scripts/bench_ab_task_runner.py +475 -30
- package/src/scripts/bench_ab_v2_run.py +247 -0
- package/src/scripts/bench_ab_v2_stats.py +347 -0
- package/src/scripts/bench_run.py +1 -1
- package/src/scripts/build_discovery_manifest.py +10 -0
- package/src/scripts/check_bite_sized_granularity.py +1 -2
- package/src/scripts/check_memory.py +49 -63
- package/src/scripts/check_memory_proposal.py +1 -1
- package/src/scripts/check_no_external_sources.py +101 -0
- package/src/scripts/check_references.py +2 -0
- package/src/scripts/cost_by_conversation.py +1 -1
- package/src/scripts/council_cli.py +28 -14
- package/src/scripts/external_sources_denylist.json +91 -0
- package/src/scripts/hook_manifest.yaml +14 -6
- package/src/scripts/injection_scan_hook.py +145 -0
- package/src/scripts/install-hooks.sh +11 -0
- package/src/scripts/install.py +88 -13
- package/src/scripts/lint_agent_security.py +112 -0
- package/src/scripts/lint_bench_ab.py +5 -4
- package/src/scripts/lint_command_tiers.py +63 -22
- package/src/scripts/lint_discovery_vocabulary.py +2 -0
- package/src/scripts/lint_empty_roadmaps.py +80 -0
- package/src/scripts/lint_hidden_unicode.py +132 -0
- package/src/scripts/lint_instruction_smuggling.py +107 -0
- package/src/scripts/lint_marketplace.py +1 -1
- package/src/scripts/lint_mcp_config_security.py +124 -0
- package/src/scripts/lint_skill_frontmatter_safety.py +144 -0
- package/src/scripts/lint_workspace_boundary.py +122 -0
- package/src/scripts/mcp_server/consumer_tool_catalog.json +2 -3
- package/src/scripts/mcp_server/tools.py +8 -32
- package/src/scripts/memory_lookup.py +27 -296
- package/src/scripts/memory_report.py +1 -23
- package/src/scripts/memory_signal.py +6 -53
- package/src/scripts/memory_status.py +25 -206
- package/src/scripts/mine_session.py +118 -41
- package/src/scripts/pack_dependency_allowlist.json +2 -2
- package/src/scripts/render_benchmark_md.py +141 -52
- package/src/scripts/schemas/command.schema.json +6 -1
- package/src/scripts/security_audit_config.py +153 -0
- package/dist/agent-src/commands/chat-history/learn.md +0 -184
- package/dist/agent-src/commands/chat-history/show.md +0 -113
- package/dist/agent-src/commands/fix/pr-bot-comments.md +0 -157
- package/dist/agent-src/commands/fix/pr-developer-comments.md +0 -163
- package/dist/agent-src/templates/agents/memory/architecture-decisions.example.yml +0 -95
- package/docs/contracts/agent-memory-contract.md +0 -159
|
@@ -79,6 +79,16 @@ def safe_load(path: Path | None) -> dict:
|
|
|
79
79
|
return {}
|
|
80
80
|
|
|
81
81
|
|
|
82
|
+
def latest_trackb_with_rdp() -> dict:
|
|
83
|
+
"""Latest Track B report for the third condition (`with-rdp`), or {}."""
|
|
84
|
+
reports = sorted(REPORTS_DIR.glob("*-ab-trackb-with-rdp.json"))
|
|
85
|
+
return safe_load(reports[-1]) if reports else {}
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _delta_pct(a: float | None, b: float | None) -> str:
|
|
89
|
+
return fmt_pct((a or 0) - (b or 0))
|
|
90
|
+
|
|
91
|
+
|
|
82
92
|
def fmt_pct(value: float | None) -> str:
|
|
83
93
|
if value is None:
|
|
84
94
|
return "—"
|
|
@@ -91,33 +101,79 @@ def fmt_num(value: float | None, places: int = 2) -> str:
|
|
|
91
101
|
return f"{value:.{places}f}"
|
|
92
102
|
|
|
93
103
|
|
|
94
|
-
def
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
104
|
+
def fmt_int(value: float | None) -> str:
|
|
105
|
+
if value is None:
|
|
106
|
+
return "—"
|
|
107
|
+
return f"{int(value):,}"
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _delta_num(a: float | None, b: float | None, places: int = 3) -> str:
|
|
111
|
+
d = (a or 0) - (b or 0)
|
|
112
|
+
return f"{d:+.{places}f}"
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def render_headline(track_a: dict, track_b: dict, track_b_rdp: dict) -> str:
|
|
116
|
+
wo = (track_b.get("without") or {}).get("results", {})
|
|
117
|
+
wi = (track_b.get("with") or {}).get("results", {})
|
|
118
|
+
rd = (track_b_rdp or {}).get("results", {})
|
|
119
|
+
mode = wi.get("mode") or wo.get("mode") or rd.get("mode") or "—"
|
|
120
|
+
total = wi.get("total") or wo.get("total") or rd.get("total") or 0
|
|
121
|
+
dry = mode != "live"
|
|
103
122
|
lines = [
|
|
104
123
|
"## Headline",
|
|
105
124
|
"",
|
|
106
|
-
"> **
|
|
107
|
-
"
|
|
108
|
-
"
|
|
125
|
+
"> **Lift of agent-config on the host model — NOT a model-vs-model benchmark.** "
|
|
126
|
+
"This measures what the package + the RDP reasoning lift do to a *fixed* host "
|
|
127
|
+
"model on a neutral fixture; it is not comparable to public SWE-bench / "
|
|
128
|
+
"Fable-5 model scores (different question entirely).",
|
|
129
|
+
"",
|
|
130
|
+
]
|
|
131
|
+
if dry:
|
|
132
|
+
lines += [
|
|
133
|
+
"> ⚠️ **DRY RUN — no model calls were made; every cell is 0/N by construction.** "
|
|
134
|
+
"This shows the *shape* the real numbers will fill. Run `task bench:ab:live` "
|
|
135
|
+
"(billable) for actual results.",
|
|
136
|
+
"",
|
|
137
|
+
]
|
|
138
|
+
err_bits = []
|
|
139
|
+
for name, res in (("without", wo), ("with", wi), ("with-rdp", rd)):
|
|
140
|
+
e = res.get("errored") or 0
|
|
141
|
+
if e:
|
|
142
|
+
err_bits.append(f"{name}: {e}/{res.get('total', 0)}")
|
|
143
|
+
lines += [
|
|
144
|
+
f"> ⚠️ **Low statistical power: corpus N={total} (< 40).** Directional only; "
|
|
145
|
+
"per-cell N is shown below. The `long × mechanical` cell is intentionally "
|
|
146
|
+
"empty (documented hole, not an error).",
|
|
147
|
+
"",
|
|
148
|
+
]
|
|
149
|
+
if err_bits:
|
|
150
|
+
lines += [
|
|
151
|
+
"> ⚠️ **Some tasks errored (rate-limit / budget-cap / timeout) and are "
|
|
152
|
+
"excluded from the hit-rate** — they are NOT content failures. Errored "
|
|
153
|
+
f"counts — {'; '.join(err_bits)}. Hit-rate is computed over completed tasks only.",
|
|
154
|
+
"",
|
|
155
|
+
]
|
|
156
|
+
lines += [
|
|
157
|
+
"_Host model + inference config (temp / top-p / max-tokens) are recorded in "
|
|
158
|
+
"Methodology and must be cited with any quoted number._",
|
|
159
|
+
"",
|
|
160
|
+
"### Table 1 — Package value (without → with)",
|
|
161
|
+
"",
|
|
162
|
+
"| Metric | without | with | delta |",
|
|
163
|
+
"|---|---|---|---|",
|
|
164
|
+
f"| Success / hit-rate | {fmt_pct(wo.get('completion_rate'))} | {fmt_pct(wi.get('completion_rate'))} | {_delta_pct(wi.get('completion_rate'), wo.get('completion_rate'))} |",
|
|
165
|
+
f"| Mean wall-time | {fmt_num(wo.get('mean_wall_time'))}s | {fmt_num(wi.get('mean_wall_time'))}s | {fmt_num((wi.get('mean_wall_time') or 0) - (wo.get('mean_wall_time') or 0))}s |",
|
|
166
|
+
f"| Ask-vs-act ratio | {fmt_num(wo.get('ask_vs_act_ratio'), 3)} | {fmt_num(wi.get('ask_vs_act_ratio'), 3)} | {_delta_num(wi.get('ask_vs_act_ratio'), wo.get('ask_vs_act_ratio'))} |",
|
|
167
|
+
f"| Total tokens | {fmt_int(wo.get('total_tokens'))} | {fmt_int(wi.get('total_tokens'))} | {fmt_int((wi.get('total_tokens') or 0) - (wo.get('total_tokens') or 0))} |",
|
|
168
|
+
"",
|
|
169
|
+
"### Table 2 — RDP reasoning lift (with → with-rdp)",
|
|
109
170
|
"",
|
|
110
|
-
"| Metric | with |
|
|
171
|
+
"| Metric | with | with-rdp | delta |",
|
|
111
172
|
"|---|---|---|---|",
|
|
112
|
-
f"|
|
|
113
|
-
f"{
|
|
114
|
-
f"|
|
|
115
|
-
f"{
|
|
116
|
-
f"| Track B mean wall-time | {fmt_num(b_results.get('mean_wall_time'))}s "
|
|
117
|
-
f"| {fmt_num(b_without.get('mean_wall_time'))}s | "
|
|
118
|
-
f"{fmt_num((b_results.get('mean_wall_time') or 0) - (b_without.get('mean_wall_time') or 0))}s |",
|
|
119
|
-
f"| Track B ask-vs-act ratio | {fmt_num(b_results.get('ask_vs_act_ratio'), 3)} "
|
|
120
|
-
f"| {fmt_num(b_without.get('ask_vs_act_ratio'), 3)} | — |",
|
|
173
|
+
f"| Success / hit-rate | {fmt_pct(wi.get('completion_rate'))} | {fmt_pct(rd.get('completion_rate'))} | {_delta_pct(rd.get('completion_rate'), wi.get('completion_rate'))} |",
|
|
174
|
+
f"| Mean wall-time | {fmt_num(wi.get('mean_wall_time'))}s | {fmt_num(rd.get('mean_wall_time'))}s | {fmt_num((rd.get('mean_wall_time') or 0) - (wi.get('mean_wall_time') or 0))}s |",
|
|
175
|
+
f"| Ask-vs-act ratio | {fmt_num(wi.get('ask_vs_act_ratio'), 3)} | {fmt_num(rd.get('ask_vs_act_ratio'), 3)} | {_delta_num(rd.get('ask_vs_act_ratio'), wi.get('ask_vs_act_ratio'))} |",
|
|
176
|
+
f"| Total tokens | {fmt_int(wi.get('total_tokens'))} | {fmt_int(rd.get('total_tokens'))} | {fmt_int((rd.get('total_tokens') or 0) - (wi.get('total_tokens') or 0))} |",
|
|
121
177
|
"",
|
|
122
178
|
]
|
|
123
179
|
return "\n".join(lines)
|
|
@@ -153,37 +209,68 @@ def render_track_a(track_a: dict) -> str:
|
|
|
153
209
|
return "\n".join(lines)
|
|
154
210
|
|
|
155
211
|
|
|
156
|
-
def render_track_b(track_b: dict) -> str:
|
|
212
|
+
def render_track_b(track_b: dict, track_b_rdp: dict) -> str:
|
|
157
213
|
lines = ["## Track B — Task completion", ""]
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
214
|
+
wo = (track_b.get("without") or {}).get("results", {})
|
|
215
|
+
wi = (track_b.get("with") or {}).get("results", {})
|
|
216
|
+
rd = (track_b_rdp or {}).get("results", {})
|
|
217
|
+
mode = wi.get("mode") or wo.get("mode") or rd.get("mode") or "—"
|
|
161
218
|
lines.append(f"- Mode: `{mode}`")
|
|
162
|
-
if not
|
|
163
|
-
lines.
|
|
164
|
-
lines.append("_No Track B reports yet. Run `task bench:ab:track-b`._")
|
|
165
|
-
lines.append("")
|
|
219
|
+
if not (wo or wi or rd):
|
|
220
|
+
lines += ["", "_No Track B reports yet. Run `task bench:ab:track-b`._", ""]
|
|
166
221
|
return "\n".join(lines)
|
|
167
|
-
lines
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
for
|
|
183
|
-
|
|
184
|
-
|
|
222
|
+
lines += [
|
|
223
|
+
f"- without → **{fmt_pct(wo.get('completion_rate'))}** ({wo.get('passed', 0)}/{wo.get('total', 0)})",
|
|
224
|
+
f"- with → **{fmt_pct(wi.get('completion_rate'))}** ({wi.get('passed', 0)}/{wi.get('total', 0)})",
|
|
225
|
+
f"- with-rdp → **{fmt_pct(rd.get('completion_rate'))}** ({rd.get('passed', 0)}/{rd.get('total', 0)})",
|
|
226
|
+
"",
|
|
227
|
+
"### Per 2×2 cell (success-rate per condition; per-cell N in parens)",
|
|
228
|
+
"",
|
|
229
|
+
"| Cell (duration × cognitive) | N | without | with | with-rdp |",
|
|
230
|
+
"|---|---|---|---|---|",
|
|
231
|
+
]
|
|
232
|
+
wo_c, wi_c, rd_c = wo.get("per_cell", {}), wi.get("per_cell", {}), rd.get("per_cell", {})
|
|
233
|
+
cells = sorted(set(wo_c) | set(wi_c) | set(rd_c)) or [
|
|
234
|
+
"short/reasoning-heavy", "short/mechanical",
|
|
235
|
+
"long/reasoning-heavy", "long/mechanical",
|
|
236
|
+
]
|
|
237
|
+
for cell in cells:
|
|
238
|
+
n = (wi_c.get(cell) or wo_c.get(cell) or rd_c.get(cell) or {}).get("total", 0)
|
|
239
|
+
lines.append(
|
|
240
|
+
f"| {cell} | {n} | {fmt_pct(wo_c.get(cell, {}).get('completion_rate'))} "
|
|
241
|
+
f"| {fmt_pct(wi_c.get(cell, {}).get('completion_rate'))} "
|
|
242
|
+
f"| {fmt_pct(rd_c.get(cell, {}).get('completion_rate'))} |"
|
|
243
|
+
)
|
|
244
|
+
lines += [
|
|
245
|
+
"",
|
|
246
|
+
"### Per 2×2 cell — mean tokens per condition",
|
|
247
|
+
"",
|
|
248
|
+
"| Cell (duration × cognitive) | without | with | with-rdp |",
|
|
249
|
+
"|---|---|---|---|",
|
|
250
|
+
]
|
|
251
|
+
for cell in cells:
|
|
252
|
+
lines.append(
|
|
253
|
+
f"| {cell} | {fmt_int(wo_c.get(cell, {}).get('mean_tokens'))} "
|
|
254
|
+
f"| {fmt_int(wi_c.get(cell, {}).get('mean_tokens'))} "
|
|
255
|
+
f"| {fmt_int(rd_c.get(cell, {}).get('mean_tokens'))} |"
|
|
256
|
+
)
|
|
257
|
+
lines += [
|
|
258
|
+
"",
|
|
259
|
+
"_`short × mechanical` mean-tokens across conditions answers \"are short "
|
|
260
|
+
"tasks more expensive?\"; `long × reasoning-heavy` answers \"do long tasks "
|
|
261
|
+
"get cheaper / better?\"._",
|
|
262
|
+
"",
|
|
263
|
+
"### Per category",
|
|
264
|
+
"",
|
|
265
|
+
"| Category | without | with | with-rdp |",
|
|
266
|
+
"|---|---|---|---|",
|
|
267
|
+
]
|
|
268
|
+
wo_cat, wi_cat, rd_cat = wo.get("per_category", {}), wi.get("per_category", {}), rd.get("per_category", {})
|
|
269
|
+
for cat in sorted(set(wo_cat) | set(wi_cat) | set(rd_cat)):
|
|
185
270
|
lines.append(
|
|
186
|
-
f"| {cat} | {fmt_pct(
|
|
271
|
+
f"| {cat} | {fmt_pct(wo_cat.get(cat, {}).get('completion_rate'))} "
|
|
272
|
+
f"| {fmt_pct(wi_cat.get(cat, {}).get('completion_rate'))} "
|
|
273
|
+
f"| {fmt_pct(rd_cat.get(cat, {}).get('completion_rate'))} |"
|
|
187
274
|
)
|
|
188
275
|
lines.append("")
|
|
189
276
|
return "\n".join(lines)
|
|
@@ -265,8 +352,10 @@ def render(quiet: bool = False) -> int:
|
|
|
265
352
|
b_with, b_without = latest_pair("ab-trackb")
|
|
266
353
|
track_a = {"with": safe_load(a_with), "without": safe_load(a_without)}
|
|
267
354
|
track_b = {"with": safe_load(b_with), "without": safe_load(b_without)}
|
|
355
|
+
track_b_rdp = latest_trackb_with_rdp()
|
|
268
356
|
have_data = bool(
|
|
269
|
-
track_a["with"] or track_a["without"]
|
|
357
|
+
track_a["with"] or track_a["without"]
|
|
358
|
+
or track_b["with"] or track_b["without"] or track_b_rdp
|
|
270
359
|
)
|
|
271
360
|
if not have_data:
|
|
272
361
|
OUT_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
@@ -282,9 +371,9 @@ def render(quiet: bool = False) -> int:
|
|
|
282
371
|
"> Generated by `scripts/render_benchmark_md.py`. Source of truth: "
|
|
283
372
|
"`internal/bench/reports/ab/`. Re-render anytime with `task bench:ab:diff`.",
|
|
284
373
|
"",
|
|
285
|
-
render_headline(track_a, track_b),
|
|
374
|
+
render_headline(track_a, track_b, track_b_rdp),
|
|
286
375
|
render_track_a(track_a),
|
|
287
|
-
render_track_b(track_b),
|
|
376
|
+
render_track_b(track_b, track_b_rdp),
|
|
288
377
|
render_methodology(track_a, track_b),
|
|
289
378
|
render_history(),
|
|
290
379
|
]
|
|
@@ -16,7 +16,12 @@
|
|
|
16
16
|
"tier": {
|
|
17
17
|
"type": "integer",
|
|
18
18
|
"enum": [0, 1, 2],
|
|
19
|
-
"description": "Command-surface tier per docs/contracts/command-surface-tiers.md. 0 = daily-driver (rendered in default `./agent-config --help`), 1 = power-user (rendered with `--tier=1`), 2 = maintenance/internal (rendered only with `--tier=all`). Default for new commands is 2 — promotion is gated by ADR criteria, never by author preference."
|
|
19
|
+
"description": "Command-surface tier per docs/contracts/command-surface-tiers.md. 0 = daily-driver (rendered in default `./agent-config --help`), 1 = power-user (rendered with `--tier=1`), 2 = maintenance/internal (rendered only with `--tier=all`). Default for new commands is 2 — promotion is gated by ADR criteria, never by author preference. BACK-COMPAT ALIAS since ADR-090: `visibility:` is the named source of truth (visible↔0, advanced↔1, internal↔2); `tier:` is retained as a derived integer alias and dual-emitted in the discovery manifest during the deprecation window. When both are present they MUST agree (enforced by lint_command_tiers.py)."
|
|
20
|
+
},
|
|
21
|
+
"visibility": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"enum": ["visible", "advanced", "internal"],
|
|
24
|
+
"description": "Command-surface visibility (ADR-090) — the NAMED source of truth that supersedes the integer `tier:` proxy. `visible` = daily-driver (default `./agent-config --help`, ↔ tier 0), `advanced` = power-user (`--tier=1`, ↔ tier 1), `internal` = maintenance/hidden (`--tier=all` only, ↔ tier 2). Read by the surface classifier (commands ls/explain), the per-pack visible-command budget audit, and the discovery-manifest builder, each preferring `visibility:` and falling back to `tier:`. Default for new commands is `internal`; promotion is gated by ADR criteria per docs/contracts/command-surface-tiers.md."
|
|
20
25
|
},
|
|
21
26
|
"description": {
|
|
22
27
|
"type": "string",
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""P3.1 — consumer-facing agent-config security audit (road-to-security-pillar.md).
|
|
3
|
+
|
|
4
|
+
Points the Phase-1 detection logic at a *consumer's assembled* agent config —
|
|
5
|
+
instruction files (CLAUDE.md, AGENTS.md, .cursor/rules, copilot-instructions),
|
|
6
|
+
MCP configs (.mcp.json, .cursor/mcp.json, claude_desktop_config.json), settings
|
|
7
|
+
+ hooks (.claude/settings.json), and installed skills — and emits an A–F score
|
|
8
|
+
with a per-category breakdown mapped to the OWASP Top 10 for Agentic
|
|
9
|
+
Applications (ASI).
|
|
10
|
+
|
|
11
|
+
Detection is the same library as the self-audit gate (so there is one source of
|
|
12
|
+
truth for the patterns) under the same false-positive containment convention.
|
|
13
|
+
This is decision-support, not a guarantee: detection is probabilistic.
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
python3 src/scripts/security_audit_config.py [--root DIR] [--json]
|
|
17
|
+
"""
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import argparse
|
|
21
|
+
import sys
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
|
|
24
|
+
HERE = Path(__file__).resolve().parent
|
|
25
|
+
sys.path.insert(0, str(HERE))
|
|
26
|
+
from _lib import security_lint as sl # noqa: E402
|
|
27
|
+
import lint_hidden_unicode as p11 # noqa: E402
|
|
28
|
+
import lint_instruction_smuggling as p12 # noqa: E402
|
|
29
|
+
import lint_mcp_config_security as p13 # noqa: E402
|
|
30
|
+
import lint_skill_frontmatter_safety as p14 # noqa: E402
|
|
31
|
+
|
|
32
|
+
# Consumer config surfaces (globs relative to --root).
|
|
33
|
+
SURFACES = [
|
|
34
|
+
"CLAUDE.md", "AGENTS.md", "GEMINI.md", ".clinerules", ".windsurfrules",
|
|
35
|
+
".github/copilot-instructions.md",
|
|
36
|
+
".cursor/rules/**/*", ".cursorrules",
|
|
37
|
+
".claude/skills/**/SKILL.md", ".claude/commands/**/*.md",
|
|
38
|
+
".claude/settings.json", ".claude/settings.local.json",
|
|
39
|
+
".mcp.json", ".cursor/mcp.json", "claude_desktop_config.json",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
# check id → (category, OWASP-ASI tag)
|
|
43
|
+
CATEGORY = {
|
|
44
|
+
"hidden-unicode": ("Agents/Rules", "ASI01 Goal Hijack"),
|
|
45
|
+
"instruction-smuggling": ("Agents/Rules", "ASI01 Goal Hijack"),
|
|
46
|
+
"mcp-config-security": ("MCP", "ASI04 Supply Chain"),
|
|
47
|
+
"dangerous-frontmatter": ("Permissions", "ASI03 Privilege Abuse"),
|
|
48
|
+
}
|
|
49
|
+
SECRET_HINT = "secret" # mcp finding mentioning a secret → Secrets category
|
|
50
|
+
CATEGORIES = ["Secrets", "Permissions", "Hooks", "MCP", "Agents/Rules"]
|
|
51
|
+
|
|
52
|
+
# Deduction per finding (full weight); weighted findings scale by their weight.
|
|
53
|
+
_DEDUCT = {"HIGH": 25.0, "MED": 5.0, "LOW": 2.0}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _grade(score: float) -> str:
|
|
57
|
+
return ("A" if score >= 90 else "B" if score >= 80 else "C" if score >= 70
|
|
58
|
+
else "D" if score >= 60 else "F")
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _category(f) -> str:
|
|
62
|
+
if f.check == "mcp-config-security" and SECRET_HINT in f.message.lower():
|
|
63
|
+
return "Secrets"
|
|
64
|
+
return CATEGORY.get(f.check, ("Agents/Rules", ""))[0]
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _iter_targets(root: Path):
|
|
68
|
+
seen = set()
|
|
69
|
+
for pattern in SURFACES:
|
|
70
|
+
for p in root.glob(pattern):
|
|
71
|
+
if p.is_file() and p not in seen:
|
|
72
|
+
seen.add(p)
|
|
73
|
+
yield p
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def audit(root: Path) -> dict:
|
|
77
|
+
findings = []
|
|
78
|
+
for p in _iter_targets(root):
|
|
79
|
+
try:
|
|
80
|
+
sf = sl.scan_path(p, root)
|
|
81
|
+
except (UnicodeDecodeError, OSError):
|
|
82
|
+
continue
|
|
83
|
+
for mod in (p11, p12, p13, p14):
|
|
84
|
+
try:
|
|
85
|
+
findings.extend(mod._scan(sf))
|
|
86
|
+
except Exception:
|
|
87
|
+
pass
|
|
88
|
+
|
|
89
|
+
per_cat = {c: 100.0 for c in CATEGORIES}
|
|
90
|
+
cat_findings = {c: [] for c in CATEGORIES}
|
|
91
|
+
for f in findings:
|
|
92
|
+
cat = _category(f)
|
|
93
|
+
per_cat[cat] -= _DEDUCT.get(f.severity, 2.0) * float(f.weight)
|
|
94
|
+
cat_findings[cat].append(f)
|
|
95
|
+
for c in per_cat:
|
|
96
|
+
per_cat[c] = max(0.0, per_cat[c])
|
|
97
|
+
|
|
98
|
+
overall = round(sum(per_cat.values()) / len(CATEGORIES), 1)
|
|
99
|
+
return {
|
|
100
|
+
"root": str(root),
|
|
101
|
+
"overall_score": overall,
|
|
102
|
+
"overall_grade": _grade(overall),
|
|
103
|
+
"categories": {
|
|
104
|
+
c: {
|
|
105
|
+
"score": round(per_cat[c], 1),
|
|
106
|
+
"grade": _grade(per_cat[c]),
|
|
107
|
+
"owasp": next((CATEGORY[fl.check][1] for fl in cat_findings[c]
|
|
108
|
+
if fl.check in CATEGORY), ""),
|
|
109
|
+
"findings": [
|
|
110
|
+
{"path": fl.path, "line": fl.line, "check": fl.check,
|
|
111
|
+
"severity": fl.severity, "message": fl.message,
|
|
112
|
+
"weight": fl.weight}
|
|
113
|
+
for fl in cat_findings[c]
|
|
114
|
+
],
|
|
115
|
+
}
|
|
116
|
+
for c in CATEGORIES
|
|
117
|
+
},
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _print(report: dict) -> None:
|
|
122
|
+
print(f"Agent-config security audit — {report['root']}")
|
|
123
|
+
print(f"Overall: {report['overall_grade']} ({report['overall_score']}/100)\n")
|
|
124
|
+
for c in CATEGORIES:
|
|
125
|
+
cat = report["categories"][c]
|
|
126
|
+
tag = f" · {cat['owasp']}" if cat["owasp"] else ""
|
|
127
|
+
print(f" {cat['grade']} {c:<12} {cat['score']:>5}/100{tag}")
|
|
128
|
+
for f in cat["findings"]:
|
|
129
|
+
loc = f"{f['path']}:{f['line']}" if f["line"] else f["path"]
|
|
130
|
+
w = "" if f["weight"] >= 1.0 else f" (weight {f['weight']:g})"
|
|
131
|
+
print(f" [{f['severity']}] {loc}{w}: {f['message']}")
|
|
132
|
+
print("\n> Decision support, not a guarantee — detection is probabilistic. "
|
|
133
|
+
"Pair with /threat-model and judge-security-auditor for a deep pass.")
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def main() -> int:
|
|
137
|
+
ap = argparse.ArgumentParser(description=__doc__, epilog=sl.GUIDELINE_EPILOG)
|
|
138
|
+
ap.add_argument("--root", default=".", help="consumer repo root to audit (default: cwd)")
|
|
139
|
+
ap.add_argument("--json", action="store_true")
|
|
140
|
+
args = ap.parse_args()
|
|
141
|
+
|
|
142
|
+
report = audit(Path(args.root))
|
|
143
|
+
if args.json:
|
|
144
|
+
import json
|
|
145
|
+
print(json.dumps(report, indent=2))
|
|
146
|
+
else:
|
|
147
|
+
_print(report)
|
|
148
|
+
# Audit is advisory: always exit 0 (it informs, it does not gate the consumer).
|
|
149
|
+
return 0
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
if __name__ == "__main__":
|
|
153
|
+
raise SystemExit(main())
|
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
model_tier: medium
|
|
3
|
-
name: chat-history-learn
|
|
4
|
-
pack: meta
|
|
5
|
-
tier: 2
|
|
6
|
-
cluster: chat-history
|
|
7
|
-
sub: learn
|
|
8
|
-
skills: [learning-to-rule-or-skill]
|
|
9
|
-
description: Pick a prior chat-history session and mine it for project-improving learnings — runs learning-to-rule-or-skill on the picked session, drafts proposal(s) under agents/proposals/
|
|
10
|
-
suggestion:
|
|
11
|
-
eligible: true
|
|
12
|
-
trigger_description: "extract a learning from a past session, mine chat-history for proposals, what did we learn last session, codify a pattern from a prior session"
|
|
13
|
-
trigger_context: "user wants to derive a rule/skill/guideline proposal from the content of one prior session"
|
|
14
|
-
workspaces:
|
|
15
|
-
- agent-config-maintainer
|
|
16
|
-
packs:
|
|
17
|
-
- meta
|
|
18
|
-
---
|
|
19
|
-
<!-- cloud_safe: noop -->
|
|
20
|
-
|
|
21
|
-
# /chat-history learn
|
|
22
|
-
|
|
23
|
-
User-driven **learning extraction** from a prior session. Surfaces
|
|
24
|
-
prior sessions logged in `agents/runtime/.agent-chat-history` as numbered options,
|
|
25
|
-
the user picks **one**, the agent reads that session's entries and
|
|
26
|
-
runs the [`learning-to-rule-or-skill`](../../skills/learning-to-rule-or-skill/SKILL.md)
|
|
27
|
-
workflow on the content — surfacing repeated mistakes, successful
|
|
28
|
-
patterns, or constraints worth codifying as a rule, skill, or
|
|
29
|
-
guideline proposal.
|
|
30
|
-
|
|
31
|
-
This is the **project-improvement** counterpart to
|
|
32
|
-
[`/chat-history import`](import.md): `import` renders a session
|
|
33
|
-
verbatim into the current chat for the user to act on; `learn`
|
|
34
|
-
mines a session for proposals that improve the agent or the
|
|
35
|
-
project itself.
|
|
36
|
-
|
|
37
|
-
## When NOT to use
|
|
38
|
-
|
|
39
|
-
- Pull a prior session into the current chat verbatim — use
|
|
40
|
-
[`/chat-history import`](import.md).
|
|
41
|
-
- Capture a learning that originated **in the current** session —
|
|
42
|
-
invoke the [`learning-to-rule-or-skill`](../../skills/learning-to-rule-or-skill/SKILL.md)
|
|
43
|
-
skill directly. `learn` is for prior-session mining only.
|
|
44
|
-
- Bulk-mine all sessions — out of scope for v1. One session per
|
|
45
|
-
invocation; multi-pick is v2.
|
|
46
|
-
|
|
47
|
-
## Steps
|
|
48
|
-
|
|
49
|
-
### 1. Check if enabled
|
|
50
|
-
|
|
51
|
-
Read `chat_history.enabled` from `.agent-settings.yml`. If `false`
|
|
52
|
-
or the section is missing, say so and stop:
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
> 📒 chat-history is disabled (chat_history.enabled = false).
|
|
56
|
-
> Set it to true in .agent-settings.yml to start logging.
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
### 2. List sessions
|
|
60
|
-
|
|
61
|
-
Run `scripts/chat_history.py sessions --json --limit 20 --summary`.
|
|
62
|
-
The helper returns an array of
|
|
63
|
-
`{id, count, first_ts, last_ts, preview, summary}` sorted by
|
|
64
|
-
`last_ts` desc. The `summary` field is built inside the helper
|
|
65
|
-
from ≤10 sampled entries per session (5 oldest + 5 newest) —
|
|
66
|
-
token-cheap, no full-body read needed for the picker. Empty
|
|
67
|
-
buckets are excluded by default.
|
|
68
|
-
|
|
69
|
-
If the array is empty, stop:
|
|
70
|
-
|
|
71
|
-
```
|
|
72
|
-
> 📒 No prior sessions found in agents/runtime/.agent-chat-history.
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### 3. Surface as numbered options
|
|
76
|
-
|
|
77
|
-
Render each session as a numbered option (per the `user-interaction`
|
|
78
|
-
rule — Iron Law: numbered options for any picker). Lead with the
|
|
79
|
-
helper's `summary` field — the rough arc the user picks by
|
|
80
|
-
(`<first user msg> → <last user msg>`, or
|
|
81
|
-
`(N entries — no user prompts; t-mix: …)` for tool-only sessions).
|
|
82
|
-
Keep the session `id` **internal** for step 5's `read --session <id>`
|
|
83
|
-
call; never render it in the listing. Format:
|
|
84
|
-
|
|
85
|
-
```
|
|
86
|
-
> Pick a session to mine for learnings:
|
|
87
|
-
>
|
|
88
|
-
> 1. {summary}
|
|
89
|
-
> {YYYY-MM-DD HH:MM} · {count} entries
|
|
90
|
-
> 2. ...
|
|
91
|
-
> ...
|
|
92
|
-
> N. abort — do not extract any learning
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
Format the timestamp as `YYYY-MM-DD HH:MM` (drop seconds + timezone
|
|
96
|
-
— orientation, not forensics). Do not truncate or rewrite `summary`
|
|
97
|
-
— the helper already shapes it. Always include an explicit abort
|
|
98
|
-
option last. Track option-number → `id` internally so step 5 calls
|
|
99
|
-
`scripts/chat_history.py read --session <id>` with the right id.
|
|
100
|
-
|
|
101
|
-
### 4. Wait for the pick
|
|
102
|
-
|
|
103
|
-
**One question per turn** (per `ask-when-uncertain`). Do not chain
|
|
104
|
-
the listing with anything else; do not auto-pick; do not surface a
|
|
105
|
-
default. Wait for the user's response.
|
|
106
|
-
|
|
107
|
-
If the user picks the abort option, stop without reading.
|
|
108
|
-
|
|
109
|
-
### 5. Read the picked session
|
|
110
|
-
|
|
111
|
-
Run `scripts/chat_history.py read --session <id>` with the picked
|
|
112
|
-
`id`. Hold the entries in working memory — do **not** render them
|
|
113
|
-
verbatim into the chat. The verbatim path is `import`'s job; here
|
|
114
|
-
the entries are input to step 6.
|
|
115
|
-
|
|
116
|
-
### 6. Run `learning-to-rule-or-skill`
|
|
117
|
-
|
|
118
|
-
Apply the [`learning-to-rule-or-skill`](../../skills/learning-to-rule-or-skill/SKILL.md)
|
|
119
|
-
procedure on the session content:
|
|
120
|
-
|
|
121
|
-
1. **Scan** the entries for candidate learnings — repeated
|
|
122
|
-
mistakes, successful patterns, friction points, or constraints
|
|
123
|
-
stated by the user.
|
|
124
|
-
2. **Pass each candidate through the Promotion Gate** (§ 0 of the
|
|
125
|
-
skill): repetition, impact, failure pattern, non-duplication,
|
|
126
|
-
scope fit, minimal. Drop candidates that fail any gate.
|
|
127
|
-
3. **For each surviving candidate**, run § 4 (search protocol — all
|
|
128
|
-
four steps), then decide rule / skill / guideline / update / no
|
|
129
|
-
action per § 3 of the skill.
|
|
130
|
-
4. **Draft a proposal** for every candidate that warrants one,
|
|
131
|
-
following § 8 of the skill (proposal template under
|
|
132
|
-
`agents/proposals/<id>.md`).
|
|
133
|
-
|
|
134
|
-
If multiple candidates survive, draft them as **separate**
|
|
135
|
-
proposals — do not merge unrelated learnings into one.
|
|
136
|
-
|
|
137
|
-
### 7. Surface the result
|
|
138
|
-
|
|
139
|
-
Hand back to the user with a structured summary per surviving
|
|
140
|
-
candidate:
|
|
141
|
-
|
|
142
|
-
```
|
|
143
|
-
> 📒 Mined session {id} — {N} candidate(s) surfaced
|
|
144
|
-
|
|
145
|
-
> 1. {learning title}
|
|
146
|
-
> Decision: {rule|skill|guideline|update|no action}
|
|
147
|
-
> Proposal: agents/proposals/{proposal_id}.md
|
|
148
|
-
> Gate: {pass|fail — reason}
|
|
149
|
-
> 2. ...
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
If no candidate cleared the Promotion Gate, say so explicitly:
|
|
153
|
-
|
|
154
|
-
```
|
|
155
|
-
> 📒 Mined session {id} — no candidate cleared the Promotion Gate.
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
Do **not** open a PR, do **not** commit the proposals — proposal
|
|
159
|
-
files land in `agents/proposals/` (gitignored or curated per
|
|
160
|
-
project policy) for the user to review and route via
|
|
161
|
-
`upstream-contribute` or merge into `agents/overrides/`.
|
|
162
|
-
|
|
163
|
-
## Gotchas
|
|
164
|
-
|
|
165
|
-
- **Promotion Gate is hard.** A grep miss is not proof of
|
|
166
|
-
non-duplication — § 4 of the skill mandates the four-step search
|
|
167
|
-
protocol. Do not skip it.
|
|
168
|
-
- **One pick per invocation.** Multi-pick is v2. If the user wants
|
|
169
|
-
to mine a second session, run `/chat-history learn` again.
|
|
170
|
-
- **Read-only on the log.** This command never writes to
|
|
171
|
-
`agents/runtime/.agent-chat-history`. It writes proposal drafts under
|
|
172
|
-
`agents/proposals/` only.
|
|
173
|
-
- **No auto-promotion.** Drafted proposals stay in `proposals/`
|
|
174
|
-
until the user routes them. `learn` never invokes
|
|
175
|
-
`upstream-contribute` itself.
|
|
176
|
-
|
|
177
|
-
## See also
|
|
178
|
-
|
|
179
|
-
- [`/chat-history import`](import.md) — verbatim render of a prior session
|
|
180
|
-
- [`learning-to-rule-or-skill`](../../skills/learning-to-rule-or-skill/SKILL.md) — the workflow this command orchestrates
|
|
181
|
-
- [`upstream-contribute`](../../skills/upstream-contribute/SKILL.md) — promote a project-scoped proposal upstream
|
|
182
|
-
- [`scripts/chat_history.py`](../../../scripts/chat_history.py) — `sessions` and `read --session` CLI surface
|
|
183
|
-
- [`user-interaction`](../../rules/user-interaction.md) — numbered-options Iron Law
|
|
184
|
-
- [`ask-when-uncertain`](../../rules/ask-when-uncertain.md) — one-question-per-turn Iron Law
|