@event4u/agent-config 1.20.0 → 1.22.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/.agent-src/commands/agents.md +1 -1
- package/.agent-src/commands/bug-fix.md +2 -1
- package/.agent-src/commands/bug-investigate.md +3 -2
- package/.agent-src/commands/challenge-me/vision.md +348 -0
- package/.agent-src/commands/challenge-me/with-docs.md +333 -0
- package/.agent-src/commands/challenge-me.md +61 -0
- package/.agent-src/commands/chat-history/import.md +60 -64
- package/.agent-src/commands/compress.md +12 -0
- package/.agent-src/commands/context/create.md +2 -2
- package/.agent-src/commands/context.md +1 -1
- package/.agent-src/commands/copilot-agents.md +1 -1
- package/.agent-src/commands/council/default.md +69 -10
- package/.agent-src/commands/council.md +1 -1
- package/.agent-src/commands/create-pr.md +7 -3
- package/.agent-src/commands/e2e-heal.md +1 -1
- package/.agent-src/commands/e2e-plan.md +1 -1
- package/.agent-src/commands/feature/dev.md +3 -3
- package/.agent-src/commands/feature.md +1 -1
- package/.agent-src/commands/fix/seeder.md +2 -2
- package/.agent-src/commands/fix.md +1 -1
- package/.agent-src/commands/grill-me.md +38 -0
- package/.agent-src/commands/jira-ticket.md +1 -1
- package/.agent-src/commands/judge/steps.md +1 -1
- package/.agent-src/commands/judge.md +2 -2
- package/.agent-src/commands/memory.md +1 -1
- package/.agent-src/commands/mode.md +5 -5
- package/.agent-src/commands/module.md +1 -1
- package/.agent-src/commands/onboard.md +4 -4
- package/.agent-src/commands/optimize/augmentignore.md +1 -1
- package/.agent-src/commands/optimize-prompt.md +61 -0
- package/.agent-src/commands/optimize.md +1 -1
- package/.agent-src/commands/override.md +1 -1
- package/.agent-src/commands/review-changes.md +1 -1
- package/.agent-src/commands/review-routing.md +1 -1
- package/.agent-src/commands/roadmap/ai-council.md +183 -0
- package/.agent-src/commands/roadmap/create.md +6 -1
- package/.agent-src/commands/roadmap/process-full.md +58 -0
- package/.agent-src/commands/roadmap/process-phase.md +69 -0
- package/.agent-src/commands/roadmap/process-step.md +57 -0
- package/.agent-src/commands/roadmap.md +45 -17
- package/.agent-src/commands/set-cost-profile.md +3 -3
- package/.agent-src/commands/sync-agent-settings.md +2 -2
- package/.agent-src/commands/tests/create.md +2 -2
- package/.agent-src/commands/tests.md +1 -1
- package/.agent-src/commands/threat-model.md +5 -4
- package/.agent-src/contexts/augment-infrastructure.md +1 -1
- package/.agent-src/contexts/authority/commit-mechanics.md +14 -1
- package/.agent-src/contexts/authority/destructive-mechanics.md +14 -1
- package/.agent-src/contexts/authority/scope-mechanics.md +5 -0
- package/.agent-src/contexts/communication/rules-auto/guidelines-mechanics.md +76 -0
- package/.agent-src/contexts/communication/rules-auto/slash-command-routing-policy-mechanics.md +54 -19
- package/.agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +98 -0
- package/.agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +93 -0
- package/.agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +128 -5
- package/.agent-src/contexts/execution/autonomy-mechanics.md +44 -0
- package/.agent-src/contexts/execution/roadmap-process-loop.md +125 -0
- package/.agent-src/contexts/model-recommendations.md +2 -2
- package/.agent-src/contexts/override-system.md +1 -1
- package/.agent-src/contexts/skills-and-commands.md +1 -1
- package/.agent-src/personas/product-owner.md +2 -2
- package/.agent-src/personas/qa.md +1 -1
- package/.agent-src/rules/agent-authority.md +5 -6
- package/.agent-src/rules/agent-docs.md +11 -53
- package/.agent-src/rules/analysis-skill-routing.md +10 -40
- package/.agent-src/rules/architecture.md +6 -1
- package/.agent-src/rules/artifact-drafting-protocol.md +5 -0
- package/.agent-src/rules/artifact-engagement-recording.md +23 -59
- package/.agent-src/rules/ask-when-uncertain.md +24 -47
- package/.agent-src/rules/augment-portability.md +14 -62
- package/.agent-src/rules/augment-source-of-truth.md +10 -1
- package/.agent-src/rules/autonomous-execution.md +17 -98
- package/.agent-src/rules/capture-learnings.md +9 -80
- package/.agent-src/rules/cli-output-handling.md +12 -42
- package/.agent-src/rules/command-suggestion-policy.md +25 -73
- package/.agent-src/rules/commit-conventions.md +9 -58
- package/.agent-src/rules/commit-policy.md +16 -47
- package/.agent-src/rules/context-hygiene.md +5 -0
- package/.agent-src/rules/direct-answers.md +21 -50
- package/.agent-src/rules/docker-commands.md +11 -45
- package/.agent-src/rules/docs-sync.md +10 -56
- package/.agent-src/rules/downstream-changes.md +5 -0
- package/.agent-src/rules/e2e-testing.md +9 -44
- package/.agent-src/rules/guidelines.md +13 -75
- package/.agent-src/rules/improve-before-implement.md +11 -2
- package/.agent-src/rules/invite-challenge.md +71 -0
- package/.agent-src/rules/language-and-tone.md +41 -106
- package/.agent-src/rules/laravel-translations.md +11 -40
- package/.agent-src/rules/markdown-safe-codeblocks.md +4 -0
- package/.agent-src/rules/minimal-safe-diff.md +4 -0
- package/.agent-src/rules/missing-tool-handling.md +4 -0
- package/.agent-src/rules/model-recommendation.md +9 -61
- package/.agent-src/rules/no-attribution-footers.md +5 -0
- package/.agent-src/rules/no-cheap-questions.md +11 -27
- package/.agent-src/rules/no-council-references.md +76 -0
- package/.agent-src/rules/no-roadmap-references.md +7 -0
- package/.agent-src/rules/non-destructive-by-default.md +13 -43
- package/.agent-src/rules/onboarding-gate.md +9 -117
- package/.agent-src/rules/package-ci-checks.md +10 -37
- package/.agent-src/rules/php-coding.md +10 -55
- package/.agent-src/rules/preservation-guard.md +9 -0
- package/.agent-src/rules/review-routing-awareness.md +9 -97
- package/.agent-src/rules/reviewer-awareness.md +8 -83
- package/.agent-src/rules/roadmap-progress-sync.md +7 -170
- package/.agent-src/rules/role-mode-adherence.md +6 -2
- package/.agent-src/rules/rule-type-governance.md +8 -66
- package/.agent-src/rules/runtime-safety.md +5 -0
- package/.agent-src/rules/scope-control.md +17 -62
- package/.agent-src/rules/security-sensitive-stop.md +7 -1
- package/.agent-src/rules/size-enforcement.md +6 -1
- package/.agent-src/rules/skill-improvement-trigger.md +9 -49
- package/.agent-src/rules/skill-quality.md +7 -113
- package/.agent-src/rules/slash-command-routing-policy.md +11 -63
- package/.agent-src/rules/think-before-action.md +22 -87
- package/.agent-src/rules/token-efficiency.md +10 -74
- package/.agent-src/rules/token-optimizer-maintenance.md +68 -0
- package/.agent-src/rules/tool-safety.md +4 -0
- package/.agent-src/rules/ui-audit-gate.md +25 -61
- package/.agent-src/rules/upstream-proposal.md +9 -67
- package/.agent-src/rules/user-interaction.md +22 -108
- package/.agent-src/rules/verify-before-complete.md +1 -1
- package/.agent-src/skills/adversarial-review/SKILL.md +1 -0
- package/.agent-src/skills/agent-docs-writing/SKILL.md +1 -1
- package/.agent-src/skills/ai-council/SKILL.md +197 -8
- package/.agent-src/skills/analysis-autonomous-mode/SKILL.md +1 -1
- package/.agent-src/skills/analysis-skill-router/SKILL.md +3 -3
- package/.agent-src/skills/artisan-commands/SKILL.md +2 -2
- package/.agent-src/skills/authz-review/SKILL.md +1 -1
- package/.agent-src/skills/aws-infrastructure/SKILL.md +5 -5
- package/.agent-src/skills/blast-radius-analyzer/SKILL.md +8 -8
- package/.agent-src/skills/bug-analyzer/SKILL.md +6 -5
- package/.agent-src/skills/code-refactoring/SKILL.md +4 -4
- package/.agent-src/skills/code-review/SKILL.md +2 -2
- package/.agent-src/skills/command-writing/SKILL.md +11 -0
- package/.agent-src/skills/composer-packages/SKILL.md +2 -2
- package/.agent-src/skills/context-authoring/SKILL.md +11 -0
- package/.agent-src/skills/context-document/SKILL.md +1 -1
- package/.agent-src/skills/copilot-agents-optimization/SKILL.md +23 -0
- package/.agent-src/skills/copilot-config/SKILL.md +1 -1
- package/.agent-src/skills/dependency-upgrade/SKILL.md +2 -2
- package/.agent-src/skills/devcontainer/SKILL.md +2 -2
- package/.agent-src/skills/developer-like-execution/SKILL.md +1 -1
- package/.agent-src/skills/docker/SKILL.md +1 -1
- package/.agent-src/skills/dto-creator/SKILL.md +1 -1
- package/.agent-src/skills/estimate-ticket/SKILL.md +2 -2
- package/.agent-src/skills/fe-design/SKILL.md +4 -4
- package/.agent-src/skills/feature-planning/SKILL.md +5 -5
- package/.agent-src/skills/funnel-analysis/SKILL.md +1 -1
- package/.agent-src/skills/laravel/SKILL.md +1 -1
- package/.agent-src/skills/laravel-notifications/SKILL.md +5 -5
- package/.agent-src/skills/laravel-pennant/SKILL.md +1 -1
- package/.agent-src/skills/laravel-pulse/SKILL.md +4 -4
- package/.agent-src/skills/laravel-reverb/SKILL.md +2 -2
- package/.agent-src/skills/laravel-scheduling/SKILL.md +1 -1
- package/.agent-src/skills/migration-creator/SKILL.md +7 -7
- package/.agent-src/skills/multi-tenancy/SKILL.md +8 -8
- package/.agent-src/skills/performance-analysis/SKILL.md +3 -3
- package/.agent-src/skills/pest-testing/SKILL.md +6 -6
- package/.agent-src/skills/php-service/SKILL.md +2 -2
- package/.agent-src/skills/project-analysis-hypothesis-driven/SKILL.md +3 -3
- package/.agent-src/skills/project-analysis-react/SKILL.md +1 -1
- package/.agent-src/skills/project-analysis-symfony/SKILL.md +1 -1
- package/.agent-src/skills/project-analysis-zend-laminas/SKILL.md +2 -2
- package/.agent-src/skills/project-analyzer/SKILL.md +4 -4
- package/.agent-src/skills/prompt-optimizer/SKILL.md +108 -0
- package/.agent-src/skills/readme-reviewer/SKILL.md +1 -1
- package/.agent-src/skills/roadmap-management/SKILL.md +7 -7
- package/.agent-src/skills/rule-writing/SKILL.md +33 -0
- package/.agent-src/skills/sentry-integration/SKILL.md +1 -1
- package/.agent-src/skills/skill-writing/SKILL.md +14 -0
- package/.agent-src/skills/systematic-debugging/SKILL.md +22 -2
- package/.agent-src/skills/technical-specification/SKILL.md +58 -1
- package/.agent-src/skills/terraform/SKILL.md +2 -2
- package/.agent-src/skills/terragrunt/SKILL.md +8 -8
- package/.agent-src/skills/test-performance/SKILL.md +5 -5
- package/.agent-src/skills/threat-modeling/SKILL.md +3 -2
- package/.agent-src/skills/token-optimizer/SKILL.md +110 -0
- package/.agent-src/skills/universal-project-analysis/SKILL.md +1 -1
- package/.agent-src/templates/AGENTS.md +1 -1
- package/.agent-src/templates/agent-settings.md +35 -19
- package/.agent-src/templates/command.md +17 -1
- package/.agent-src/templates/contexts/tenant-boundaries.md +2 -2
- package/.agent-src/templates/contexts.md +1 -1
- package/.agent-src/templates/copilot-instructions.md +21 -0
- package/.agent-src/templates/copilot-review-instructions.md +76 -0
- package/.agent-src/templates/features.md +1 -1
- package/.agent-src/templates/roadmaps.md +10 -2
- package/.agent-src/templates/rule.md +129 -0
- package/.agent-src/templates/skill.md +17 -0
- package/.claude-plugin/marketplace.json +12 -2
- package/AGENTS.md +32 -5
- package/CHANGELOG.md +107 -3
- package/README.md +22 -21
- package/config/agent-settings.template.yml +66 -10
- package/config/gitignore-block.txt +7 -0
- package/docs/architecture.md +86 -5
- package/docs/catalog.md +16 -6
- package/docs/contracts/agent-memory-contract.md +1 -1
- package/docs/contracts/command-clusters.md +45 -1
- package/docs/contracts/context-paths.md +2 -1
- package/docs/contracts/file-ownership-matrix.json +354 -500
- package/docs/contracts/iron-law-overrides.txt +25 -0
- package/docs/contracts/kernel-membership.md +273 -0
- package/docs/contracts/load-context-schema.md +26 -11
- package/docs/contracts/pilot/agent-authority.md +24 -0
- package/docs/contracts/pilot/direct-answers.md +70 -0
- package/docs/contracts/pilot/language-and-tone.md +63 -0
- package/docs/contracts/rule-classification.md +170 -0
- package/docs/contracts/rule-router.md +153 -0
- package/docs/customization.md +17 -6
- package/docs/decisions/ADR-001-kernel-swap-deferred.md +109 -0
- package/docs/decisions/ADR-002-kernel-bucket-overrides.md +124 -0
- package/docs/decisions/ADR-003-flat-cluster-subs-and-colon-syntax.md +126 -0
- package/docs/decisions/ADR-rule-kernel-and-router.md +122 -0
- package/docs/getting-started.md +2 -2
- package/docs/guidelines/agent-infra/naming.md +1 -1
- package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +176 -0
- package/docs/guidelines/agent-infra/rule-type-governance.md +73 -0
- package/docs/guidelines/agent-infra/size-and-scope.md +13 -2
- package/docs/guidelines/agent-infra/skill-quality-checklist.md +119 -0
- package/docs/guidelines/augment-portability-patterns.md +68 -0
- package/docs/guidelines/php/php-coding-patterns.md +62 -0
- package/package.json +1 -1
- package/scripts/_p43_bodies.py +235 -0
- package/scripts/_p43_compress.py +118 -0
- package/scripts/_p4_migrate.py +199 -0
- package/scripts/_phase2_shim_helper.py +1 -1
- package/scripts/_pilot_council_question.py +57 -0
- package/scripts/_pilot_measure.py +53 -0
- package/scripts/ai_council/session.py +107 -5
- package/scripts/build_linear_digest.py +3 -5
- package/scripts/check_always_budget.py +39 -6
- package/scripts/check_compressed_paths.py +213 -0
- package/scripts/check_compression.py +15 -0
- package/scripts/check_context_paths.py +1 -0
- package/scripts/check_council_layout.py +105 -0
- package/scripts/check_council_references.py +145 -0
- package/scripts/check_portability.py +2 -0
- package/scripts/check_references.py +2 -0
- package/scripts/check_token_optimizer_freshness.py +131 -0
- package/scripts/compile_router.py +148 -0
- package/scripts/compress.py +219 -11
- package/scripts/council_cli.py +132 -11
- package/scripts/council_prune.py +81 -0
- package/scripts/count_token_optimizer_usage.sh +54 -0
- package/scripts/install.sh +44 -2
- package/scripts/iron_law_sha.py +98 -0
- package/scripts/lint_load_context.py +35 -5
- package/scripts/measure_rule_budget.py +314 -0
- package/scripts/migrate_command_suggestions.py +2 -2
- package/scripts/prototype_lint_contradictions.py +150 -0
- package/scripts/schemas/command.schema.json +5 -0
- package/scripts/schemas/rule.schema.json +60 -6
- package/scripts/schemas/skill.schema.json +5 -0
- package/scripts/skill_linter.py +197 -7
- package/scripts/smoke_path_resolution.py +93 -0
- package/scripts/validate_frontmatter.py +41 -1
- package/.agent-src/commands/roadmap/execute.md +0 -109
- package/.agent-src/contexts/communication/rules-auto/artifact-engagement-recording-mechanics.md +0 -72
- package/.agent-src/contexts/communication/rules-auto/augment-portability-mechanics.md +0 -79
- package/.agent-src/contexts/communication/rules-auto/cli-output-handling-mechanics.md +0 -87
- package/.agent-src/contexts/communication/rules-auto/command-suggestion-policy-mechanics.md +0 -62
- package/.agent-src/contexts/communication/rules-auto/docs-sync-mechanics.md +0 -78
- package/.agent-src/contexts/communication/rules-auto/package-ci-checks-mechanics.md +0 -85
- package/.agent-src/contexts/communication/rules-auto/review-routing-awareness-mechanics.md +0 -65
- package/.agent-src/contexts/communication/rules-auto/roadmap-progress-sync-mechanics.md +0 -78
- package/.agent-src/contexts/communication/rules-auto/ui-audit-gate-mechanics.md +0 -53
- /package/{docs → .agent-src/contexts}/contracts/artifact-engagement-flow.md +0 -0
- /package/{docs → .agent-src/contexts}/contracts/command-suggestion-flow.md +0 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""P4.1 + P4.2 migration: rule → skill / guideline / command / contract stub.
|
|
3
|
+
|
|
4
|
+
Replaces 25 rules with thin stubs declaring `triggers:` + `routes_to:`.
|
|
5
|
+
For move-to-guideline, copies the rule body into a new guideline file.
|
|
6
|
+
For move-to-skill / command / contract, the target already carries the
|
|
7
|
+
procedure — stub keeps an Iron-Law one-liner only.
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
import re, sys, pathlib
|
|
11
|
+
|
|
12
|
+
ROOT = pathlib.Path(__file__).resolve().parents[1]
|
|
13
|
+
RULES = ROOT / ".agent-src.uncompressed" / "rules"
|
|
14
|
+
GUIDELINES = ROOT / "docs" / "guidelines"
|
|
15
|
+
|
|
16
|
+
# (rule_id, route, triggers, iron_law_one_liner)
|
|
17
|
+
# route format: "kind:id"
|
|
18
|
+
SKILL_MIGRATIONS = [
|
|
19
|
+
("agent-docs", "skill:agent-docs-writing",
|
|
20
|
+
[("path_prefix", "agents/"), ("path_prefix", ".github/copilot-instructions"), ("keyword", "AGENTS.md"), ("keyword", "roadmap")],
|
|
21
|
+
"Read agent docs (`AGENTS.md`, `agents/`, module `agents/`) before work; update them after structural changes."),
|
|
22
|
+
("analysis-skill-routing", "skill:analysis-skill-router",
|
|
23
|
+
[("keyword", "analyze"), ("keyword", "analysis"), ("phrase", "dig into the codebase")],
|
|
24
|
+
"Route analysis tasks to the narrowest matching `project-analysis-*` skill, not the broad fallback."),
|
|
25
|
+
("capture-learnings", "skill:learning-to-rule-or-skill",
|
|
26
|
+
[("phrase", "after completing a task"), ("keyword", "learning"), ("keyword", "lesson")],
|
|
27
|
+
"After a task, capture repeated mistakes / successful patterns as a rule or skill — never lose the learning."),
|
|
28
|
+
("cli-output-handling", "skill:rtk-output-filtering",
|
|
29
|
+
[("keyword", "git"), ("keyword", "phpstan"), ("keyword", "rector"), ("keyword", "phpunit"), ("keyword", "composer")],
|
|
30
|
+
"Wrap verbose CLI output with `rtk` when installed; fall back to `tail`/`grep` only when missing."),
|
|
31
|
+
("commit-conventions", "skill:conventional-commits-writing",
|
|
32
|
+
[("keyword", "commit"), ("keyword", "branch"), ("phrase", "conventional commits")],
|
|
33
|
+
"Use Conventional Commits (`feat:`, `fix:`, `chore:` …); branches `<type>/<short-slug>`; never invent your own format."),
|
|
34
|
+
("docker-commands", "skill:docker",
|
|
35
|
+
[("keyword", "docker"), ("keyword", "artisan"), ("keyword", "composer"), ("phrase", "inside the container")],
|
|
36
|
+
"Run PHP / artisan / composer / phpstan / rector / ecs / phpunit inside the project container, never on the host."),
|
|
37
|
+
("docs-sync", "skill:agent-docs-writing",
|
|
38
|
+
[("path_prefix", ".agent-src.uncompressed/"), ("path_prefix", ".augment/"), ("keyword", "rename"), ("keyword", "delete")],
|
|
39
|
+
"On any add / rename / delete of skill / rule / command / guideline, update counts and cross-references in the same edit."),
|
|
40
|
+
("e2e-testing", "command:e2e-heal",
|
|
41
|
+
[("keyword", "playwright"), ("keyword", "e2e"), ("phrase", "page object")],
|
|
42
|
+
"Playwright E2E: stable locators, no `waitForTimeout`, Page Objects for shared flows, fixtures over `beforeEach`."),
|
|
43
|
+
("laravel-translations", "skill:laravel",
|
|
44
|
+
[("path_prefix", "lang/"), ("keyword", "translation"), ("keyword", "__()"), ("keyword", "trans(")],
|
|
45
|
+
"Use `__()`/`trans()` with language keys for every user-visible string; mirror keys across `lang/<locale>/` files."),
|
|
46
|
+
("model-recommendation", "command:set-cost-profile",
|
|
47
|
+
[("phrase", "switch task"), ("phrase", "new task"), ("phrase", "which model")],
|
|
48
|
+
"On task / model switch, recommend the optimal model for the task complexity before any work begins."),
|
|
49
|
+
("onboarding-gate", "command:onboard",
|
|
50
|
+
[("phrase", "first turn"), ("keyword", "onboarding"), ("path_prefix", ".agent-settings.yml")],
|
|
51
|
+
"First turn of a project: if `onboarding.onboarded` is false, prompt `/onboard` before executing any other request."),
|
|
52
|
+
("package-ci-checks", "skill:lint-skills",
|
|
53
|
+
[("phrase", "task ci"), ("phrase", "before push"), ("phrase", "before pr")],
|
|
54
|
+
"Run `task ci` locally and confirm green before pushing or opening a PR in this package."),
|
|
55
|
+
("review-routing-awareness", "skill:review-routing",
|
|
56
|
+
[("keyword", "reviewer"), ("phrase", "risk hotspot"), ("phrase", "ownership map")],
|
|
57
|
+
"Consult ownership-map and historical-bug-patterns before suggesting reviewers or claiming a change is safe."),
|
|
58
|
+
("reviewer-awareness", "skill:review-routing",
|
|
59
|
+
[("keyword", "reviewer"), ("phrase", "suggest reviewers")],
|
|
60
|
+
"Anchor reviewer choice in paths and risk, never seniority; medium / high risk requires primary + secondary role."),
|
|
61
|
+
("skill-improvement-trigger", "skill:skill-improvement-pipeline",
|
|
62
|
+
[("phrase", "after completing"), ("keyword", "improvement"), ("keyword", "pipeline")],
|
|
63
|
+
"After a meaningful task, trigger the post-task learning capture if `pipelines.skill_improvement` is enabled."),
|
|
64
|
+
("slash-command-routing-policy", "skill:command-routing",
|
|
65
|
+
[("keyword", "/create-pr"), ("keyword", "/commit"), ("keyword", "/fix-ci"), ("phrase", "slash command")],
|
|
66
|
+
"On a slash-command invocation or pasted command body, route to the matching command file; never improvise."),
|
|
67
|
+
("ui-audit-gate", "skill:existing-ui-audit",
|
|
68
|
+
[("path_prefix", "resources/views/"), ("path_prefix", "resources/js/"), ("keyword", "component"), ("keyword", "design token")],
|
|
69
|
+
"Before any non-trivial UI change, require `state.ui_audit` findings — gate, not suggestion."),
|
|
70
|
+
("upstream-proposal", "skill:upstream-contribute",
|
|
71
|
+
[("phrase", "after creating"), ("phrase", "after improving"), ("keyword", "upstream")],
|
|
72
|
+
"After creating or significantly improving a skill / rule / guideline / command, ask whether to upstream it."),
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
GUIDELINE_MIGRATIONS = [
|
|
76
|
+
("artifact-engagement-recording", "contract:artifact-engagement-flow",
|
|
77
|
+
[("phrase", "/implement-ticket"), ("phrase", "/work"), ("keyword", "telemetry")],
|
|
78
|
+
"After a `/implement-ticket` or `/work` phase-step, emit one `telemetry:record` call with consulted + applied ids when telemetry is enabled."),
|
|
79
|
+
("augment-portability", "guideline:augment-portability-patterns",
|
|
80
|
+
[("path_prefix", ".augment/"), ("path_prefix", ".agent-src.uncompressed/"), ("keyword", "portable")],
|
|
81
|
+
"Files inside `.augment/` and `.agent-src.uncompressed/` MUST stay project-agnostic — no project names, domains, stacks."),
|
|
82
|
+
("command-suggestion-policy", "contract:command-suggestion-flow",
|
|
83
|
+
[("phrase", "free-form prompt"), ("phrase", "command suggestion")],
|
|
84
|
+
"When a free-form prompt matches a command, surface matches as numbered options with as-is escape; never auto-execute."),
|
|
85
|
+
("php-coding", "guideline:php/php-coding-patterns",
|
|
86
|
+
[("file_pattern", "*.php"), ("keyword", "phpstan"), ("keyword", "ecs")],
|
|
87
|
+
"PHP: strict types, named comparisons, early returns, Eloquent conventions — full pattern library in the guideline."),
|
|
88
|
+
("roadmap-progress-sync", "guideline:agent-infra/roadmap-progress-mechanics",
|
|
89
|
+
[("path_prefix", "agents/roadmaps/")],
|
|
90
|
+
"Any touch to `agents/roadmaps/` regenerates the dashboard in the same response; archive the roadmap when 0 open items remain."),
|
|
91
|
+
("rule-type-governance", "guideline:agent-infra/rule-type-governance",
|
|
92
|
+
[("path_prefix", ".agent-src.uncompressed/rules/")],
|
|
93
|
+
"Choose `always` vs `auto` per the governance table; over-broad `always` rules degrade the kernel budget."),
|
|
94
|
+
("skill-quality", "guideline:agent-infra/skill-quality-checklist",
|
|
95
|
+
[("path_prefix", ".agent-src.uncompressed/skills/")],
|
|
96
|
+
"Every skill must be executable, validated, and self-contained — full checklist in the guideline."),
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def yaml_triggers(triggers: list[tuple[str, str]]) -> str:
|
|
102
|
+
lines = []
|
|
103
|
+
for kind, val in triggers:
|
|
104
|
+
v = val.replace('"', '\\"')
|
|
105
|
+
lines.append(f' - {kind}: "{v}"')
|
|
106
|
+
return "\n".join(lines)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def parse_existing_frontmatter(text: str) -> tuple[dict, str]:
|
|
110
|
+
m = re.match(r"^---\n(.*?)\n---\n(.*)$", text, re.DOTALL)
|
|
111
|
+
if not m:
|
|
112
|
+
return {}, text
|
|
113
|
+
fm_text, body = m.group(1), m.group(2)
|
|
114
|
+
fm = {}
|
|
115
|
+
for line in fm_text.split("\n"):
|
|
116
|
+
if ":" not in line or line.startswith(" "):
|
|
117
|
+
continue
|
|
118
|
+
k, _, v = line.partition(":")
|
|
119
|
+
fm[k.strip()] = v.strip().strip('"')
|
|
120
|
+
return fm, body
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def build_stub(rule_id: str, route: str, triggers: list[tuple[str, str]],
|
|
124
|
+
iron_law: str, existing_fm: dict) -> str:
|
|
125
|
+
desc = existing_fm.get("description", "")
|
|
126
|
+
tier = existing_fm.get("tier", "3")
|
|
127
|
+
rtype = existing_fm.get("type", "auto")
|
|
128
|
+
source = existing_fm.get("source", "package")
|
|
129
|
+
new_tier = {"1": "tier-1", "2a": "tier-2", "2b": "tier-2", "3": "tier-2",
|
|
130
|
+
"mechanical-already": "tier-2", "mech": "tier-2"}.get(tier, "tier-2")
|
|
131
|
+
fm_lines = [
|
|
132
|
+
"---",
|
|
133
|
+
f'type: "{rtype}"',
|
|
134
|
+
f'tier: "{new_tier}"',
|
|
135
|
+
f'description: "{desc}"',
|
|
136
|
+
f'source: {source}',
|
|
137
|
+
"triggers:",
|
|
138
|
+
yaml_triggers(triggers),
|
|
139
|
+
"routes_to:",
|
|
140
|
+
f' - "{route}"',
|
|
141
|
+
"---",
|
|
142
|
+
"",
|
|
143
|
+
f"# {rule_id.replace('-', ' ').title()}",
|
|
144
|
+
"",
|
|
145
|
+
f"**Iron Law.** {iron_law}",
|
|
146
|
+
"",
|
|
147
|
+
f"Body migrated to `{route}` (per P4 of `road-to-kernel-and-router.md`).",
|
|
148
|
+
"Trigger-set above activates this routing under the `balanced` and `full` profiles.",
|
|
149
|
+
]
|
|
150
|
+
return "\n".join(fm_lines) + "\n"
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def write_guideline(rule_id: str, route: str, body: str, existing_fm: dict) -> pathlib.Path:
|
|
154
|
+
kind, _, gid = route.partition(":")
|
|
155
|
+
if kind == "guideline":
|
|
156
|
+
target = GUIDELINES / f"{gid}.md"
|
|
157
|
+
elif kind == "contract":
|
|
158
|
+
target = ROOT / "docs" / "contracts" / f"{gid}.md"
|
|
159
|
+
else:
|
|
160
|
+
raise ValueError(f"unsupported route kind for guideline migration: {kind}")
|
|
161
|
+
if target.exists():
|
|
162
|
+
return target
|
|
163
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
164
|
+
desc = existing_fm.get("description", "")
|
|
165
|
+
header = (f"# {rule_id.replace('-', ' ').title()}\n\n"
|
|
166
|
+
f"> {desc}\n\n"
|
|
167
|
+
f"_Origin: migrated from `.agent-src.uncompressed/rules/{rule_id}.md` "
|
|
168
|
+
f"per P4.2 of `road-to-kernel-and-router.md`._\n\n")
|
|
169
|
+
target.write_text(header + body.lstrip())
|
|
170
|
+
return target
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def main() -> int:
|
|
174
|
+
written = []
|
|
175
|
+
for rule_id, route, triggers, iron_law in SKILL_MIGRATIONS:
|
|
176
|
+
rule_path = RULES / f"{rule_id}.md"
|
|
177
|
+
if not rule_path.exists():
|
|
178
|
+
print(f" ✗ MISSING rule: {rule_id}"); continue
|
|
179
|
+
fm, body = parse_existing_frontmatter(rule_path.read_text())
|
|
180
|
+
stub = build_stub(rule_id, route, triggers, iron_law, fm)
|
|
181
|
+
rule_path.write_text(stub)
|
|
182
|
+
written.append(("skill-stub", rule_id, route, len(stub)))
|
|
183
|
+
for rule_id, route, triggers, iron_law in GUIDELINE_MIGRATIONS:
|
|
184
|
+
rule_path = RULES / f"{rule_id}.md"
|
|
185
|
+
if not rule_path.exists():
|
|
186
|
+
print(f" ✗ MISSING rule: {rule_id}"); continue
|
|
187
|
+
fm, body = parse_existing_frontmatter(rule_path.read_text())
|
|
188
|
+
write_guideline(rule_id, route, body, fm)
|
|
189
|
+
stub = build_stub(rule_id, route, triggers, iron_law, fm)
|
|
190
|
+
rule_path.write_text(stub)
|
|
191
|
+
written.append(("guideline", rule_id, route, len(stub)))
|
|
192
|
+
print(f"\nMigrated {len(written)} rules:")
|
|
193
|
+
for kind, rid, route, sz in written:
|
|
194
|
+
print(f" {kind:14s} {rid:35s} → {route:55s} stub={sz}c")
|
|
195
|
+
return 0
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
if __name__ == "__main__":
|
|
199
|
+
sys.exit(main())
|
|
@@ -25,7 +25,7 @@ PHASE2_SHIMS: list[tuple[str, str]] = [
|
|
|
25
25
|
("propose-memory", "memory propose"),
|
|
26
26
|
# roadmap cluster
|
|
27
27
|
("roadmap-create", "roadmap create"),
|
|
28
|
-
("roadmap-execute", "roadmap
|
|
28
|
+
("roadmap-execute", "roadmap process-phase"),
|
|
29
29
|
# module cluster
|
|
30
30
|
("module-create", "module create"),
|
|
31
31
|
("module-explore", "module explore"),
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""Build the Phase-1 council question file (one-off)."""
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
OUT = Path("/tmp/council-p1/question.md")
|
|
5
|
+
OUT.parent.mkdir(parents=True, exist_ok=True)
|
|
6
|
+
|
|
7
|
+
framing = """# Cross-check request — Phase 1 of "Road to Rule Kernel and Router"
|
|
8
|
+
|
|
9
|
+
We are about to compress a 56-rule "always-active" set down to a small
|
|
10
|
+
hard-capped kernel + a router-loaded auto bucket. Phase 1 is purely
|
|
11
|
+
classification + projection — no source rules edited yet. Two contracts
|
|
12
|
+
were produced. We want a neutral second opinion BEFORE Phase 2 ships
|
|
13
|
+
compression to the actual rule files.
|
|
14
|
+
|
|
15
|
+
## What we want from you
|
|
16
|
+
|
|
17
|
+
1. **Disposition calls.** Look at the 56-rule classification. Are any
|
|
18
|
+
`keep-in-kernel` rules over-included (could safely become auto-tier)?
|
|
19
|
+
Are any `move-to-skill` / `move-to-guideline` calls wrong (e.g.
|
|
20
|
+
carrying an Iron Law that should stay always-on)? Cite the rule id
|
|
21
|
+
and the better disposition.
|
|
22
|
+
2. **Kernel inclusion criteria.** Section 1 of `kernel-membership.md`
|
|
23
|
+
lists 4 criteria (Iron-Law floor / mode-independent / pre-action
|
|
24
|
+
gate / cross-cutting). Are these the right gates? Is anything
|
|
25
|
+
missing or redundant?
|
|
26
|
+
3. **Compression-rate r = 0.742.** Three pilots gave r-values 0.677 /
|
|
27
|
+
0.712 / 0.838. We locked the **mean**. Reasonable, or should we use
|
|
28
|
+
median (0.712) / max (0.838) as a more conservative budget cushion?
|
|
29
|
+
Note: pilot range straddles the typical 0.6-0.75 band; max came
|
|
30
|
+
from the shortest rule (already-lean floor effect).
|
|
31
|
+
4. **The 1.5k per-rule cap with ADR-override.** Two of the three pilots
|
|
32
|
+
land >1.5k post-compression and would need an `iron-law-override`
|
|
33
|
+
ADR. Is the per-rule cap realistic, or should we raise the per-rule
|
|
34
|
+
ceiling (e.g. 2.5k or 3.5k) and lower the bucket cap (e.g. from 25k
|
|
35
|
+
to 20k)? What's the failure mode you'd be most worried about?
|
|
36
|
+
5. **Anything we missed.** Risks, blind spots, sequencing problems.
|
|
37
|
+
|
|
38
|
+
Be specific. Cite the rule id or the section number. We will reject
|
|
39
|
+
generic "looks good" reviews.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Contract 1 — docs/contracts/rule-classification.md
|
|
44
|
+
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
OUT.write_text(framing)
|
|
48
|
+
with OUT.open("a") as fh:
|
|
49
|
+
fh.write(Path("docs/contracts/rule-classification.md").read_text())
|
|
50
|
+
fh.write("\n\n---\n\n## Contract 2 — docs/contracts/kernel-membership.md\n\n")
|
|
51
|
+
fh.write(Path("docs/contracts/kernel-membership.md").read_text())
|
|
52
|
+
fh.write("\n\n---\n\n## Pilot inputs (compressed bodies, for reference)\n")
|
|
53
|
+
for rid in ("agent-authority", "direct-answers", "language-and-tone"):
|
|
54
|
+
fh.write(f"\n### Pilot — {rid}\n\n")
|
|
55
|
+
fh.write(Path(f"docs/contracts/pilot/{rid}.md").read_text())
|
|
56
|
+
|
|
57
|
+
print(f"wrote {OUT} — {OUT.stat().st_size} bytes")
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Pilot compression ratio + Iron-Law checksum verification (one-off, not CI)."""
|
|
2
|
+
import sys, re, hashlib, statistics
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
sys.path.insert(0, "scripts")
|
|
6
|
+
from measure_rule_budget import strip_frontmatter
|
|
7
|
+
|
|
8
|
+
FENCE_RE = re.compile(r"```(?:[^\n]*\n)([\s\S]*?)```")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def iron_law_sha(body: str) -> str:
|
|
12
|
+
blocks = FENCE_RE.findall(body)
|
|
13
|
+
norm = "".join(re.sub(r"\s+", " ", b).strip().upper() for b in blocks)
|
|
14
|
+
return hashlib.sha256(norm.encode()).hexdigest()[:16]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
pairs = [
|
|
18
|
+
("agent-authority", ".agent-src.uncompressed/rules/agent-authority.md", "docs/contracts/pilot/agent-authority.md"),
|
|
19
|
+
("direct-answers", ".agent-src.uncompressed/rules/direct-answers.md", "docs/contracts/pilot/direct-answers.md"),
|
|
20
|
+
("language-and-tone", ".agent-src.uncompressed/rules/language-and-tone.md", "docs/contracts/pilot/language-and-tone.md"),
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
header = f"{'rule':25s} {'orig':>6s} {'pilot':>6s} {'r':>6s} {'budget':>7s} {'sha-orig':>16s} {'sha-pilot':>16s} {'IL':>3s}"
|
|
24
|
+
print(header)
|
|
25
|
+
print("-" * len(header))
|
|
26
|
+
|
|
27
|
+
ratios = []
|
|
28
|
+
for rid, orig_path, pilot_path in pairs:
|
|
29
|
+
orig_body, _ = strip_frontmatter(Path(orig_path).read_text())
|
|
30
|
+
pilot_body, _ = strip_frontmatter(Path(pilot_path).read_text())
|
|
31
|
+
o, p = len(orig_body), len(pilot_body)
|
|
32
|
+
r = p / o
|
|
33
|
+
ratios.append(r)
|
|
34
|
+
sha_o = iron_law_sha(orig_body)
|
|
35
|
+
sha_p = iron_law_sha(pilot_body)
|
|
36
|
+
match = "OK" if sha_o == sha_p else "FAIL"
|
|
37
|
+
budget = "OK" if p <= 1500 else f"+{p - 1500}"
|
|
38
|
+
print(f"{rid:25s} {o:6d} {p:6d} {r:6.3f} {budget:>7s} {sha_o:>16s} {sha_p:>16s} {match:>3s}")
|
|
39
|
+
|
|
40
|
+
mean = sum(ratios) / len(ratios)
|
|
41
|
+
median = statistics.median(ratios)
|
|
42
|
+
print()
|
|
43
|
+
print(f"r-values : {[round(x, 3) for x in ratios]}")
|
|
44
|
+
print(f"mean r = {mean:.3f}")
|
|
45
|
+
print(f"median r = {median:.3f}")
|
|
46
|
+
print(f"max r = {max(ratios):.3f}")
|
|
47
|
+
print(f"min r = {min(ratios):.3f}")
|
|
48
|
+
print()
|
|
49
|
+
|
|
50
|
+
TOTAL = 32403
|
|
51
|
+
print(f"Projected always-bucket @ r=mean ({mean:.3f}) : {int(TOTAL * mean):>6d} (target ≤ 25000)")
|
|
52
|
+
print(f"Projected always-bucket @ r=max ({max(ratios):.3f}) : {int(TOTAL * max(ratios)):>6d} (target ≤ 25000)")
|
|
53
|
+
print(f"Projected always-bucket @ r=med ({median:.3f}) : {int(TOTAL * median):>6d} (target ≤ 25000)")
|
|
@@ -35,9 +35,15 @@ from scripts.ai_council.orchestrator import render
|
|
|
35
35
|
|
|
36
36
|
REPO_ROOT = Path(__file__).resolve().parents[2]
|
|
37
37
|
SESSIONS_DIR = REPO_ROOT / "agents" / "council-sessions"
|
|
38
|
+
QUESTIONS_DIR = REPO_ROOT / "agents" / "council-questions"
|
|
39
|
+
RESPONSES_DIR = REPO_ROOT / "agents" / "council-responses"
|
|
38
40
|
SETTINGS_FILE = REPO_ROOT / ".agent-settings.yml"
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
# Default retention for all council artefacts (questions, responses,
|
|
43
|
+
# sessions). Overridden by `ai_council.session_retention_days`
|
|
44
|
+
# in `.agent-settings.yml`. Council files are local-only scratch — short
|
|
45
|
+
# retention keeps the working tree from accumulating dead weight.
|
|
46
|
+
DEFAULT_RETENTION_DAYS = 7
|
|
41
47
|
_TS_RE = re.compile(r"^(\d{4})-(\d{2})-(\d{2})T(\d{2})-(\d{2})-(\d{2})Z$")
|
|
42
48
|
|
|
43
49
|
|
|
@@ -152,6 +158,92 @@ def prune_old_sessions(
|
|
|
152
158
|
return removed
|
|
153
159
|
|
|
154
160
|
|
|
161
|
+
def prune_old_artifacts(
|
|
162
|
+
artifact_dir: Path,
|
|
163
|
+
retention_days: int,
|
|
164
|
+
*,
|
|
165
|
+
now: _dt.datetime | None = None,
|
|
166
|
+
) -> list[Path]:
|
|
167
|
+
"""Delete files and timestamp-less directories older than `retention_days`.
|
|
168
|
+
|
|
169
|
+
mtime-based — used for `agents/council-questions/`,
|
|
170
|
+
`agents/council-responses/`, and root-level files in
|
|
171
|
+
`agents/council-sessions/` that don't match the
|
|
172
|
+
timestamp-subdir convention handled by `prune_old_sessions`.
|
|
173
|
+
|
|
174
|
+
Walks the directory non-recursively. For files: deletes when
|
|
175
|
+
mtime predates the cutoff. For sub-directories without a
|
|
176
|
+
timestamp name: deletes recursively when mtime predates the
|
|
177
|
+
cutoff. Never raises — disk failures log to stderr.
|
|
178
|
+
|
|
179
|
+
Returns the list of deleted paths. `retention_days <= 0`
|
|
180
|
+
disables pruning and returns an empty list.
|
|
181
|
+
"""
|
|
182
|
+
if retention_days <= 0 or not artifact_dir.exists():
|
|
183
|
+
return []
|
|
184
|
+
cutoff = (now or _dt.datetime.now(_dt.timezone.utc)) - _dt.timedelta(days=retention_days)
|
|
185
|
+
cutoff_ts = cutoff.timestamp()
|
|
186
|
+
removed: list[Path] = []
|
|
187
|
+
try:
|
|
188
|
+
entries = list(artifact_dir.iterdir())
|
|
189
|
+
except OSError as exc: # noqa: BLE001 - never block the report
|
|
190
|
+
print(f"[council:session] artifact iterdir failed: {exc}", file=sys.stderr)
|
|
191
|
+
return removed
|
|
192
|
+
for entry in entries:
|
|
193
|
+
# Timestamp subdirs are owned by prune_old_sessions; skip them
|
|
194
|
+
# so the two pruners don't race.
|
|
195
|
+
if entry.is_dir() and _parse_session_timestamp(entry.name) is not None:
|
|
196
|
+
continue
|
|
197
|
+
try:
|
|
198
|
+
mtime = entry.stat().st_mtime
|
|
199
|
+
except OSError as exc: # noqa: BLE001 - never block the report
|
|
200
|
+
print(f"[council:session] artifact stat failed for {entry}: {exc}",
|
|
201
|
+
file=sys.stderr)
|
|
202
|
+
continue
|
|
203
|
+
if mtime >= cutoff_ts:
|
|
204
|
+
continue
|
|
205
|
+
try:
|
|
206
|
+
if entry.is_dir():
|
|
207
|
+
shutil.rmtree(entry)
|
|
208
|
+
else:
|
|
209
|
+
entry.unlink()
|
|
210
|
+
removed.append(entry)
|
|
211
|
+
except OSError as exc: # noqa: BLE001 - never block the report
|
|
212
|
+
print(f"[council:session] artifact remove failed for {entry}: {exc}",
|
|
213
|
+
file=sys.stderr)
|
|
214
|
+
return removed
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def prune_all_council_artifacts(
|
|
218
|
+
retention_days: int | None = None,
|
|
219
|
+
*,
|
|
220
|
+
repo_root: Path | None = None,
|
|
221
|
+
now: _dt.datetime | None = None,
|
|
222
|
+
) -> dict[str, list[Path]]:
|
|
223
|
+
"""Prune every council artefact dir under `repo_root` in one pass.
|
|
224
|
+
|
|
225
|
+
Reads `retention_days` from settings if not supplied. Used by the
|
|
226
|
+
`task council-prune` target and by `save()`. Never raises.
|
|
227
|
+
|
|
228
|
+
Returns a dict keyed by directory label — `sessions`,
|
|
229
|
+
`questions`, `responses` — each mapped to the list of
|
|
230
|
+
paths actually removed.
|
|
231
|
+
"""
|
|
232
|
+
root = repo_root or REPO_ROOT
|
|
233
|
+
days = _load_retention_days() if retention_days is None else retention_days
|
|
234
|
+
sessions = root / "agents" / "council-sessions"
|
|
235
|
+
questions = root / "agents" / "council-questions"
|
|
236
|
+
responses = root / "agents" / "council-responses"
|
|
237
|
+
return {
|
|
238
|
+
"sessions": (
|
|
239
|
+
prune_old_sessions(sessions, days, now=now)
|
|
240
|
+
+ prune_old_artifacts(sessions, days, now=now)
|
|
241
|
+
),
|
|
242
|
+
"questions": prune_old_artifacts(questions, days, now=now),
|
|
243
|
+
"responses": prune_old_artifacts(responses, days, now=now),
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
|
|
155
247
|
def save(
|
|
156
248
|
*,
|
|
157
249
|
manifest: SessionManifest,
|
|
@@ -167,10 +259,12 @@ def save(
|
|
|
167
259
|
- `Iterable[list[CouncilResponse]]` — multi-round, one list per
|
|
168
260
|
round in execution order.
|
|
169
261
|
|
|
170
|
-
`retention_days` controls auto-pruning of older
|
|
171
|
-
after the new one is written
|
|
172
|
-
|
|
173
|
-
|
|
262
|
+
`retention_days` controls auto-pruning of older council artefacts
|
|
263
|
+
after the new one is written — sibling sessions plus, when
|
|
264
|
+
`sessions_dir` is not overridden, files in `council-questions/`
|
|
265
|
+
and `council-responses/`. `None` reads the value
|
|
266
|
+
from `.agent-settings.yml` (`ai_council.session_retention_days`,
|
|
267
|
+
default `7`); `0` disables pruning.
|
|
174
268
|
|
|
175
269
|
Disk-write failures are surfaced via a stderr line but do not
|
|
176
270
|
raise; the caller's text report is the source of truth.
|
|
@@ -232,5 +326,13 @@ def save(
|
|
|
232
326
|
|
|
233
327
|
days = _load_retention_days() if retention_days is None else retention_days
|
|
234
328
|
prune_old_sessions(base, days)
|
|
329
|
+
prune_old_artifacts(base, days)
|
|
330
|
+
# In production (no sessions_dir override), also prune the sibling
|
|
331
|
+
# council artefact dirs so questions/responses aren't left as dead
|
|
332
|
+
# weight. Tests that pass an explicit sessions_dir stay isolated
|
|
333
|
+
# from the wider tree.
|
|
334
|
+
if sessions_dir is None:
|
|
335
|
+
prune_old_artifacts(QUESTIONS_DIR, days)
|
|
336
|
+
prune_old_artifacts(RESPONSES_DIR, days)
|
|
235
337
|
|
|
236
338
|
return session_dir
|
|
@@ -76,15 +76,13 @@ WORKSPACE: list[RuleEntry] = [
|
|
|
76
76
|
RuleEntry("reviewer-awareness"),
|
|
77
77
|
RuleEntry("scope-control"),
|
|
78
78
|
RuleEntry("security-sensitive-stop"),
|
|
79
|
-
RuleEntry("think-before-action",
|
|
80
|
-
strip_sections=["Consult memory before editing"]),
|
|
79
|
+
RuleEntry("think-before-action"),
|
|
81
80
|
RuleEntry("verify-before-complete"),
|
|
82
|
-
RuleEntry("cli-output-handling",
|
|
83
|
-
strip_sections=["Iron Law — rtk first, tail/grep fallback"]),
|
|
81
|
+
RuleEntry("cli-output-handling"),
|
|
84
82
|
RuleEntry("downstream-changes"),
|
|
85
83
|
RuleEntry("improve-before-implement"),
|
|
86
84
|
RuleEntry("language-and-tone", "degraded",
|
|
87
|
-
strip_sections=["`.md` files
|
|
85
|
+
strip_sections=["`.md` files — ALWAYS English"]),
|
|
88
86
|
RuleEntry("missing-tool-handling"),
|
|
89
87
|
RuleEntry("token-efficiency"),
|
|
90
88
|
RuleEntry("user-interaction"),
|
|
@@ -47,6 +47,26 @@ FAIL_THRESHOLD = 0.90
|
|
|
47
47
|
CONCENTRATION_SINGLE_PCT = 0.12
|
|
48
48
|
CONCENTRATION_TOP3_PCT = 0.30
|
|
49
49
|
|
|
50
|
+
# Transitional concentration allowlist — non-safety-floor rules whose
|
|
51
|
+
# extended share exceeds CONCENTRATION_SINGLE_PCT after the kernel-trim
|
|
52
|
+
# refactor (commit 4e771da `refactor(kernel): compress 8 kernel rules
|
|
53
|
+
# per P2.2 playbook + lock kernel`). Trimming safety-floor rules shrank
|
|
54
|
+
# the denominator, mechanically lifting non-floor rules' percentage
|
|
55
|
+
# share even though their absolute size did not grow. Each entry pins
|
|
56
|
+
# the measured extended-size ceiling at the day road-to-path-fixes was
|
|
57
|
+
# closed; growth above the ceiling regresses CI. Future kernel-aware
|
|
58
|
+
# trimming work retires entries here.
|
|
59
|
+
KNOWN_CONCENTRATION_BREACHES: dict[str, int] = {
|
|
60
|
+
"language-and-tone.md": 3_985,
|
|
61
|
+
"no-cheap-questions.md": 3_530,
|
|
62
|
+
}
|
|
63
|
+
# Top-3 non-floor concentration ceiling — same rationale as the
|
|
64
|
+
# per-rule allowlist above. The current top-3 sum (language-and-tone +
|
|
65
|
+
# scope-control-allowlisted + non-destructive-allowlisted) clears the
|
|
66
|
+
# 30 % cap; the entry below pins the measured ceiling. Future trim
|
|
67
|
+
# work drops this back to None (default 30 %).
|
|
68
|
+
KNOWN_TOP3_CONCENTRATION_CEILING: int | None = 10_900
|
|
69
|
+
|
|
50
70
|
# Q3=A locked safety-floor rules — out of scope for slimming and for the
|
|
51
71
|
# concentration check. Their size is intentional (Iron Laws + obligation
|
|
52
72
|
# surface), not drift. See road-to-structural-optimization Phase 5.
|
|
@@ -221,6 +241,12 @@ def _concentration_check(
|
|
|
221
241
|
Returns (single-rule breaches, top-3 breach or None). Q3=A locked
|
|
222
242
|
safety-floor rules are excluded from both numerator and the top-3
|
|
223
243
|
selection — their size is intentional, not drift.
|
|
244
|
+
|
|
245
|
+
Allowlisted rules in `KNOWN_CONCENTRATION_BREACHES` are exempted
|
|
246
|
+
from the per-rule cap as long as their extended size does not
|
|
247
|
+
exceed the recorded ceiling (regression guard). The top-3 cap is
|
|
248
|
+
relaxed to `KNOWN_TOP3_CONCENTRATION_CEILING` while that ceiling
|
|
249
|
+
is non-None.
|
|
224
250
|
"""
|
|
225
251
|
non_floor = [
|
|
226
252
|
(name, raw, ext) for name, raw, ext in sizes
|
|
@@ -229,15 +255,22 @@ def _concentration_check(
|
|
|
229
255
|
single_cap = total_ext * CONCENTRATION_SINGLE_PCT
|
|
230
256
|
top3_cap = total_ext * CONCENTRATION_TOP3_PCT
|
|
231
257
|
|
|
232
|
-
single_breaches = [
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
258
|
+
single_breaches: list[tuple[str, int, float]] = []
|
|
259
|
+
for name, _, ext in non_floor:
|
|
260
|
+
if ext <= single_cap:
|
|
261
|
+
continue
|
|
262
|
+
ceiling = KNOWN_CONCENTRATION_BREACHES.get(name)
|
|
263
|
+
if ceiling is not None and ext <= ceiling:
|
|
264
|
+
continue
|
|
265
|
+
single_breaches.append((name, ext, ext / total_ext))
|
|
266
|
+
|
|
237
267
|
top3_sum = sum(ext for _, _, ext in non_floor[:3])
|
|
268
|
+
effective_top3_cap = top3_cap
|
|
269
|
+
if KNOWN_TOP3_CONCENTRATION_CEILING is not None:
|
|
270
|
+
effective_top3_cap = max(top3_cap, KNOWN_TOP3_CONCENTRATION_CEILING)
|
|
238
271
|
top3_breach = (
|
|
239
272
|
(top3_sum, top3_sum / total_ext)
|
|
240
|
-
if top3_sum >
|
|
273
|
+
if top3_sum > effective_top3_cap else None
|
|
241
274
|
)
|
|
242
275
|
return single_breaches, top3_breach
|
|
243
276
|
|