@event4u/agent-config 1.16.0 → 1.17.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-audit.md → agents/audit.md} +4 -3
- package/.agent-src/commands/{agents-cleanup.md → agents/cleanup.md} +12 -6
- package/.agent-src/commands/{agents-prepare.md → agents/prepare.md} +4 -3
- package/.agent-src/commands/agents.md +46 -0
- package/.agent-src/commands/{chat-history-checkpoint.md → chat-history/checkpoint.md} +4 -4
- package/.agent-src/commands/{chat-history-clear.md → chat-history/clear.md} +4 -4
- package/.agent-src/commands/{chat-history-resume.md → chat-history/resume.md} +4 -4
- package/.agent-src/commands/chat-history/show.md +107 -0
- package/.agent-src/commands/chat-history.md +33 -89
- package/.agent-src/commands/{commit-in-chunks.md → commit/in-chunks.md} +15 -13
- package/.agent-src/commands/commit.md +22 -2
- package/.agent-src/commands/{context-create.md → context/create.md} +4 -3
- package/.agent-src/commands/{context-refactor.md → context/refactor.md} +4 -3
- package/.agent-src/commands/context.md +44 -0
- package/.agent-src/commands/{copilot-agents-init.md → copilot-agents/init.md} +4 -3
- package/.agent-src/commands/{copilot-agents-optimize.md → copilot-agents/optimize.md} +4 -3
- package/.agent-src/commands/copilot-agents.md +44 -0
- package/.agent-src/commands/council/default.md +221 -0
- package/.agent-src/commands/{council-design.md → council/design.md} +6 -5
- package/.agent-src/commands/{council-optimize.md → council/optimize.md} +7 -6
- package/.agent-src/commands/{council-pr.md → council/pr.md} +6 -5
- package/.agent-src/commands/council.md +47 -212
- package/.agent-src/commands/{create-pr-description.md → create-pr/description-only.md} +4 -2
- package/.agent-src/commands/create-pr.md +26 -5
- package/.agent-src/commands/{feature-dev.md → feature/dev.md} +5 -10
- package/.agent-src/commands/{feature-explore.md → feature/explore.md} +4 -8
- package/.agent-src/commands/{feature-plan.md → feature/plan.md} +4 -8
- package/.agent-src/commands/{feature-refactor.md → feature/refactor.md} +4 -8
- package/.agent-src/commands/{feature-roadmap.md → feature/roadmap.md} +6 -10
- package/.agent-src/commands/feature.md +6 -12
- package/.agent-src/commands/{fix-ci.md → fix/ci.md} +4 -8
- package/.agent-src/commands/{fix-portability.md → fix/portability.md} +4 -8
- package/.agent-src/commands/{fix-pr-bot-comments.md → fix/pr-bots.md} +4 -8
- package/.agent-src/commands/{fix-pr-developer-comments.md → fix/pr-developers.md} +4 -8
- package/.agent-src/commands/{fix-pr-comments.md → fix/pr.md} +7 -11
- package/.agent-src/commands/{fix-references.md → fix/refs.md} +4 -8
- package/.agent-src/commands/{fix-seeder.md → fix/seeder.md} +4 -8
- package/.agent-src/commands/fix.md +7 -13
- package/.agent-src/commands/{do-and-judge.md → judge/on-diff.md} +4 -3
- package/.agent-src/commands/judge/solo.md +90 -0
- package/.agent-src/commands/{do-in-steps.md → judge/steps.md} +4 -3
- package/.agent-src/commands/judge.md +35 -70
- package/.agent-src/commands/{memory-add.md → memory/add.md} +4 -3
- package/.agent-src/commands/{memory-full.md → memory/load.md} +4 -3
- package/.agent-src/commands/{memory-promote.md → memory/promote.md} +4 -3
- package/.agent-src/commands/{propose-memory.md → memory/propose.md} +4 -3
- package/.agent-src/commands/memory.md +48 -0
- package/.agent-src/commands/{module-create.md → module/create.md} +4 -3
- package/.agent-src/commands/{module-explore.md → module/explore.md} +4 -3
- package/.agent-src/commands/module.md +44 -0
- package/.agent-src/commands/{optimize-agents.md → optimize/agents.md} +4 -8
- package/.agent-src/commands/{optimize-augmentignore.md → optimize/augmentignore.md} +4 -9
- package/.agent-src/commands/{optimize-rtk-filters.md → optimize/rtk.md} +4 -8
- package/.agent-src/commands/{optimize-skills.md → optimize/skills.md} +4 -8
- package/.agent-src/commands/optimize.md +4 -10
- package/.agent-src/commands/{override-create.md → override/create.md} +4 -3
- package/.agent-src/commands/{override-manage.md → override/manage.md} +4 -3
- package/.agent-src/commands/override.md +44 -0
- package/.agent-src/commands/{roadmap-create.md → roadmap/create.md} +4 -3
- package/.agent-src/commands/{roadmap-execute.md → roadmap/execute.md} +4 -3
- package/.agent-src/commands/roadmap.md +44 -0
- package/.agent-src/commands/{tests-create.md → tests/create.md} +4 -3
- package/.agent-src/commands/{tests-execute.md → tests/execute.md} +4 -3
- package/.agent-src/commands/tests.md +44 -0
- package/.agent-src/contexts/communication/rules-auto/artifact-engagement-recording-mechanics.md +72 -0
- package/.agent-src/contexts/communication/rules-auto/augment-portability-mechanics.md +79 -0
- package/.agent-src/contexts/communication/rules-auto/augment-source-of-truth-mechanics.md +98 -0
- package/.agent-src/contexts/communication/rules-auto/cli-output-handling-mechanics.md +87 -0
- package/.agent-src/contexts/communication/rules-auto/command-suggestion-policy-mechanics.md +62 -0
- package/.agent-src/contexts/communication/rules-auto/docs-sync-mechanics.md +78 -0
- package/.agent-src/contexts/communication/rules-auto/package-ci-checks-mechanics.md +85 -0
- package/.agent-src/contexts/communication/rules-auto/review-routing-awareness-mechanics.md +65 -0
- package/.agent-src/contexts/communication/rules-auto/roadmap-progress-sync-mechanics.md +78 -0
- package/.agent-src/contexts/communication/rules-auto/skill-quality-mechanics.md +62 -0
- package/.agent-src/contexts/communication/rules-auto/slash-command-routing-policy-mechanics.md +55 -0
- package/.agent-src/contexts/communication/rules-auto/ui-audit-gate-mechanics.md +53 -0
- package/.agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +77 -0
- package/.agent-src/contexts/judges/no-consolidate-rationale.md +102 -0
- package/.agent-src/contexts/judges/persona-voice-rubric.md +140 -0
- package/.agent-src/rules/artifact-engagement-recording.md +13 -69
- package/.agent-src/rules/ask-when-uncertain.md +27 -42
- package/.agent-src/rules/augment-portability.md +15 -61
- package/.agent-src/rules/augment-source-of-truth.md +27 -93
- package/.agent-src/rules/cli-output-handling.md +10 -76
- package/.agent-src/rules/command-suggestion-policy.md +18 -59
- package/.agent-src/rules/commit-conventions.md +17 -14
- package/.agent-src/rules/direct-answers.md +34 -49
- package/.agent-src/rules/docker-commands.md +5 -5
- package/.agent-src/rules/docs-sync.md +15 -69
- package/.agent-src/rules/language-and-tone.md +48 -72
- package/.agent-src/rules/missing-tool-handling.md +28 -22
- package/.agent-src/rules/no-cheap-questions.md +45 -52
- package/.agent-src/rules/no-roadmap-references.md +73 -0
- package/.agent-src/rules/package-ci-checks.md +21 -61
- package/.agent-src/rules/preservation-guard.md +64 -29
- package/.agent-src/rules/review-routing-awareness.md +24 -43
- package/.agent-src/rules/roadmap-progress-sync.md +10 -71
- package/.agent-src/rules/security-sensitive-stop.md +8 -8
- package/.agent-src/rules/skill-quality.md +16 -48
- package/.agent-src/rules/slash-command-routing-policy.md +7 -4
- package/.agent-src/rules/think-before-action.md +52 -42
- package/.agent-src/rules/tool-safety.md +19 -16
- package/.agent-src/rules/ui-audit-gate.md +24 -38
- package/.agent-src/rules/user-interaction.md +13 -68
- package/.agent-src/skills/ai-council/SKILL.md +2 -0
- package/.agent-src/skills/api-testing/SKILL.md +1 -1
- package/.agent-src/skills/check-refs/SKILL.md +59 -40
- package/.agent-src/skills/conventional-commits-writing/SKILL.md +86 -28
- package/.agent-src/skills/copilot-agents-optimization/SKILL.md +5 -5
- package/.agent-src/skills/developer-like-execution/SKILL.md +4 -4
- package/.agent-src/skills/finishing-a-development-branch/SKILL.md +101 -65
- package/.agent-src/skills/flux/SKILL.md +30 -10
- package/.agent-src/skills/github-ci/SKILL.md +2 -2
- package/.agent-src/skills/judge-code-quality/SKILL.md +7 -8
- package/.agent-src/skills/judge-security-auditor/SKILL.md +4 -5
- package/.agent-src/skills/judge-test-coverage/SKILL.md +3 -4
- package/.agent-src/skills/lint-skills/SKILL.md +57 -39
- package/.agent-src/skills/md-language-check/SKILL.md +61 -39
- package/.agent-src/skills/override-management/SKILL.md +5 -5
- package/.agent-src/skills/quality-tools/SKILL.md +2 -2
- package/.agent-src/skills/react-shadcn-ui/SKILL.md +116 -43
- package/.agent-src/skills/readme-reviewer/SKILL.md +30 -29
- package/.agent-src/skills/readme-writing/SKILL.md +78 -53
- package/.agent-src/skills/readme-writing-package/SKILL.md +50 -47
- package/.agent-src/skills/receiving-code-review/SKILL.md +52 -47
- package/.agent-src/skills/refine-prompt/SKILL.md +0 -1
- package/.agent-src/skills/requesting-code-review/SKILL.md +35 -30
- package/.agent-src/skills/security/SKILL.md +7 -2
- package/.agent-src/skills/security-audit/SKILL.md +7 -3
- package/.agent-src/skills/systematic-debugging/SKILL.md +68 -60
- package/.agent-src/skills/test-driven-development/SKILL.md +59 -57
- package/.agent-src/skills/test-performance/SKILL.md +0 -1
- package/.agent-src/skills/traefik/SKILL.md +4 -4
- package/.agent-src/skills/verify-completion-evidence/SKILL.md +28 -26
- package/.claude-plugin/marketplace.json +22 -11
- package/AGENTS.md +2 -2
- package/CHANGELOG.md +90 -1
- package/README.md +18 -17
- package/docs/architecture.md +4 -6
- package/docs/catalog.md +67 -39
- package/docs/contracts/STABILITY.md +13 -7
- package/docs/contracts/adr-chat-history-split.md +1 -3
- package/docs/contracts/adr-command-suggestion.md +0 -2
- package/docs/contracts/adr-implement-ticket-runtime.md +1 -2
- package/docs/contracts/adr-product-ui-track.md +3 -6
- package/docs/contracts/adr-prompt-driven-execution.md +3 -4
- package/docs/contracts/agent-memory-contract.md +6 -11
- package/docs/contracts/artifact-engagement-flow.md +6 -9
- package/docs/contracts/command-clusters.md +56 -46
- package/docs/contracts/command-suggestion-flow.md +1 -3
- package/docs/contracts/context-paths.md +99 -0
- package/docs/contracts/file-ownership-matrix.json +6722 -0
- package/docs/contracts/file-ownership-matrix.md +134 -0
- package/docs/contracts/implement-ticket-flow.md +6 -9
- package/docs/contracts/linear-ai-rules-inclusion.md +0 -1
- package/docs/contracts/linear-ai-three-layers.md +0 -2
- package/docs/contracts/load-context-budget-model.md +178 -0
- package/docs/contracts/load-context-schema.md +1 -3
- package/docs/contracts/rule-interactions.md +0 -1
- package/docs/contracts/rule-priority-hierarchy.md +1 -1
- package/docs/contracts/ui-track-flow.md +7 -17
- package/docs/customization.md +2 -0
- package/docs/getting-started.md +5 -4
- package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +100 -0
- package/package.json +1 -1
- package/scripts/_one_off_phase4_dispatch_latency.py +108 -0
- package/scripts/_one_off_phase6_trigger_jaccard.py +92 -0
- package/scripts/_phase2_shim_helper.py +109 -0
- package/scripts/agent-config +10 -0
- package/scripts/ai_council/_one_off_2a4_acceptance.py +208 -0
- package/scripts/ai_council/_one_off_context_layer_v1_estimate.py +67 -0
- package/scripts/ai_council/_one_off_context_layer_v1_review.py +292 -0
- package/scripts/ai_council/_one_off_followups_review.py +259 -0
- package/scripts/ai_council/_one_off_nondestructive_inline_audit.py +209 -0
- package/scripts/ai_council/_one_off_phase_2a_budget_rebalance.py +257 -0
- package/scripts/ai_council/_one_off_phase_2a_post_revert.py +197 -0
- package/scripts/ai_council/_one_off_rule_hardening_v1.py +251 -0
- package/scripts/ai_council/_one_off_structural_open_questions.py +232 -0
- package/scripts/ai_council/_one_off_structural_optimization.py +144 -0
- package/scripts/ai_council/_one_off_structural_v3_gaps.py +252 -0
- package/scripts/ai_council/_one_off_structural_v3_review.py +240 -0
- package/scripts/check_always_budget.py +363 -45
- package/scripts/check_cluster_patterns.py +159 -0
- package/scripts/check_command_count_messaging.py +14 -7
- package/scripts/check_context_paths.py +201 -0
- package/scripts/check_no_roadmap_refs.py +155 -0
- package/scripts/check_phase_coupling.py +148 -0
- package/scripts/check_portability.py +2 -0
- package/scripts/check_references.py +29 -2
- package/scripts/check_safety_floor_untouched.py +125 -0
- package/scripts/command_suggester/loader.py +4 -1
- package/scripts/compress.py +59 -13
- package/scripts/generate_index.py +6 -2
- package/scripts/generate_ownership_matrix.py +323 -0
- package/scripts/hooks/augment-roadmap-progress.sh +57 -0
- package/scripts/install.py +49 -28
- package/scripts/lint_no_new_atomic_commands.py +12 -11
- package/scripts/requirements-evals.txt +1 -0
- package/scripts/roadmap_progress_hook.py +159 -0
- package/scripts/schemas/command.schema.json +4 -3
- package/scripts/skill_linter.py +1 -0
- package/scripts/sync_agent_settings.py +25 -2
- package/scripts/update_counts.py +7 -0
|
@@ -43,24 +43,24 @@ class Violation:
|
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
def load_locked_clusters() -> set[str]:
|
|
46
|
-
"""Parse the
|
|
46
|
+
"""Parse the locked cluster table from the contract."""
|
|
47
47
|
text = (ROOT / CLUSTER_CONTRACT).read_text(encoding="utf-8")
|
|
48
|
-
# Locate the
|
|
49
|
-
|
|
48
|
+
# Locate the locked-clusters table; cluster names sit in backticks in column 1.
|
|
49
|
+
in_table = False
|
|
50
50
|
clusters: set[str] = set()
|
|
51
51
|
for line in text.splitlines():
|
|
52
|
-
if line.startswith("##
|
|
53
|
-
|
|
52
|
+
if line.startswith("## Locked clusters"):
|
|
53
|
+
in_table = True
|
|
54
54
|
continue
|
|
55
|
-
if
|
|
55
|
+
if in_table and line.startswith("## "):
|
|
56
56
|
break
|
|
57
|
-
if
|
|
57
|
+
if in_table:
|
|
58
58
|
m = re.match(r"\|\s*`([a-z][a-z0-9-]*)`\s*\|", line)
|
|
59
59
|
if m:
|
|
60
60
|
clusters.add(m.group(1))
|
|
61
61
|
if not clusters:
|
|
62
62
|
print(
|
|
63
|
-
f"❌ Could not parse
|
|
63
|
+
f"❌ Could not parse locked-clusters table from {CLUSTER_CONTRACT}",
|
|
64
64
|
file=sys.stderr,
|
|
65
65
|
)
|
|
66
66
|
sys.exit(3)
|
|
@@ -83,7 +83,7 @@ def added_command_files(baseline: str) -> list[Path]:
|
|
|
83
83
|
file=sys.stderr)
|
|
84
84
|
sys.exit(3)
|
|
85
85
|
files = [Path(p) for p in result.stdout.splitlines()
|
|
86
|
-
if p.endswith(".md") and p != ""]
|
|
86
|
+
if p.endswith(".md") and p != "" and Path(p).name != "AGENTS.md"]
|
|
87
87
|
# Also include untracked (newly added, uncommitted) files.
|
|
88
88
|
try:
|
|
89
89
|
wt = subprocess.run(
|
|
@@ -97,7 +97,7 @@ def added_command_files(baseline: str) -> list[Path]:
|
|
|
97
97
|
if status.strip() not in ("A", "??", "AM"):
|
|
98
98
|
continue
|
|
99
99
|
path = line[3:].strip().split(" -> ")[-1]
|
|
100
|
-
if path.endswith(".md"):
|
|
100
|
+
if path.endswith(".md") and Path(path).name != "AGENTS.md":
|
|
101
101
|
p = Path(path)
|
|
102
102
|
if p not in files:
|
|
103
103
|
files.append(p)
|
|
@@ -107,7 +107,8 @@ def added_command_files(baseline: str) -> list[Path]:
|
|
|
107
107
|
|
|
108
108
|
|
|
109
109
|
def all_command_files() -> list[Path]:
|
|
110
|
-
return sorted((ROOT / COMMANDS_DIR).
|
|
110
|
+
return sorted(p for p in (ROOT / COMMANDS_DIR).rglob("*.md")
|
|
111
|
+
if p.name != "AGENTS.md")
|
|
111
112
|
|
|
112
113
|
|
|
113
114
|
def parse_frontmatter(path: Path) -> dict[str, str]:
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Platform-agnostic PostToolUse hook for the `roadmap-progress-sync` rule.
|
|
3
|
+
|
|
4
|
+
Reads a JSON event from stdin (Augment / Claude / Cursor / Cline /
|
|
5
|
+
Windsurf / Gemini PostToolUse-shaped envelopes), decides whether the
|
|
6
|
+
tool call wrote to a roadmap file under `agents/roadmaps/`, and — when
|
|
7
|
+
it did — re-runs `update_roadmap_progress.py` so the dashboard stays
|
|
8
|
+
in sync without depending on agent self-discipline.
|
|
9
|
+
|
|
10
|
+
Exit code is **always 0**. Hooks must never block the agent loop; the
|
|
11
|
+
worst-case is a no-op when stdin is malformed or the regenerator is
|
|
12
|
+
missing.
|
|
13
|
+
|
|
14
|
+
Output discipline:
|
|
15
|
+
- stdout: nothing (Augment would surface stdout to the user)
|
|
16
|
+
- stderr: one short line in --verbose mode, otherwise silent
|
|
17
|
+
|
|
18
|
+
CLI:
|
|
19
|
+
python3 scripts/roadmap_progress_hook.py [--platform NAME] [--verbose]
|
|
20
|
+
|
|
21
|
+
The `--platform` flag is informational only — the filter logic reads
|
|
22
|
+
the same field names across platforms (tool_name, tool_input.path,
|
|
23
|
+
file_changes[].path).
|
|
24
|
+
"""
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
import argparse
|
|
28
|
+
import json
|
|
29
|
+
import subprocess
|
|
30
|
+
import sys
|
|
31
|
+
from pathlib import Path
|
|
32
|
+
|
|
33
|
+
# Tools whose successful execution can write to a roadmap file. We keep
|
|
34
|
+
# the list explicit so an unknown tool name (e.g. a new MCP tool that
|
|
35
|
+
# happens to mention a roadmap path in its input) does not trigger a
|
|
36
|
+
# spurious regeneration.
|
|
37
|
+
WRITE_TOOLS = frozenset({
|
|
38
|
+
"str-replace-editor",
|
|
39
|
+
"save-file",
|
|
40
|
+
"remove-files",
|
|
41
|
+
# Claude Code / Cursor naming variants — kept for cross-platform
|
|
42
|
+
# parity if this hook is ever wired beyond Augment.
|
|
43
|
+
"Edit",
|
|
44
|
+
"Write",
|
|
45
|
+
"MultiEdit",
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
ROADMAP_PREFIX = "agents/roadmaps/"
|
|
49
|
+
# Paths under these subtrees are tracked but not part of the open list
|
|
50
|
+
# the dashboard summarises — regenerating on every archived edit would
|
|
51
|
+
# be wasteful. The check still fires on the parent dir itself.
|
|
52
|
+
ROADMAP_EXCLUDED_PARTS = frozenset({"archive", "skipped"})
|
|
53
|
+
DASHBOARD_PATH = "agents/roadmaps-progress.md"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _candidate_paths(payload: dict) -> list[str]:
|
|
57
|
+
"""Pull every plausible file path out of a PostToolUse payload."""
|
|
58
|
+
out: list[str] = []
|
|
59
|
+
fc = payload.get("file_changes")
|
|
60
|
+
if isinstance(fc, list):
|
|
61
|
+
for entry in fc:
|
|
62
|
+
if isinstance(entry, dict):
|
|
63
|
+
p = entry.get("path")
|
|
64
|
+
if isinstance(p, str) and p:
|
|
65
|
+
out.append(p)
|
|
66
|
+
ti = payload.get("tool_input")
|
|
67
|
+
if isinstance(ti, dict):
|
|
68
|
+
for key in ("path", "file_path", "target_file"):
|
|
69
|
+
v = ti.get(key)
|
|
70
|
+
if isinstance(v, str) and v:
|
|
71
|
+
out.append(v)
|
|
72
|
+
return out
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _is_roadmap_touch(path: str) -> bool:
|
|
76
|
+
"""Return True if `path` is a roadmap file we should react to."""
|
|
77
|
+
norm = path.lstrip("./").replace("\\", "/")
|
|
78
|
+
if not norm.startswith(ROADMAP_PREFIX):
|
|
79
|
+
return False
|
|
80
|
+
if norm == DASHBOARD_PATH:
|
|
81
|
+
# Defensive — the dashboard sits at agents/roadmaps-progress.md,
|
|
82
|
+
# NOT inside agents/roadmaps/. The prefix check above already
|
|
83
|
+
# excludes it, but keep this explicit so a future relocation
|
|
84
|
+
# cannot turn the hook into an infinite loop.
|
|
85
|
+
return False
|
|
86
|
+
rest = norm[len(ROADMAP_PREFIX):]
|
|
87
|
+
parts = rest.split("/")
|
|
88
|
+
if len(parts) >= 2 and parts[0] in ROADMAP_EXCLUDED_PARTS:
|
|
89
|
+
return False
|
|
90
|
+
if not norm.endswith(".md"):
|
|
91
|
+
return False
|
|
92
|
+
return True
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _resolve_regenerator(consumer_root: Path) -> Path | None:
|
|
96
|
+
"""Find the regenerator script — package-shipped or installed copy."""
|
|
97
|
+
for candidate in (
|
|
98
|
+
consumer_root / ".augment" / "scripts" / "update_roadmap_progress.py",
|
|
99
|
+
consumer_root / ".agent-src" / "scripts" / "update_roadmap_progress.py",
|
|
100
|
+
consumer_root / ".agent-src.uncompressed" / "scripts" / "update_roadmap_progress.py",
|
|
101
|
+
):
|
|
102
|
+
if candidate.is_file():
|
|
103
|
+
return candidate
|
|
104
|
+
return None
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def run(stdin_text: str, *, consumer_root: Path, verbose: bool = False) -> int:
|
|
108
|
+
payload: dict = {}
|
|
109
|
+
if stdin_text.strip():
|
|
110
|
+
try:
|
|
111
|
+
decoded = json.loads(stdin_text)
|
|
112
|
+
if isinstance(decoded, dict):
|
|
113
|
+
payload = decoded
|
|
114
|
+
except json.JSONDecodeError:
|
|
115
|
+
return 0 # malformed stdin → silent no-op, never block
|
|
116
|
+
|
|
117
|
+
tool = payload.get("tool_name") or payload.get("toolName") or payload.get("tool")
|
|
118
|
+
if not isinstance(tool, str) or tool not in WRITE_TOOLS:
|
|
119
|
+
return 0
|
|
120
|
+
|
|
121
|
+
paths = _candidate_paths(payload)
|
|
122
|
+
if not any(_is_roadmap_touch(p) for p in paths):
|
|
123
|
+
return 0
|
|
124
|
+
|
|
125
|
+
script = _resolve_regenerator(consumer_root)
|
|
126
|
+
if script is None:
|
|
127
|
+
if verbose:
|
|
128
|
+
print("roadmap-progress-hook: regenerator not found, skipping",
|
|
129
|
+
file=sys.stderr)
|
|
130
|
+
return 0
|
|
131
|
+
|
|
132
|
+
try:
|
|
133
|
+
subprocess.run(
|
|
134
|
+
[sys.executable, str(script)],
|
|
135
|
+
cwd=consumer_root, check=False,
|
|
136
|
+
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
|
|
137
|
+
timeout=30,
|
|
138
|
+
)
|
|
139
|
+
except (OSError, subprocess.SubprocessError):
|
|
140
|
+
pass # never propagate regenerator failures into the agent loop
|
|
141
|
+
|
|
142
|
+
if verbose:
|
|
143
|
+
print(f"roadmap-progress-hook: regenerated for tool={tool}",
|
|
144
|
+
file=sys.stderr)
|
|
145
|
+
return 0
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def main(argv: list[str] | None = None) -> int:
|
|
149
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
150
|
+
parser.add_argument("--platform", default="generic",
|
|
151
|
+
help="informational platform tag (augment/claude/...)")
|
|
152
|
+
parser.add_argument("--verbose", action="store_true",
|
|
153
|
+
help="emit one stderr line per invocation")
|
|
154
|
+
args = parser.parse_args(argv)
|
|
155
|
+
return run(sys.stdin.read(), consumer_root=Path.cwd(), verbose=args.verbose)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
if __name__ == "__main__": # pragma: no cover
|
|
159
|
+
sys.exit(main())
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"properties": {
|
|
10
10
|
"name": {
|
|
11
11
|
"type": "string",
|
|
12
|
-
"pattern": "^[a-z][a-z0-9-]
|
|
12
|
+
"pattern": "^[a-z][a-z0-9-]*(:[a-z][a-z0-9-]*)?$",
|
|
13
|
+
"$comment": "Top-level commands use the bare slug (`commit`). Nested cluster commands under `commands/<cluster>/<sub>.md` use the colon form (`council:default`) to mirror Claude Code's `/cluster:sub` rendering. Directory slug for `.claude/skills/` is the hyphenated form (`council-default`), generated by compress.py."
|
|
13
14
|
},
|
|
14
15
|
"description": {
|
|
15
16
|
"type": "string",
|
|
@@ -40,8 +41,8 @@
|
|
|
40
41
|
},
|
|
41
42
|
"superseded_by": {
|
|
42
43
|
"type": "string",
|
|
43
|
-
"pattern": "^[a-z][a-z0-9-]*( [a-z][a-z0-9-]*)?$",
|
|
44
|
-
"description": "Set on deprecation shims. Format: '<cluster> <sub>' (e.g. 'fix ci'). See docs/contracts/command-clusters.md § Deprecation shim contract."
|
|
44
|
+
"pattern": "^[a-z][a-z0-9-]*( (--[a-z][a-z0-9-]*|[a-z][a-z0-9-]*))?$",
|
|
45
|
+
"description": "Set on deprecation shims. Format: '<cluster> <sub>' (e.g. 'fix ci') or '<cluster> --<flag>' for flag-clusters (e.g. 'commit --in-chunks'). See docs/contracts/command-clusters.md § Deprecation shim contract."
|
|
45
46
|
},
|
|
46
47
|
"deprecated_in": {
|
|
47
48
|
"type": "string",
|
package/scripts/skill_linter.py
CHANGED
|
@@ -886,6 +886,7 @@ def lint_command(path: Path, text: str) -> LintResult:
|
|
|
886
886
|
"error", "shim_missing_warning",
|
|
887
887
|
"Deprecation shim must contain a one-line warning matching "
|
|
888
888
|
"'⚠️ /<old-name> is deprecated; use /<cluster> <sub> instead.'"
|
|
889
|
+
" (or '/<cluster> --<flag>' for flag-clusters)"
|
|
889
890
|
" (see docs/contracts/command-clusters.md § Deprecation shim contract)"
|
|
890
891
|
))
|
|
891
892
|
|
|
@@ -136,8 +136,31 @@ def _append_unknown(body: str, user_flat: dict[str, object], known: set[str]) ->
|
|
|
136
136
|
|
|
137
137
|
|
|
138
138
|
def render_target(template_body: str, user_data: dict) -> str:
|
|
139
|
-
"""Return the desired `.agent-settings.yml` body for the given user data.
|
|
140
|
-
|
|
139
|
+
"""Return the desired `.agent-settings.yml` body for the given user data.
|
|
140
|
+
|
|
141
|
+
The trailing ``_user:`` block (emitted by :func:`_append_unknown`) is
|
|
142
|
+
already in dotted-key form on every read after the first sync. Re-
|
|
143
|
+
flattening it would prepend another ``_user.`` segment on every run
|
|
144
|
+
and accumulate forever, so we strip the wrapper and merge its
|
|
145
|
+
contents straight into the flat dict.
|
|
146
|
+
"""
|
|
147
|
+
if user_data:
|
|
148
|
+
user_only = user_data.pop("_user", None) if isinstance(user_data, dict) else None
|
|
149
|
+
user_flat = _flatten(user_data)
|
|
150
|
+
if isinstance(user_only, dict):
|
|
151
|
+
for key, value in user_only.items():
|
|
152
|
+
# Dotted keys round-trip verbatim — never re-flatten them.
|
|
153
|
+
if isinstance(key, str):
|
|
154
|
+
# Heal legacy corruption: pre-fix syncs prepended a
|
|
155
|
+
# `_user.` segment per run, so a key may carry an
|
|
156
|
+
# arbitrary number of them. Strip them all back to
|
|
157
|
+
# the original leaf path.
|
|
158
|
+
healed = key
|
|
159
|
+
while healed.startswith("_user."):
|
|
160
|
+
healed = healed[len("_user."):]
|
|
161
|
+
user_flat[healed] = value
|
|
162
|
+
else:
|
|
163
|
+
user_flat = {}
|
|
141
164
|
known = _template_keys(template_body)
|
|
142
165
|
body = _apply_user_values(template_body, user_flat)
|
|
143
166
|
return _append_unknown(body, user_flat, known)
|
package/scripts/update_counts.py
CHANGED
|
@@ -37,6 +37,13 @@ def count(kind: str) -> int:
|
|
|
37
37
|
if not pdir.exists():
|
|
38
38
|
return 0
|
|
39
39
|
return sum(1 for f in pdir.glob("*.md") if f.name != "README.md")
|
|
40
|
+
if kind == "commands":
|
|
41
|
+
# Commands may be flat (`commands/<name>.md`) or nested under a
|
|
42
|
+
# cluster directory (`commands/<cluster>/<sub>.md`). Walk the tree
|
|
43
|
+
# and skip the AGENTS.md reference orchestrator.
|
|
44
|
+
return sum(
|
|
45
|
+
1 for f in (SRC / kind).rglob("*.md") if f.name != "AGENTS.md"
|
|
46
|
+
)
|
|
40
47
|
return sum(1 for _ in (SRC / kind).glob("*.md"))
|
|
41
48
|
|
|
42
49
|
|