@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
package/scripts/skill_linter.py
CHANGED
|
@@ -117,6 +117,17 @@ VALID_RULE_TYPES = {"always", "auto"}
|
|
|
117
117
|
VALID_RULE_SOURCES = {"package", "project"}
|
|
118
118
|
VALID_STATUSES = {"active", "deprecated", "superseded"}
|
|
119
119
|
|
|
120
|
+
# --- Router schema (docs/contracts/rule-router.md) ---
|
|
121
|
+
ROUTER_ALLOWED_TRIGGER_KEYS = {"keyword", "phrase", "intent", "file_pattern",
|
|
122
|
+
"path_prefix", "command"}
|
|
123
|
+
ROUTER_ALLOWED_PROFILES = {"minimal", "balanced", "full"}
|
|
124
|
+
KERNEL_RULE_IDS: set[str] = {
|
|
125
|
+
"agent-authority", "ask-when-uncertain", "commit-policy",
|
|
126
|
+
"direct-answers", "language-and-tone", "no-cheap-questions",
|
|
127
|
+
"non-destructive-by-default", "scope-control",
|
|
128
|
+
"verify-before-complete",
|
|
129
|
+
}
|
|
130
|
+
|
|
120
131
|
# --- Runtime execution metadata constants ---
|
|
121
132
|
VALID_EXECUTION_TYPES = {"manual", "assisted", "automated"}
|
|
122
133
|
VALID_EXECUTION_HANDLERS = {"none", "shell", "php", "node", "internal"}
|
|
@@ -220,6 +231,42 @@ def extract_sections(text: str) -> set[str]:
|
|
|
220
231
|
return {match.group(1).strip() for match in SECTION_PATTERN.finditer(text)}
|
|
221
232
|
|
|
222
233
|
|
|
234
|
+
def _count_code_blocks(text: str) -> int:
|
|
235
|
+
"""Return the number of fenced code blocks (``` … ```) in *text*."""
|
|
236
|
+
fence_count = 0
|
|
237
|
+
for line in text.splitlines():
|
|
238
|
+
stripped = line.lstrip()
|
|
239
|
+
if stripped.startswith("```"):
|
|
240
|
+
fence_count += 1
|
|
241
|
+
return fence_count // 2
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def _fenced_content_ratio(text: str) -> float:
|
|
245
|
+
"""Return the fraction of non-empty lines that sit inside fenced blocks.
|
|
246
|
+
|
|
247
|
+
Used as a structural signal: rules / files dominated by verbatim Iron-Law
|
|
248
|
+
blocks or worked examples score high and are exempted from raw line-count
|
|
249
|
+
warnings (council review 2026-05-06).
|
|
250
|
+
"""
|
|
251
|
+
inside = False
|
|
252
|
+
fenced_lines = 0
|
|
253
|
+
non_empty = 0
|
|
254
|
+
for line in text.splitlines():
|
|
255
|
+
stripped = line.strip()
|
|
256
|
+
if stripped.startswith("```"):
|
|
257
|
+
inside = not inside
|
|
258
|
+
if stripped:
|
|
259
|
+
non_empty += 1
|
|
260
|
+
continue
|
|
261
|
+
if stripped:
|
|
262
|
+
non_empty += 1
|
|
263
|
+
if inside:
|
|
264
|
+
fenced_lines += 1
|
|
265
|
+
if non_empty == 0:
|
|
266
|
+
return 0.0
|
|
267
|
+
return fenced_lines / non_empty
|
|
268
|
+
|
|
269
|
+
|
|
223
270
|
def extract_description(text: str) -> Optional[str]:
|
|
224
271
|
frontmatter = FRONTMATTER_PATTERN.search(text)
|
|
225
272
|
if not frontmatter:
|
|
@@ -495,8 +542,12 @@ def lint_skill(path: Path, text: str) -> LintResult:
|
|
|
495
542
|
suggestions.append("Add a requirement-checking or validation step before implementation")
|
|
496
543
|
|
|
497
544
|
# --- Size check (see guidelines/agent-infra/size-and-scope.md) ---
|
|
545
|
+
# Threshold raised from 300 → 400 (council review 2026-05-06): reference-rich
|
|
546
|
+
# skills (quality-tools 411, ai-council 399, project-analyzer 341) legitimately
|
|
547
|
+
# exceed 300 lines without being split-candidates. Structural follow-up tracked
|
|
548
|
+
# in agents/roadmaps/road-to-structural-linter-reform.md.
|
|
498
549
|
total_lines = len(text.splitlines())
|
|
499
|
-
if total_lines >
|
|
550
|
+
if total_lines > 400:
|
|
500
551
|
issues.append(Issue("warning", "skill_too_large", f"Skill has {total_lines} lines; review for split (see size-and-scope guideline)"))
|
|
501
552
|
|
|
502
553
|
# --- Pointer-only / guideline-dependent skill detection ---
|
|
@@ -553,6 +604,131 @@ def extract_frontmatter(text: str) -> Optional[str]:
|
|
|
553
604
|
return match.group(1) if match else None
|
|
554
605
|
|
|
555
606
|
|
|
607
|
+
def _parse_yaml_list(frontmatter: str, key: str) -> Optional[list]:
|
|
608
|
+
"""Parse a simple top-level YAML list `key:` from frontmatter.
|
|
609
|
+
|
|
610
|
+
Supports the two shapes we emit in rule frontmatter:
|
|
611
|
+
triggers:
|
|
612
|
+
- keyword: "foo"
|
|
613
|
+
- phrase: "bar baz"
|
|
614
|
+
routes_to:
|
|
615
|
+
- skill:php-coder
|
|
616
|
+
- guideline:agent-infra/asking-and-brevity-examples
|
|
617
|
+
|
|
618
|
+
Returns ``None`` if the key is absent (so the caller can distinguish
|
|
619
|
+
"missing" from "empty"); returns ``[]`` for an explicitly empty list.
|
|
620
|
+
"""
|
|
621
|
+
lines = frontmatter.splitlines()
|
|
622
|
+
out: list = []
|
|
623
|
+
in_block = False
|
|
624
|
+
for line in lines:
|
|
625
|
+
if not in_block:
|
|
626
|
+
if line.startswith(f"{key}:"):
|
|
627
|
+
rhs = line[len(key) + 1:].strip()
|
|
628
|
+
if rhs in ("", "[]"):
|
|
629
|
+
if rhs == "[]":
|
|
630
|
+
return []
|
|
631
|
+
in_block = True
|
|
632
|
+
else:
|
|
633
|
+
return None # unexpected scalar shape
|
|
634
|
+
continue
|
|
635
|
+
if line.startswith(" - "):
|
|
636
|
+
item = line[4:].strip()
|
|
637
|
+
if ":" in item and not item.startswith(("'", '"')):
|
|
638
|
+
k, _, v = item.partition(":")
|
|
639
|
+
out.append({k.strip(): v.strip().strip('"').strip("'")})
|
|
640
|
+
else:
|
|
641
|
+
out.append(item.strip('"').strip("'"))
|
|
642
|
+
elif line.strip() == "" or line.startswith(" "):
|
|
643
|
+
continue
|
|
644
|
+
else:
|
|
645
|
+
break
|
|
646
|
+
return out if in_block else None
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
def lint_router_frontmatter(rule_id: str, frontmatter: str,
|
|
650
|
+
rule_type: Optional[str]) -> List[Issue]:
|
|
651
|
+
"""Validate `triggers:` / `routes_to:` per docs/contracts/rule-router.md.
|
|
652
|
+
|
|
653
|
+
Strict checks (always errors): kernel rules MUST NOT carry router fields;
|
|
654
|
+
`triggers:` items must use one allowed key; `routes_to:` items must
|
|
655
|
+
follow `kind:id` with kind ∈ {skill, guideline} and the target file
|
|
656
|
+
must exist on disk.
|
|
657
|
+
|
|
658
|
+
Lenient checks (info-level until Phase 4 migrations land): non-kernel
|
|
659
|
+
rules without `triggers:` / `routes_to:` get an informational note,
|
|
660
|
+
not an error — the existing description-matching path still works.
|
|
661
|
+
"""
|
|
662
|
+
issues: List[Issue] = []
|
|
663
|
+
triggers = _parse_yaml_list(frontmatter, "triggers")
|
|
664
|
+
routes_to = _parse_yaml_list(frontmatter, "routes_to")
|
|
665
|
+
|
|
666
|
+
is_kernel = rule_id in KERNEL_RULE_IDS or rule_type == "always"
|
|
667
|
+
|
|
668
|
+
if is_kernel:
|
|
669
|
+
if triggers is not None:
|
|
670
|
+
issues.append(Issue("error", "kernel_has_triggers",
|
|
671
|
+
"Kernel rules MUST NOT declare triggers: (kernel is unconditional)"))
|
|
672
|
+
if routes_to is not None:
|
|
673
|
+
issues.append(Issue("error", "kernel_has_routes_to",
|
|
674
|
+
"Kernel rules MUST NOT declare routes_to: (kernel body stays inline)"))
|
|
675
|
+
return issues
|
|
676
|
+
|
|
677
|
+
# Non-kernel rule path
|
|
678
|
+
if triggers is None:
|
|
679
|
+
issues.append(Issue("info", "router_triggers_missing",
|
|
680
|
+
"Non-kernel rule has no triggers: — falls back to description matching "
|
|
681
|
+
"until Phase 4 migration lands"))
|
|
682
|
+
else:
|
|
683
|
+
for idx, item in enumerate(triggers):
|
|
684
|
+
if not isinstance(item, dict) or len(item) != 1:
|
|
685
|
+
issues.append(Issue("error", "trigger_shape_invalid",
|
|
686
|
+
f"triggers[{idx}] must be a single-key mapping"))
|
|
687
|
+
continue
|
|
688
|
+
(k,) = item.keys()
|
|
689
|
+
if k not in ROUTER_ALLOWED_TRIGGER_KEYS:
|
|
690
|
+
allowed = ", ".join(sorted(ROUTER_ALLOWED_TRIGGER_KEYS))
|
|
691
|
+
issues.append(Issue("error", "trigger_key_unknown",
|
|
692
|
+
f"triggers[{idx}] key '{k}' not in allowed set ({allowed})"))
|
|
693
|
+
|
|
694
|
+
if routes_to is None:
|
|
695
|
+
issues.append(Issue("info", "router_routes_to_missing",
|
|
696
|
+
"Non-kernel rule has no routes_to: — body should migrate to skill / "
|
|
697
|
+
"guideline in Phase 4"))
|
|
698
|
+
else:
|
|
699
|
+
repo_root = Path(__file__).resolve().parent.parent
|
|
700
|
+
for idx, item in enumerate(routes_to):
|
|
701
|
+
if not isinstance(item, str) or ":" not in item:
|
|
702
|
+
issues.append(Issue("error", "route_shape_invalid",
|
|
703
|
+
f"routes_to[{idx}] must be 'kind:id'"))
|
|
704
|
+
continue
|
|
705
|
+
kind, _, target_id = item.partition(":")
|
|
706
|
+
if kind == "skill":
|
|
707
|
+
target = repo_root / ".agent-src.uncompressed" / "skills" / target_id / "SKILL.md"
|
|
708
|
+
elif kind == "guideline":
|
|
709
|
+
target = repo_root / "docs" / "guidelines" / f"{target_id}.md"
|
|
710
|
+
elif kind == "command":
|
|
711
|
+
target = repo_root / ".agent-src.uncompressed" / "commands" / f"{target_id}.md"
|
|
712
|
+
elif kind == "contract":
|
|
713
|
+
# Contracts live in two places: stable host docs in
|
|
714
|
+
# docs/contracts/ and load-bearing flows in
|
|
715
|
+
# .agent-src.uncompressed/contexts/contracts/ (road-to-path-fixes
|
|
716
|
+
# P4 / Council R2). Try both before failing.
|
|
717
|
+
target = repo_root / "docs" / "contracts" / f"{target_id}.md"
|
|
718
|
+
if not target.exists():
|
|
719
|
+
alt = repo_root / ".agent-src.uncompressed" / "contexts" / "contracts" / f"{target_id}.md"
|
|
720
|
+
if alt.exists():
|
|
721
|
+
target = alt
|
|
722
|
+
else:
|
|
723
|
+
issues.append(Issue("error", "route_kind_unknown",
|
|
724
|
+
f"routes_to[{idx}] kind '{kind}' must be 'skill', 'guideline', 'command', or 'contract'"))
|
|
725
|
+
continue
|
|
726
|
+
if not target.exists():
|
|
727
|
+
issues.append(Issue("error", "route_target_missing",
|
|
728
|
+
f"routes_to[{idx}] target '{item}' not found at {target}"))
|
|
729
|
+
return issues
|
|
730
|
+
|
|
731
|
+
|
|
556
732
|
def extract_frontmatter_field(frontmatter: str, pattern: re.Pattern[str]) -> Optional[str]:
|
|
557
733
|
match = pattern.search(frontmatter)
|
|
558
734
|
return match.group(1).strip() if match else None
|
|
@@ -801,6 +977,9 @@ def lint_rule(path: Path, text: str) -> LintResult:
|
|
|
801
977
|
f"Always-rule with topic-specific description ({', '.join(topic_keywords)}) — "
|
|
802
978
|
f"consider auto type per rule-type-governance"))
|
|
803
979
|
|
|
980
|
+
# Router schema validation (docs/contracts/rule-router.md, Phase 3.3).
|
|
981
|
+
issues.extend(lint_router_frontmatter(path.stem, frontmatter, rule_type))
|
|
982
|
+
|
|
804
983
|
# --- Structure checks ---
|
|
805
984
|
# H1 heading
|
|
806
985
|
if not H1_PATTERN.search(text):
|
|
@@ -817,14 +996,18 @@ def lint_rule(path: Path, text: str) -> LintResult:
|
|
|
817
996
|
issues.append(Issue("warning", "double_blank_lines", "File contains double or triple blank lines"))
|
|
818
997
|
|
|
819
998
|
# --- Content checks (see guidelines/agent-infra/size-and-scope.md) ---
|
|
999
|
+
# Length thresholds gated by fenced-content density (council review 2026-05-06):
|
|
1000
|
+
# rules dominated by verbatim Iron-Law blocks / worked examples are protected
|
|
1001
|
+
# from the > 40 / > 60 warnings. Hard error at 200 stays unconditional.
|
|
820
1002
|
line_count = len([line for line in text.splitlines() if line.strip()])
|
|
821
1003
|
total_lines = len(text.splitlines())
|
|
1004
|
+
fenced_ratio = _fenced_content_ratio(text)
|
|
822
1005
|
if total_lines > 200:
|
|
823
1006
|
issues.append(Issue("error", "rule_too_large", f"Rule has {total_lines} lines (hard limit: 200); must split or move to guideline"))
|
|
824
|
-
elif line_count > 60:
|
|
825
|
-
issues.append(Issue("warning", "long_rule", f"Rule has {line_count} non-empty lines; prefer < 60 (see size-and-scope guideline)"))
|
|
826
|
-
elif line_count > 40:
|
|
827
|
-
issues.append(Issue("warning", "long_rule", f"Rule has {line_count} non-empty lines; rules should be concise"))
|
|
1007
|
+
elif line_count > 60 and fenced_ratio < 0.30:
|
|
1008
|
+
issues.append(Issue("warning", "long_rule", f"Rule has {line_count} non-empty lines (fenced-content {fenced_ratio:.0%}); prefer < 60 (see size-and-scope guideline)"))
|
|
1009
|
+
elif line_count > 40 and fenced_ratio < 0.30:
|
|
1010
|
+
issues.append(Issue("warning", "long_rule", f"Rule has {line_count} non-empty lines (fenced-content {fenced_ratio:.0%}); rules should be concise"))
|
|
828
1011
|
|
|
829
1012
|
for bad_sign in RULE_BAD_SIGNS:
|
|
830
1013
|
if bad_sign in text:
|
|
@@ -859,7 +1042,7 @@ def _lint_command_suggestion_block(text: str) -> List[Issue]:
|
|
|
859
1042
|
suggestion = data.get("suggestion")
|
|
860
1043
|
if suggestion is None:
|
|
861
1044
|
issues.append(Issue(
|
|
862
|
-
"
|
|
1045
|
+
"error", "missing_suggestion_block",
|
|
863
1046
|
"Command frontmatter is missing the 'suggestion' block — required by "
|
|
864
1047
|
"road-to-context-aware-command-suggestion Phase 2.",
|
|
865
1048
|
))
|
|
@@ -969,9 +1152,16 @@ def lint_command(path: Path, text: str) -> LintResult:
|
|
|
969
1152
|
issues.append(Issue("warning", "no_steps", "Command has no Steps section or numbered sub-headings"))
|
|
970
1153
|
|
|
971
1154
|
# --- Size check (see guidelines/agent-infra/size-and-scope.md) ---
|
|
1155
|
+
# Word threshold (1000) gated by structural delegation signal (council review
|
|
1156
|
+
# 2026-05-06): well-factored orchestrators with ≥ 5 sub-sections AND ≥ 3 code
|
|
1157
|
+
# blocks are exempt — the size reflects dispatch breadth, not bloat.
|
|
972
1158
|
word_count = len(text.split())
|
|
973
1159
|
if word_count > 1000:
|
|
974
|
-
|
|
1160
|
+
section_count = len(sections)
|
|
1161
|
+
code_block_count = _count_code_blocks(text)
|
|
1162
|
+
delegation_signal = section_count >= 5 and code_block_count >= 3
|
|
1163
|
+
if not delegation_signal:
|
|
1164
|
+
issues.append(Issue("warning", "large_command", f"Command has {word_count} words (target: 200-600, max ~1000); {section_count} sub-sections, {code_block_count} code blocks — lacks delegation structure"))
|
|
975
1165
|
|
|
976
1166
|
# File must end with exactly one newline
|
|
977
1167
|
if not text.endswith("\n"):
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Smoke-test path resolution against the package's own `.augment/` projection.
|
|
3
|
+
|
|
4
|
+
Per `agents/roadmaps/road-to-path-fixes.md` Phase 7 (Council Decision 3,
|
|
5
|
+
2026-05-06): the package's `.augment/` tree has the same shape as the
|
|
6
|
+
`.augment/` tree a consumer would receive after `scripts/install.sh`.
|
|
7
|
+
If `load_context:` entries resolve cleanly here, they resolve cleanly
|
|
8
|
+
in any consumer.
|
|
9
|
+
|
|
10
|
+
What it does:
|
|
11
|
+
- Walks `.augment/rules/*.md`.
|
|
12
|
+
- Parses each rule's YAML frontmatter.
|
|
13
|
+
- Resolves every `load_context:` and `load_context_eager:` entry
|
|
14
|
+
against the rule file's directory.
|
|
15
|
+
- Reports any miss with a file:entry line.
|
|
16
|
+
|
|
17
|
+
Exit codes: 0 = all entries resolve, 1 = one or more misses, 3 = no
|
|
18
|
+
`.augment/rules/` directory found (run `task sync` first).
|
|
19
|
+
"""
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import sys
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
|
|
25
|
+
import yaml
|
|
26
|
+
|
|
27
|
+
ROOT = Path(__file__).resolve().parent.parent
|
|
28
|
+
AUGMENT_RULES = ROOT / ".augment" / "rules"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _split_frontmatter(text: str):
|
|
32
|
+
if not text.startswith("---\n"):
|
|
33
|
+
return None
|
|
34
|
+
end = text.find("\n---\n", 4)
|
|
35
|
+
if end == -1:
|
|
36
|
+
return None
|
|
37
|
+
try:
|
|
38
|
+
fm = yaml.safe_load(text[4:end])
|
|
39
|
+
except yaml.YAMLError:
|
|
40
|
+
return None
|
|
41
|
+
return fm if isinstance(fm, dict) else {}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _check_rule(rule_file: Path, misses: list[tuple[str, str]]) -> int:
|
|
45
|
+
fm = _split_frontmatter(rule_file.read_text(encoding="utf-8"))
|
|
46
|
+
if not fm:
|
|
47
|
+
return 0
|
|
48
|
+
checked = 0
|
|
49
|
+
rule_dir = rule_file.parent
|
|
50
|
+
for key in ("load_context", "load_context_eager"):
|
|
51
|
+
entries = fm.get(key) or []
|
|
52
|
+
if not isinstance(entries, list):
|
|
53
|
+
continue
|
|
54
|
+
for entry in entries:
|
|
55
|
+
if not isinstance(entry, str):
|
|
56
|
+
continue
|
|
57
|
+
checked += 1
|
|
58
|
+
target = (rule_dir / entry).resolve()
|
|
59
|
+
if not target.is_file():
|
|
60
|
+
misses.append((str(rule_file.relative_to(ROOT)), entry))
|
|
61
|
+
return checked
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def main() -> int:
|
|
65
|
+
if not AUGMENT_RULES.is_dir():
|
|
66
|
+
print(
|
|
67
|
+
f"❌ {AUGMENT_RULES.relative_to(ROOT)} not found — run `task sync` first",
|
|
68
|
+
file=sys.stderr,
|
|
69
|
+
)
|
|
70
|
+
return 3
|
|
71
|
+
|
|
72
|
+
misses: list[tuple[str, str]] = []
|
|
73
|
+
rule_count = 0
|
|
74
|
+
entry_count = 0
|
|
75
|
+
for rule_file in sorted(AUGMENT_RULES.glob("*.md")):
|
|
76
|
+
rule_count += 1
|
|
77
|
+
entry_count += _check_rule(rule_file, misses)
|
|
78
|
+
|
|
79
|
+
if misses:
|
|
80
|
+
print(f"❌ {len(misses)} unresolved load_context entr(y/ies):")
|
|
81
|
+
for rule, entry in misses:
|
|
82
|
+
print(f" {rule} → {entry!r}")
|
|
83
|
+
return 1
|
|
84
|
+
|
|
85
|
+
print(
|
|
86
|
+
f"✅ smoke-path-resolution clean "
|
|
87
|
+
f"({rule_count} rules, {entry_count} load_context entr(y/ies) resolved)"
|
|
88
|
+
)
|
|
89
|
+
return 0
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
if __name__ == "__main__":
|
|
93
|
+
sys.exit(main())
|
|
@@ -157,15 +157,55 @@ def _parse_yaml_block(body: str) -> dict[str, Any]:
|
|
|
157
157
|
def _consume_block_list(lines: list[str], start: int) -> tuple[list[Any], int]:
|
|
158
158
|
items: list[Any] = []
|
|
159
159
|
i = start
|
|
160
|
+
item_indent: int | None = None
|
|
160
161
|
while i < len(lines):
|
|
161
162
|
line = lines[i]
|
|
162
163
|
if not line.strip():
|
|
163
164
|
i += 1
|
|
164
165
|
continue
|
|
165
166
|
stripped = line.lstrip()
|
|
167
|
+
leading = len(line) - len(stripped)
|
|
166
168
|
if not stripped.startswith("- "):
|
|
169
|
+
# Out of the list — caller resumes.
|
|
167
170
|
break
|
|
168
|
-
|
|
171
|
+
if item_indent is None:
|
|
172
|
+
item_indent = leading
|
|
173
|
+
elif leading != item_indent:
|
|
174
|
+
break
|
|
175
|
+
item_body = stripped[2:].strip()
|
|
176
|
+
# Inline mapping inside the list: `- key: value`
|
|
177
|
+
m = re.match(r"^([\w-]+):\s*(.*)$", item_body)
|
|
178
|
+
if m:
|
|
179
|
+
mapping: dict[str, Any] = {}
|
|
180
|
+
key = m.group(1)
|
|
181
|
+
raw = m.group(2).strip()
|
|
182
|
+
mapping[key] = _coerce(raw) if raw != "" else ""
|
|
183
|
+
# Consume continuation lines that are indented past the dash —
|
|
184
|
+
# they belong to the same mapping item (`pattern: …`, `reason: …`).
|
|
185
|
+
cont_indent = item_indent + 2 # `- ` is two chars
|
|
186
|
+
i += 1
|
|
187
|
+
while i < len(lines):
|
|
188
|
+
cont = lines[i]
|
|
189
|
+
if not cont.strip():
|
|
190
|
+
i += 1
|
|
191
|
+
continue
|
|
192
|
+
cont_stripped = cont.lstrip()
|
|
193
|
+
cont_leading = len(cont) - len(cont_stripped)
|
|
194
|
+
if cont_stripped.startswith("- "):
|
|
195
|
+
break
|
|
196
|
+
if cont_leading <= item_indent:
|
|
197
|
+
break
|
|
198
|
+
cm = re.match(r"^([\w-]+):\s*(.*)$", cont_stripped)
|
|
199
|
+
if cm and cont_leading >= cont_indent:
|
|
200
|
+
ckey = cm.group(1)
|
|
201
|
+
cval = cm.group(2).strip()
|
|
202
|
+
mapping[ckey] = _coerce(cval) if cval != "" else ""
|
|
203
|
+
i += 1
|
|
204
|
+
else:
|
|
205
|
+
break
|
|
206
|
+
items.append(mapping)
|
|
207
|
+
continue
|
|
208
|
+
items.append(_coerce(item_body))
|
|
169
209
|
i += 1
|
|
170
210
|
return items, i - start
|
|
171
211
|
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: roadmap:execute
|
|
3
|
-
cluster: roadmap
|
|
4
|
-
sub: execute
|
|
5
|
-
skills: [agent-docs-writing]
|
|
6
|
-
description: Read and interactively execute a roadmap from agents/roadmaps/
|
|
7
|
-
disable-model-invocation: true
|
|
8
|
-
suggestion:
|
|
9
|
-
eligible: true
|
|
10
|
-
trigger_description: "execute the roadmap, work through the roadmap step by step"
|
|
11
|
-
trigger_context: "existing agents/roadmaps/*.md referenced in the prompt"
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
# /roadmap execute
|
|
15
|
-
## Instructions
|
|
16
|
-
|
|
17
|
-
### 1. Find the roadmap
|
|
18
|
-
|
|
19
|
-
- List all roadmap files: `agents/roadmaps/*.md` (project root) and `app/Modules/*/agents/roadmaps/*.md` (modules).
|
|
20
|
-
- Exclude `template.md`.
|
|
21
|
-
- If only one roadmap exists → use it (confirm with user).
|
|
22
|
-
- If multiple exist → present a numbered list and let the user choose.
|
|
23
|
-
- If none exist → tell the user and suggest running `roadmap-create`.
|
|
24
|
-
|
|
25
|
-
### 2. Read and understand the roadmap
|
|
26
|
-
|
|
27
|
-
- Read the full roadmap file.
|
|
28
|
-
- Identify the **phases** and **steps/tasks** within each phase.
|
|
29
|
-
- Determine which steps are already completed (look for checkboxes `[x]`, status markers, or "done" notes).
|
|
30
|
-
- Present a summary to the user:
|
|
31
|
-
> "Roadmap: {title}"
|
|
32
|
-
> "Phase 1: {name} — 3/5 Schritte erledigt"
|
|
33
|
-
> "Phase 2: {name} — noch nicht begonnen"
|
|
34
|
-
> "Next open step: {step description}"
|
|
35
|
-
|
|
36
|
-
### 3. Resolve quality cadence (read once, before any step runs)
|
|
37
|
-
|
|
38
|
-
Read `roadmap.quality_cadence` from `.agent-settings.yml`:
|
|
39
|
-
|
|
40
|
-
| Value | When the project's quality pipeline runs |
|
|
41
|
-
|---|---|
|
|
42
|
-
| `end_of_roadmap` (default) | Once, in step 7 — before archiving |
|
|
43
|
-
| `per_phase` | Once after every completed phase, plus step 7 |
|
|
44
|
-
| `per_step` | After every completed step, plus step 7 (legacy verbose) |
|
|
45
|
-
|
|
46
|
-
Missing key, unreadable file, or unknown value → fall back to `end_of_roadmap`.
|
|
47
|
-
Cite the resolved cadence once in step 2's summary so the user can override it.
|
|
48
|
-
|
|
49
|
-
The Iron Law `verify-before-complete` still applies — fresh quality
|
|
50
|
-
output is mandatory before any "roadmap complete" claim, regardless of
|
|
51
|
-
cadence. Step checkboxes and `agents/roadmaps-progress.md` are ALWAYS
|
|
52
|
-
updated in the same response per `roadmap-progress-sync`; cadence only
|
|
53
|
-
gates the *quality pipeline*, not progress tracking.
|
|
54
|
-
|
|
55
|
-
### 4. Execute step by step
|
|
56
|
-
|
|
57
|
-
For each open step:
|
|
58
|
-
|
|
59
|
-
1. **Summarize** what needs to be done (in the user's language).
|
|
60
|
-
2. **Analyze** the codebase to understand what's needed for this step.
|
|
61
|
-
3. **Present a plan** — what files to change, what approach to take.
|
|
62
|
-
4. **Ask for confirmation**: "Should I implement this step?"
|
|
63
|
-
- If yes → implement, mark the step `[x]` in the roadmap file.
|
|
64
|
-
- If no / skip → move to the next step.
|
|
65
|
-
- If the user wants to stop → stop and summarize progress.
|
|
66
|
-
|
|
67
|
-
### 5. After each step
|
|
68
|
-
|
|
69
|
-
- Update the roadmap file: mark the completed step `[x]` (or `[~]` / `[-]`).
|
|
70
|
-
- Regenerate `agents/roadmaps-progress.md` — `./agent-config roadmap:progress`.
|
|
71
|
-
- **Quality pipeline** — run only when `quality_cadence: per_step`.
|
|
72
|
-
Otherwise skip and proceed.
|
|
73
|
-
- Ask: "Continue with the next step?"
|
|
74
|
-
|
|
75
|
-
### 6. After all steps in a phase
|
|
76
|
-
|
|
77
|
-
- Summarize what was accomplished in the phase.
|
|
78
|
-
- **Quality pipeline** — run when `quality_cadence: per_phase` (or `per_step`).
|
|
79
|
-
Skip when `end_of_roadmap`.
|
|
80
|
-
- Ask: "Phase {N} complete. Continue with Phase {N+1}?"
|
|
81
|
-
|
|
82
|
-
### 7. When done (or stopped)
|
|
83
|
-
|
|
84
|
-
- Summarize total progress: steps completed, steps remaining.
|
|
85
|
-
- Update the roadmap file with the current status.
|
|
86
|
-
- Regenerate the dashboard one last time so it matches the final state.
|
|
87
|
-
- **If ALL steps are done** → run the project's quality pipeline now
|
|
88
|
-
(this is the `verify-before-complete` evidence gate; required for
|
|
89
|
-
every cadence value, including `end_of_roadmap`). On green, trigger
|
|
90
|
-
the completion & archiving workflow from the `roadmap-management`
|
|
91
|
-
skill. On red, stop, surface the failures, do not archive.
|
|
92
|
-
|
|
93
|
-
### Rules
|
|
94
|
-
|
|
95
|
-
- **Commits are governed by [`commit-policy`](../rules/commit-policy.md).**
|
|
96
|
-
By default: only apply local changes and update the roadmap file — no commits.
|
|
97
|
-
- If the roadmap **does not** contain explicit commit steps → never commit, never ask.
|
|
98
|
-
- If the roadmap **does** contain explicit commit steps:
|
|
99
|
-
- **Non-autonomous** (`personal.autonomy: off`, or `auto` before opt-in) →
|
|
100
|
-
ask before each commit step.
|
|
101
|
-
- **Autonomous** (`personal.autonomy: on`, or `auto` after opt-in) →
|
|
102
|
-
pre-scan the roadmap **before starting**, ask **once** upfront whether
|
|
103
|
-
to execute the listed commit steps, then proceed silently per the answer.
|
|
104
|
-
- **Push, merge, branch, PR, tag** stay permission-gated by [`scope-control`](../rules/scope-control.md#git-operations--permission-gated).
|
|
105
|
-
- **Always ask before implementing** a step — never auto-execute.
|
|
106
|
-
- **Quality cadence** is set by `roadmap.quality_cadence` (see step 3).
|
|
107
|
-
Step 7 always runs the pipeline before archival regardless of cadence.
|
|
108
|
-
- If a step is unclear or too large, suggest breaking it down further.
|
|
109
|
-
- If a step reveals a problem not covered in the roadmap, flag it to the user.
|
package/.agent-src/contexts/communication/rules-auto/artifact-engagement-recording-mechanics.md
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
# Artifact Engagement Recording — mechanics
|
|
2
|
-
|
|
3
|
-
CLI invocation, privacy contract, failure-mode handling, and "what
|
|
4
|
-
this rule does NOT do" catalog for the
|
|
5
|
-
[`artifact-engagement-recording`](../../../rules/artifact-engagement-recording.md)
|
|
6
|
-
rule. The activation gate, cadence table, and consulted-vs-applied
|
|
7
|
-
definitions live in the rule; this file is the lookup material for
|
|
8
|
-
the actual `telemetry:record` call and the privacy floor.
|
|
9
|
-
|
|
10
|
-
## What to record — id-only, no payload
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
./agent-config telemetry:record \
|
|
14
|
-
--task-id "$TASK_ID" \
|
|
15
|
-
--boundary task \
|
|
16
|
-
--consulted skills:php-coder \
|
|
17
|
-
--consulted skills:eloquent \
|
|
18
|
-
--consulted rules:scope-control \
|
|
19
|
-
--applied skills:php-coder \
|
|
20
|
-
--applied rules:scope-control
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
- `--task-id` — the ticket key (`PROJ-123`) for `/implement-ticket`, or a
|
|
24
|
-
short opaque slug derived from the prompt for `/work`. **Never** a
|
|
25
|
-
branch name, a file path, or a free-text title.
|
|
26
|
-
- `--boundary` — `task` or `phase-step`, matching the cadence in the rule.
|
|
27
|
-
- `--consulted <kind>:<id>` — repeat per artefact. `<kind>` is one of
|
|
28
|
-
`skills`, `rules`, `commands`, `guidelines`, `personas`.
|
|
29
|
-
- `--applied <kind>:<id>` — repeat per artefact actually applied.
|
|
30
|
-
- Exit `0` always when disabled (silent). Exit `1` on schema validation
|
|
31
|
-
failure (rule must NOT swallow this — surface to the user). Exit `2`
|
|
32
|
-
on IO failure.
|
|
33
|
-
|
|
34
|
-
## Privacy contract — what NEVER goes into a record
|
|
35
|
-
|
|
36
|
-
The CLI rejects most violations on the input boundary, but the agent must
|
|
37
|
-
not even attempt these:
|
|
38
|
-
|
|
39
|
-
- ❌ File paths (`src/Foo.php`, `tests/...`) — id fields are
|
|
40
|
-
artefact identifiers only.
|
|
41
|
-
- ❌ Source code, prompt text, ticket body, AC text.
|
|
42
|
-
- ❌ Branch names, commit shas, PR numbers, URLs.
|
|
43
|
-
- ❌ Secrets, env vars, credentials, customer data.
|
|
44
|
-
- ❌ Free-text strings longer than 200 chars (CLI enforces; agent must
|
|
45
|
-
not generate).
|
|
46
|
-
|
|
47
|
-
When in doubt → **don't record**. A missing event is cheap; a leaked
|
|
48
|
-
prompt is not.
|
|
49
|
-
|
|
50
|
-
## Failure modes — DO NOT block the user's task
|
|
51
|
-
|
|
52
|
-
- Schema rejection (CLI exit `1`) → log the message internally, continue
|
|
53
|
-
the user's task. Do **not** halt the dispatch loop.
|
|
54
|
-
- IO failure (CLI exit `2`) → same. The telemetry is **observation**, not
|
|
55
|
-
a delivery requirement.
|
|
56
|
-
- Settings malformed → already handled by the CLI: it falls back to
|
|
57
|
-
disabled and exits `0`. Agent treats it as "disabled this task".
|
|
58
|
-
|
|
59
|
-
The only error the agent surfaces is when the user explicitly asked for
|
|
60
|
-
recording (`telemetry:status` confirms enabled) but no event reached the
|
|
61
|
-
log — that is a real bug, not a swallowed error.
|
|
62
|
-
|
|
63
|
-
## What this rule does NOT do
|
|
64
|
-
|
|
65
|
-
- Run when `enabled: false` (cost floor is zero — see
|
|
66
|
-
[`tests/telemetry/test_cost_floor.py`](../../../../tests/telemetry/test_cost_floor.py)).
|
|
67
|
-
- Track the agent's tool calls, file reads, or token spend — that is
|
|
68
|
-
out of scope, see the roadmap's "out-of-scope" section.
|
|
69
|
-
- Decide retirement. Phase 4's aggregator + report renderer are the only
|
|
70
|
-
consumers that may interpret the JSONL.
|
|
71
|
-
- Run on cloud surfaces (Claude.ai Web, Skills API). The
|
|
72
|
-
`cloud_safe: noop` marker keeps it inert there.
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
# Augment portability — mechanics
|
|
2
|
-
|
|
3
|
-
`task`-to-script translation table, the `./agent-config` consumer-CLI
|
|
4
|
-
table, and the rationale behind both for the
|
|
5
|
-
[`augment-portability`](../../../rules/augment-portability.md) rule.
|
|
6
|
-
The portability obligation, the agnostic-content rules, and the
|
|
7
|
-
enforcement script reference live in the rule; this file is the
|
|
8
|
-
lookup material when an agent is about to write or edit an artefact
|
|
9
|
-
that mentions a runtime invocation.
|
|
10
|
-
|
|
11
|
-
## Why no `task` commands inside artefacts
|
|
12
|
-
|
|
13
|
-
Skills, rules, commands, guidelines, personas, and context docs
|
|
14
|
-
shipped by this package run in **consumer projects**. Consumer
|
|
15
|
-
projects may not have [Task](https://taskfile.dev) installed —
|
|
16
|
-
they might use npm scripts, Composer scripts, Make, or nothing at
|
|
17
|
-
all. A skill that instructs an agent to run `task <something>`
|
|
18
|
-
silently breaks in every project without a `Taskfile.yml`.
|
|
19
|
-
|
|
20
|
-
Task remains a convenience shortcut for maintainers working on the
|
|
21
|
-
package repo itself — `task ci` is the recommended local gate before
|
|
22
|
-
a PR and lives in `Taskfile.yml`, `AGENTS.md`, and the package README.
|
|
23
|
-
Those maintainer-facing surfaces are outside the scope of this rule.
|
|
24
|
-
Artefact files must assume Task is absent.
|
|
25
|
-
|
|
26
|
-
The detection pattern *"if the consumer has a `Makefile` / build
|
|
27
|
-
script, prefer its targets over raw commands"* is still allowed when
|
|
28
|
-
the skill adapts to the **consumer's own** tooling (e.g.
|
|
29
|
-
`tests-execute` detecting `php artisan test` vs `vendor/bin/pest`).
|
|
30
|
-
It is not allowed to reference `task <name>` as the detected target —
|
|
31
|
-
every direct invocation must resolve to a real script path.
|
|
32
|
-
|
|
33
|
-
## Translation table — `task` → script
|
|
34
|
-
|
|
35
|
-
| ❌ Forbidden | ✅ Portable |
|
|
36
|
-
|---|---|
|
|
37
|
-
| `task sync` | `bash scripts/compress.sh --sync` |
|
|
38
|
-
| `task sync-check` | `bash scripts/compress.sh --check` |
|
|
39
|
-
| `task sync-check-hashes` | `bash scripts/compress.sh --check-hashes` |
|
|
40
|
-
| `task sync-changed` | `bash scripts/compress.sh --changed` |
|
|
41
|
-
| `task sync-mark-done -- X` | `bash scripts/compress.sh --mark-done X` |
|
|
42
|
-
| `task generate-tools` | `python3 scripts/compress.py --generate-tools` |
|
|
43
|
-
| `task lint-skills` | `python3 scripts/skill_linter.py --all` |
|
|
44
|
-
| `task check-refs` | `python3 scripts/check_references.py` |
|
|
45
|
-
| `task check-portability` | `python3 scripts/check_portability.py` |
|
|
46
|
-
| `task check-compression` | `python3 scripts/check_compression.py` |
|
|
47
|
-
| `task validate-schema` | `python3 scripts/validate_frontmatter.py` |
|
|
48
|
-
| `task counts-check` | `python3 scripts/update_counts.py --check` |
|
|
49
|
-
| `task roadmap-progress` | `./agent-config roadmap:progress` |
|
|
50
|
-
| `task ci` | run each underlying script directly (no single portable equivalent) |
|
|
51
|
-
|
|
52
|
-
## Consumer CLI — `./agent-config`
|
|
53
|
-
|
|
54
|
-
A subset of package scripts is exposed through a project-local CLI
|
|
55
|
-
wrapper `./agent-config` (written into the project root by the
|
|
56
|
-
installer, gitignored). Artefacts MUST prefer the CLI over raw
|
|
57
|
-
`python3 scripts/…` paths for every command the CLI already covers,
|
|
58
|
-
because the raw paths only resolve inside the package repo — in a
|
|
59
|
-
consumer project the scripts live under `node_modules/` or `vendor/`.
|
|
60
|
-
|
|
61
|
-
| ❌ Forbidden in artefacts | ✅ Portable |
|
|
62
|
-
|---|---|
|
|
63
|
-
| `python3 scripts/mcp_render.py` | `./agent-config mcp:render` |
|
|
64
|
-
| `python3 scripts/mcp_render.py --check` | `./agent-config mcp:check` |
|
|
65
|
-
| `python3 .augment/scripts/update_roadmap_progress.py` | `./agent-config roadmap:progress` |
|
|
66
|
-
| `python3 .augment/scripts/update_roadmap_progress.py --check` | `./agent-config roadmap:progress-check` |
|
|
67
|
-
| `bash scripts/first-run.sh` | `./agent-config first-run` |
|
|
68
|
-
| `PYTHONPATH=… python3 -m implement_ticket` | `./agent-config implement-ticket` |
|
|
69
|
-
| `python3 scripts/memory_lookup.py` | `./agent-config memory:lookup` |
|
|
70
|
-
| `python3 scripts/memory_signal.py` | `./agent-config memory:signal` |
|
|
71
|
-
| `python3 scripts/memory_hash.py` | `./agent-config memory:hash` |
|
|
72
|
-
| `python3 scripts/check_memory.py` | `./agent-config memory:check` |
|
|
73
|
-
| `python3 scripts/check_memory_proposal.py` | `./agent-config memory:check-proposal` |
|
|
74
|
-
| `python3 scripts/check_proposal.py` | `./agent-config proposal:check` |
|
|
75
|
-
| `python3 scripts/refine_ticket_detect.py` | `./agent-config refine-ticket:detect` |
|
|
76
|
-
|
|
77
|
-
Commands not covered by the CLI stay as direct script invocations
|
|
78
|
-
(e.g. `bash scripts/compress.sh --sync`) — those are maintainer-only
|
|
79
|
-
and not reachable from a consumer project anyway.
|