@event4u/agent-config 1.15.0 → 1.16.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/bug-fix.md +1 -1
- package/.agent-src/commands/bug-investigate.md +2 -2
- package/.agent-src/commands/chat-history-checkpoint.md +1 -1
- package/.agent-src/commands/chat-history-clear.md +1 -1
- package/.agent-src/commands/chat-history.md +1 -1
- package/.agent-src/commands/check-current-md.md +1 -1
- package/.agent-src/commands/council-design.md +96 -0
- package/.agent-src/commands/council-optimize.md +115 -0
- package/.agent-src/commands/council-pr.md +123 -0
- package/.agent-src/commands/council.md +219 -0
- package/.agent-src/commands/create-pr.md +23 -0
- package/.agent-src/commands/do-and-judge.md +3 -3
- package/.agent-src/commands/do-in-steps.md +4 -4
- 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 +8 -0
- package/.agent-src/commands/feature-explore.md +6 -1
- package/.agent-src/commands/feature-plan.md +33 -2
- package/.agent-src/commands/feature-refactor.md +5 -0
- package/.agent-src/commands/feature-roadmap.md +6 -1
- package/.agent-src/commands/feature.md +58 -0
- package/.agent-src/commands/fix-ci.md +5 -0
- package/.agent-src/commands/fix-portability.md +5 -0
- package/.agent-src/commands/fix-pr-bot-comments.md +5 -0
- package/.agent-src/commands/fix-pr-comments.md +5 -0
- package/.agent-src/commands/fix-pr-developer-comments.md +5 -0
- package/.agent-src/commands/fix-references.md +5 -0
- package/.agent-src/commands/fix-seeder.md +5 -0
- package/.agent-src/commands/fix.md +60 -0
- package/.agent-src/commands/jira-ticket.md +1 -1
- package/.agent-src/commands/judge.md +1 -1
- package/.agent-src/commands/memory-add.md +3 -3
- package/.agent-src/commands/memory-full.md +2 -2
- package/.agent-src/commands/memory-promote.md +2 -2
- package/.agent-src/commands/mode.md +5 -5
- package/.agent-src/commands/onboard.md +3 -3
- package/.agent-src/commands/optimize-agents.md +6 -1
- package/.agent-src/commands/optimize-augmentignore.md +5 -0
- package/.agent-src/commands/optimize-rtk-filters.md +5 -0
- package/.agent-src/commands/optimize-skills.md +6 -1
- package/.agent-src/commands/optimize.md +54 -0
- package/.agent-src/commands/propose-memory.md +2 -2
- package/.agent-src/commands/review-changes.md +26 -1
- package/.agent-src/commands/review-routing.md +1 -1
- package/.agent-src/commands/roadmap-create.md +29 -2
- 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 +1 -1
- package/.agent-src/commands/upstream-contribute.md +1 -1
- package/.agent-src/contexts/authority/commit-mechanics.md +57 -0
- package/.agent-src/contexts/authority/destructive-mechanics.md +66 -0
- package/.agent-src/contexts/authority/scope-mechanics.md +87 -0
- package/.agent-src/contexts/execution/autonomy-detection.md +54 -0
- package/.agent-src/contexts/execution/autonomy-examples.md +90 -0
- package/.agent-src/contexts/execution/autonomy-mechanics.md +29 -0
- package/.agent-src/contexts/execution/verification-mechanics.md +80 -0
- package/.agent-src/personas/README.md +1 -1
- package/.agent-src/rules/agent-authority.md +24 -0
- package/.agent-src/rules/architecture.md +1 -1
- package/.agent-src/rules/artifact-drafting-protocol.md +1 -1
- package/.agent-src/rules/artifact-engagement-recording.md +1 -1
- package/.agent-src/rules/ask-when-uncertain.md +1 -1
- package/.agent-src/rules/autonomous-execution.md +78 -114
- package/.agent-src/rules/capture-learnings.md +1 -1
- package/.agent-src/rules/chat-history-cadence.md +3 -3
- package/.agent-src/rules/chat-history-ownership.md +3 -3
- package/.agent-src/rules/chat-history-visibility.md +3 -3
- package/.agent-src/rules/{command-suggestion.md → command-suggestion-policy.md} +7 -7
- package/.agent-src/rules/commit-conventions.md +1 -1
- package/.agent-src/rules/commit-policy.md +14 -42
- package/.agent-src/rules/context-hygiene.md +3 -3
- package/.agent-src/rules/direct-answers.md +1 -1
- package/.agent-src/rules/docs-sync.md +1 -1
- package/.agent-src/rules/e2e-testing.md +1 -1
- package/.agent-src/rules/guidelines.md +4 -4
- package/.agent-src/rules/improve-before-implement.md +2 -2
- package/.agent-src/rules/language-and-tone.md +37 -96
- package/.agent-src/rules/minimal-safe-diff.md +3 -3
- package/.agent-src/rules/model-recommendation.md +4 -4
- package/.agent-src/rules/no-cheap-questions.md +89 -0
- package/.agent-src/rules/non-destructive-by-default.md +15 -49
- package/.agent-src/rules/onboarding-gate.md +5 -5
- package/.agent-src/rules/review-routing-awareness.md +9 -9
- package/.agent-src/rules/roadmap-progress-sync.md +26 -33
- package/.agent-src/rules/role-mode-adherence.md +2 -2
- package/.agent-src/rules/scope-control.md +65 -46
- package/.agent-src/rules/security-sensitive-stop.md +2 -2
- package/.agent-src/rules/size-enforcement.md +1 -1
- package/.agent-src/rules/think-before-action.md +5 -5
- package/.agent-src/rules/token-efficiency.md +4 -4
- package/.agent-src/rules/{ui-audit-before-build.md → ui-audit-gate.md} +3 -3
- package/.agent-src/rules/user-interaction.md +3 -3
- package/.agent-src/rules/verify-before-complete.md +12 -67
- package/.agent-src/scripts/update_roadmap_progress.py +9 -4
- package/.agent-src/skills/ai-council/SKILL.md +333 -0
- package/.agent-src/skills/api-endpoint/SKILL.md +2 -2
- package/.agent-src/skills/blade-ui/SKILL.md +1 -1
- package/.agent-src/skills/blast-radius-analyzer/SKILL.md +1 -1
- package/.agent-src/skills/bug-analyzer/SKILL.md +1 -1
- package/.agent-src/skills/command-routing/SKILL.md +1 -1
- package/.agent-src/skills/command-writing/SKILL.md +1 -1
- package/.agent-src/skills/conventional-commits-writing/SKILL.md +1 -1
- package/.agent-src/skills/copilot-agents-optimization/SKILL.md +2 -2
- package/.agent-src/skills/developer-like-execution/SKILL.md +2 -2
- package/.agent-src/skills/flux/SKILL.md +1 -1
- package/.agent-src/skills/git-workflow/SKILL.md +1 -1
- package/.agent-src/skills/guideline-writing/SKILL.md +11 -11
- package/.agent-src/skills/learning-to-rule-or-skill/SKILL.md +4 -4
- package/.agent-src/skills/livewire/SKILL.md +1 -1
- package/.agent-src/skills/override-management/SKILL.md +2 -2
- package/.agent-src/skills/php-coder/SKILL.md +1 -1
- package/.agent-src/skills/playwright-testing/SKILL.md +2 -2
- package/.agent-src/skills/readme-reviewer/SKILL.md +1 -1
- package/.agent-src/skills/readme-writing/SKILL.md +1 -1
- package/.agent-src/skills/readme-writing-package/SKILL.md +1 -1
- package/.agent-src/skills/receiving-code-review/SKILL.md +1 -1
- package/.agent-src/skills/review-routing/SKILL.md +2 -2
- package/.agent-src/skills/rule-writing/SKILL.md +1 -1
- package/.agent-src/skills/skill-reviewer/SKILL.md +1 -1
- package/.agent-src/skills/skill-writing/SKILL.md +3 -3
- package/.agent-src/skills/subagent-orchestration/SKILL.md +1 -0
- package/.agent-src/skills/systematic-debugging/SKILL.md +1 -1
- package/.agent-src/skills/upstream-contribute/SKILL.md +1 -1
- package/.agent-src/skills/validate-feature-fit/SKILL.md +2 -2
- package/.agent-src/skills/{verify-before-complete → verify-completion-evidence}/SKILL.md +2 -2
- package/.agent-src/templates/agent-settings.md +8 -8
- package/.agent-src/templates/contexts/auth-model.md +1 -1
- package/.agent-src/templates/scripts/README.md +2 -2
- package/.agent-src/templates/scripts/telemetry/aggregator.py +16 -1
- package/.agent-src/templates/scripts/telemetry/engagement.py +59 -0
- package/.agent-src/templates/scripts/telemetry/report_renderer.py +28 -1
- package/.agent-src/templates/scripts/telemetry_record.py +14 -1
- package/.claude-plugin/marketplace.json +10 -2
- package/AGENTS.md +11 -9
- package/CHANGELOG.md +123 -1
- package/README.md +28 -30
- package/config/agent-settings.template.yml +58 -1
- package/config/gitignore-block.txt +3 -0
- package/docs/architecture.md +4 -4
- package/docs/catalog.md +331 -0
- package/docs/contracts/STABILITY.md +39 -0
- package/docs/contracts/adr-command-suggestion.md +3 -3
- package/docs/contracts/adr-product-ui-track.md +2 -2
- package/docs/contracts/agent-memory-contract.md +2 -2
- package/docs/contracts/artifact-engagement-flow.md +1 -1
- package/docs/contracts/command-clusters.md +2 -2
- package/docs/contracts/command-suggestion-flow.md +3 -3
- package/docs/contracts/implement-ticket-flow.md +2 -2
- package/docs/contracts/linear-ai-rules-inclusion.md +1 -1
- package/docs/contracts/load-context-schema.md +186 -0
- package/docs/contracts/rule-interactions.yml +96 -0
- package/docs/contracts/rule-priority-hierarchy.md +87 -0
- package/docs/contracts/ui-track-flow.md +1 -1
- package/docs/customization.md +14 -0
- package/docs/end-to-end-walkthroughs.md +165 -0
- package/docs/getting-started.md +26 -8
- package/docs/github-topics.md +12 -3
- package/docs/guidelines/agent-infra/language-and-tone-examples.md +79 -0
- package/{.agent-src → docs}/guidelines/docs/readme-size-and-splitting.md +26 -25
- package/docs/guidelines/php/git.md +164 -0
- package/docs/migrations/commands-1.15.0.md +1 -1
- package/docs/showcase.md +9 -4
- package/docs/skills-catalog.md +14 -8
- package/docs/ui-track-mental-model.md +2 -2
- package/llms.txt +13 -7
- package/package.json +1 -1
- package/scripts/agent-config +23 -0
- package/scripts/ai_council/__init__.py +39 -0
- package/scripts/ai_council/_default_prices.py +41 -0
- package/scripts/ai_council/_one_off_rebalancing_audit.py +149 -0
- package/scripts/ai_council/_one_off_roundtrip.py +106 -0
- package/scripts/ai_council/budget_guard.py +172 -0
- package/scripts/ai_council/bundler.py +261 -0
- package/scripts/ai_council/clients.py +381 -0
- package/scripts/ai_council/modes.py +127 -0
- package/scripts/ai_council/orchestrator.py +350 -0
- package/scripts/ai_council/pricing.py +213 -0
- package/scripts/ai_council/project_context.py +159 -0
- package/scripts/ai_council/prompts.py +232 -0
- package/scripts/ai_council/session.py +144 -0
- package/scripts/check_always_budget.py +126 -0
- package/scripts/check_augmentignore.py +69 -0
- package/scripts/check_command_count_messaging.py +120 -0
- package/scripts/check_portability.py +55 -0
- package/scripts/check_public_catalog_links.py +122 -0
- package/scripts/check_references.py +4 -1
- package/scripts/check_roadmap_trackable.py +111 -0
- package/scripts/command_suggester/cooldown.py +1 -1
- package/scripts/generate_index.py +266 -0
- package/scripts/install_anthropic_key.sh +5 -0
- package/scripts/install_openai_key.sh +106 -0
- package/scripts/lint_load_context.py +163 -0
- package/scripts/schemas/command.schema.json +20 -0
- package/scripts/schemas/rule.schema.json +10 -0
- package/scripts/skill_linter.py +12 -4
- package/scripts/sync_agent_settings.py +1 -1
- package/scripts/update_counts.py +9 -4
- package/scripts/update_prices.py +124 -0
- package/.agent-src/guidelines/php/git.md +0 -96
- /package/.agent-src/rules/{slash-commands.md → slash-command-routing-policy.md} +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/agent-interaction-and-decision-quality.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/break-glass-usage.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/developer-judgment.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/engineering-memory-data-format.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/layered-settings.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/memory-access.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/naming.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/output-patterns.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/review-routing-data-format.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/role-contracts.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/role-mode-router.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/runtime-layer.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/self-improvement-pipeline.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/size-and-scope.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/tool-integration.md +0 -0
- /package/{.agent-src → docs}/guidelines/e2e/playwright.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/api-design.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/artisan-commands.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/blade-ui.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/controllers.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/database.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/eloquent.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/flux.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/general.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/jobs.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/livewire.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/logging.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/naming.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/patterns/dependency-injection.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/patterns/dtos.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/patterns/events.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/patterns/factory.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/patterns/pipelines.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/patterns/policies.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/patterns/repositories.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/patterns/service-layer.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/patterns/strategy.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/patterns.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/performance.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/resources.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/security.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/sql.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/validations.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/websocket.md +0 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Advisory check for `.augmentignore` (road-to-governance-cleanup F6.3).
|
|
4
|
+
|
|
5
|
+
Runs as part of `task ci` to surface `/optimize augmentignore` as a
|
|
6
|
+
periodic reminder. Always exits 0 — this is a warn-only advisory, not
|
|
7
|
+
a gate. Failures here never block CI.
|
|
8
|
+
|
|
9
|
+
Checks performed:
|
|
10
|
+
1. Does `.augmentignore` exist at repo root?
|
|
11
|
+
2. Is its mtime older than 90 days? (stale reminder)
|
|
12
|
+
3. Is it suspiciously short (<5 non-blank, non-comment lines)?
|
|
13
|
+
|
|
14
|
+
If any check trips, prints a friendly hint and exits 0. If all clean,
|
|
15
|
+
prints a single-line OK and exits 0.
|
|
16
|
+
"""
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import sys
|
|
20
|
+
import time
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
|
|
23
|
+
STALE_DAYS = 90
|
|
24
|
+
MIN_USEFUL_LINES = 5
|
|
25
|
+
REPO_ROOT = Path(__file__).resolve().parent.parent
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def check() -> int:
|
|
29
|
+
target = REPO_ROOT / ".augmentignore"
|
|
30
|
+
notes: list[str] = []
|
|
31
|
+
|
|
32
|
+
if not target.exists():
|
|
33
|
+
notes.append("⚠️ .augmentignore is missing — run `/optimize augmentignore` to scaffold it.")
|
|
34
|
+
_emit(notes)
|
|
35
|
+
return 0
|
|
36
|
+
|
|
37
|
+
age_days = (time.time() - target.stat().st_mtime) / 86400
|
|
38
|
+
if age_days > STALE_DAYS:
|
|
39
|
+
notes.append(
|
|
40
|
+
f"ℹ️ .augmentignore is {int(age_days)} days old (threshold: {STALE_DAYS}) — "
|
|
41
|
+
"consider running `/optimize augmentignore` to refresh."
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
useful = [
|
|
45
|
+
ln for ln in target.read_text().splitlines()
|
|
46
|
+
if ln.strip() and not ln.strip().startswith("#")
|
|
47
|
+
]
|
|
48
|
+
if len(useful) < MIN_USEFUL_LINES:
|
|
49
|
+
notes.append(
|
|
50
|
+
f"ℹ️ .augmentignore has only {len(useful)} active entries — "
|
|
51
|
+
"run `/optimize augmentignore` to detect tech-stack ignores you may be missing."
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
_emit(notes)
|
|
55
|
+
return 0
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _emit(notes: list[str]) -> None:
|
|
59
|
+
if not notes:
|
|
60
|
+
print("✅ .augmentignore advisory: nothing to suggest.")
|
|
61
|
+
return
|
|
62
|
+
print("📒 .augmentignore advisory (non-blocking):")
|
|
63
|
+
for n in notes:
|
|
64
|
+
print(f" {n}")
|
|
65
|
+
print(" (This is a reminder, not a CI failure.)")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
if __name__ == "__main__":
|
|
69
|
+
sys.exit(check())
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Command-count messaging gate (regression guard for road-to-pr-34-followups 1.2).
|
|
4
|
+
|
|
5
|
+
Public surfaces (README.md, AGENTS.md, docs/getting-started.md) advertise
|
|
6
|
+
the size of the command catalog. PR #34 collapses atomic commands into
|
|
7
|
+
clusters via deprecation shims — the externally meaningful number is the
|
|
8
|
+
**active** command count (non-shim files), not the raw file count. This
|
|
9
|
+
gate sources canonical counts from `.agent-src.uncompressed/commands/`
|
|
10
|
+
frontmatter and fails when any documented number drifts from those.
|
|
11
|
+
|
|
12
|
+
Canonical counts:
|
|
13
|
+
total = number of *.md files under .agent-src.uncompressed/commands/
|
|
14
|
+
shims = files whose frontmatter declares `superseded_by:`
|
|
15
|
+
active = total - shims
|
|
16
|
+
|
|
17
|
+
Patterns checked (per file):
|
|
18
|
+
|
|
19
|
+
README.md
|
|
20
|
+
hero row "<strong>{N} Commands</strong>" → active
|
|
21
|
+
browse line "Browse all {N} active commands" → active
|
|
22
|
+
browse meta "{N} files total" → total
|
|
23
|
+
browse meta "{N} are deprecation shims" → shims
|
|
24
|
+
tools blurb "{N} native commands" → active
|
|
25
|
+
|
|
26
|
+
AGENTS.md
|
|
27
|
+
tree "commands/ ({N} files — {A} active + {S} deprecation shims)"
|
|
28
|
+
|
|
29
|
+
docs/getting-started.md
|
|
30
|
+
browse line "Browse all {N} active commands" → active
|
|
31
|
+
|
|
32
|
+
Exit codes: 0 = clean, 1 = drift detected.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
from __future__ import annotations
|
|
36
|
+
|
|
37
|
+
import re
|
|
38
|
+
import sys
|
|
39
|
+
from pathlib import Path
|
|
40
|
+
|
|
41
|
+
ROOT = Path(__file__).resolve().parent.parent
|
|
42
|
+
COMMANDS_DIR = ROOT / ".agent-src.uncompressed" / "commands"
|
|
43
|
+
README = ROOT / "README.md"
|
|
44
|
+
AGENTS = ROOT / "AGENTS.md"
|
|
45
|
+
GETTING_STARTED = ROOT / "docs" / "getting-started.md"
|
|
46
|
+
|
|
47
|
+
FM_RE = re.compile(r"^---\s*\n(.*?)\n---", re.DOTALL)
|
|
48
|
+
SUPERSEDED_RE = re.compile(r"^superseded_by:\s*\S", re.MULTILINE)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def canonical_counts() -> tuple[int, int, int]:
|
|
52
|
+
if not COMMANDS_DIR.is_dir():
|
|
53
|
+
print(f"❌ {COMMANDS_DIR.relative_to(ROOT)} not found", file=sys.stderr)
|
|
54
|
+
sys.exit(1)
|
|
55
|
+
total = shims = 0
|
|
56
|
+
for f in COMMANDS_DIR.glob("*.md"):
|
|
57
|
+
total += 1
|
|
58
|
+
m = FM_RE.match(f.read_text(encoding="utf-8"))
|
|
59
|
+
fm = m.group(1) if m else ""
|
|
60
|
+
if SUPERSEDED_RE.search(fm):
|
|
61
|
+
shims += 1
|
|
62
|
+
return total, shims, total - shims
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _check(path: Path, pattern: str, expected: int, label: str) -> str | None:
|
|
66
|
+
if not path.exists():
|
|
67
|
+
return f"missing file: {path.relative_to(ROOT)}"
|
|
68
|
+
m = re.search(pattern, path.read_text(encoding="utf-8"))
|
|
69
|
+
if not m:
|
|
70
|
+
return f"{path.relative_to(ROOT)}: pattern not found for `{label}` — /{pattern}/"
|
|
71
|
+
found = int(m.group(1))
|
|
72
|
+
if found != expected:
|
|
73
|
+
return f"{path.relative_to(ROOT)}: `{label}` says {found}, expected {expected}"
|
|
74
|
+
return None
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def main() -> int:
|
|
78
|
+
total, shims, active = canonical_counts()
|
|
79
|
+
print(f"Canonical counts: {total} files · {shims} shims · {active} active")
|
|
80
|
+
|
|
81
|
+
checks = [
|
|
82
|
+
# README.md
|
|
83
|
+
(README, r"<strong>(\d+) Commands</strong>", active, "hero row"),
|
|
84
|
+
(README, r"Browse all (\d+) active commands", active, "browse line"),
|
|
85
|
+
(README, r"\((\d+) files total ", total, "browse meta · total files"),
|
|
86
|
+
(README, r"— (\d+) are deprecation shims", shims, "browse meta · shims"),
|
|
87
|
+
(README, r"\+ (\d+) native commands\)", active, "tools blurb"),
|
|
88
|
+
# AGENTS.md (`commands/ (84 files — 69 active + 15 deprecation shims)`)
|
|
89
|
+
(AGENTS, r"commands/\s+\((\d+) files —", total, "tree · total files"),
|
|
90
|
+
(AGENTS, r"files — (\d+) active", active, "tree · active"),
|
|
91
|
+
(AGENTS, r"active \+ (\d+) deprecation shims", shims, "tree · shims"),
|
|
92
|
+
# docs/getting-started.md
|
|
93
|
+
(GETTING_STARTED, r"Browse all (\d+) active commands", active, "browse line"),
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
errors: list[str] = []
|
|
97
|
+
for path, pattern, expected, label in checks:
|
|
98
|
+
err = _check(path, pattern, expected, label)
|
|
99
|
+
if err:
|
|
100
|
+
errors.append(err)
|
|
101
|
+
|
|
102
|
+
if not errors:
|
|
103
|
+
print("✅ All command-count messaging in sync with registry.")
|
|
104
|
+
return 0
|
|
105
|
+
|
|
106
|
+
print(f"❌ Command-count messaging drift — {len(errors)} mismatch(es):")
|
|
107
|
+
for e in errors:
|
|
108
|
+
print(f" {e}")
|
|
109
|
+
print(
|
|
110
|
+
"\nFix: update the documented numbers above, or run "
|
|
111
|
+
"`task check-command-count` after editing."
|
|
112
|
+
)
|
|
113
|
+
print(
|
|
114
|
+
"Why this gate exists: see `agents/roadmaps/road-to-pr-34-followups.md` § 1.2."
|
|
115
|
+
)
|
|
116
|
+
return 1
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
if __name__ == "__main__":
|
|
120
|
+
sys.exit(main())
|
|
@@ -250,6 +250,55 @@ def check_file(filepath: Path, patterns: list, allowlist: list) -> List[Violatio
|
|
|
250
250
|
return violations
|
|
251
251
|
|
|
252
252
|
|
|
253
|
+
# ── Identity-framing detector ───────────────────────────────────────────
|
|
254
|
+
# The package's public identity surface (README, AGENTS, copilot-instructions)
|
|
255
|
+
# must read stack-neutral. Laravel is the deepest reference stack today, never
|
|
256
|
+
# the headline. This detector flags banned phrases that elevate any single
|
|
257
|
+
# stack to identity status. Source-of-truth list lives in the
|
|
258
|
+
# road-to-1-15-followups.md roadmap (P0 #1, F1.5).
|
|
259
|
+
_IDENTITY_FRAMING_PATTERNS: list[tuple[re.Pattern, str]] = [
|
|
260
|
+
(re.compile(r"\bLaravel-first\b", re.IGNORECASE), "identity-laravel-first"),
|
|
261
|
+
(re.compile(r"\bfor\s+PHP\s*/\s*Laravel\s+teams?\b", re.IGNORECASE), "identity-for-php-laravel-teams"),
|
|
262
|
+
(re.compile(r"\bfor\s+Laravel\s+teams?\b", re.IGNORECASE), "identity-for-laravel-teams"),
|
|
263
|
+
(re.compile(r"\bprimary\s+audience\s*[:=]\s*Laravel\b", re.IGNORECASE), "identity-primary-audience-laravel"),
|
|
264
|
+
(re.compile(r"\bbuilt\s+for\s+Laravel\b", re.IGNORECASE), "identity-built-for-laravel"),
|
|
265
|
+
(re.compile(r"\bLaravel\s*=\s*primary\b", re.IGNORECASE), "identity-laravel-equals-primary"),
|
|
266
|
+
(re.compile(r"\*\*Reference\s+implementation:\s*Laravel\.?\*\*", re.IGNORECASE), "identity-reference-implementation-laravel"),
|
|
267
|
+
]
|
|
268
|
+
|
|
269
|
+
# Files whose identity framing must stay stack-neutral. Relative to repo root.
|
|
270
|
+
IDENTITY_SCAN_FILES = [
|
|
271
|
+
"README.md",
|
|
272
|
+
"AGENTS.md",
|
|
273
|
+
".github/copilot-instructions.md",
|
|
274
|
+
]
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def check_identity_framing(filepath: Path) -> List[Violation]:
|
|
278
|
+
"""Flag banned identity-framing phrases in README / AGENTS / copilot-instructions.
|
|
279
|
+
|
|
280
|
+
The package presents itself as a universal governance system; any phrase
|
|
281
|
+
that pins identity to a single stack (Laravel-first, built for Laravel,
|
|
282
|
+
Reference implementation: Laravel as a bolded headline) is a regression.
|
|
283
|
+
"""
|
|
284
|
+
violations: List[Violation] = []
|
|
285
|
+
try:
|
|
286
|
+
lines = filepath.read_text(encoding="utf-8").splitlines()
|
|
287
|
+
except Exception:
|
|
288
|
+
return violations
|
|
289
|
+
|
|
290
|
+
for i, line in enumerate(lines, 1):
|
|
291
|
+
for pattern, name in _IDENTITY_FRAMING_PATTERNS:
|
|
292
|
+
m = pattern.search(line)
|
|
293
|
+
if m:
|
|
294
|
+
violations.append(Violation(
|
|
295
|
+
file=str(filepath), line=i, match=m.group(0),
|
|
296
|
+
pattern_name=name, severity="error",
|
|
297
|
+
context=line.strip(),
|
|
298
|
+
))
|
|
299
|
+
return violations
|
|
300
|
+
|
|
301
|
+
|
|
253
302
|
# ── Task-command detector ───────────────────────────────────────────────
|
|
254
303
|
# Artefact files shipped in the package must not reference `task <name>`
|
|
255
304
|
# invocations (per augment-portability rule). Consumer projects may not
|
|
@@ -467,6 +516,12 @@ def scan_all(root: Path) -> tuple[List[Violation], list[str]]:
|
|
|
467
516
|
if not any(path_str.endswith(skip) for skip in _CLI_DETECTOR_SKIP):
|
|
468
517
|
violations.extend(check_cli_invocations(f))
|
|
469
518
|
|
|
519
|
+
# Layer 5: identity-framing scan on the public identity surface
|
|
520
|
+
for rel in IDENTITY_SCAN_FILES:
|
|
521
|
+
f = root / rel
|
|
522
|
+
if f.is_file():
|
|
523
|
+
violations.extend(check_identity_framing(f))
|
|
524
|
+
|
|
470
525
|
return violations, detected
|
|
471
526
|
|
|
472
527
|
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Public-catalog link checker (regression guard for road-to-pr-34-followups 1.1).
|
|
4
|
+
|
|
5
|
+
`docs/catalog.md` is the consumer-facing catalog rendered by
|
|
6
|
+
`scripts/generate_index.py`. Consumers receive the package via npm /
|
|
7
|
+
Composer / archive surfaces — `.agent-src.uncompressed/` is **not**
|
|
8
|
+
shipped (see `package.json#files`). Every link in the public catalog
|
|
9
|
+
must therefore resolve to a shipped surface.
|
|
10
|
+
|
|
11
|
+
Checks:
|
|
12
|
+
1. No link href contains `.agent-src.uncompressed/`.
|
|
13
|
+
2. Every link href resolves on disk.
|
|
14
|
+
3. Every link href starts with a path declared in `package.json#files`
|
|
15
|
+
(or one of the always-shipped root files).
|
|
16
|
+
|
|
17
|
+
Exit codes: 0 = clean, 1 = violations found.
|
|
18
|
+
|
|
19
|
+
Usage:
|
|
20
|
+
python3 scripts/check_public_catalog_links.py
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
import json
|
|
26
|
+
import re
|
|
27
|
+
import sys
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
|
|
30
|
+
ROOT = Path(__file__).resolve().parent.parent
|
|
31
|
+
CATALOG = ROOT / "docs" / "catalog.md"
|
|
32
|
+
PACKAGE_JSON = ROOT / "package.json"
|
|
33
|
+
|
|
34
|
+
LINK_RE = re.compile(r"\]\((?P<href>[^)\s]+)(?:\s+\"[^\"]*\")?\)")
|
|
35
|
+
FORBIDDEN_PREFIX = ".agent-src.uncompressed/"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _shipped_roots() -> tuple[set[str], set[str]]:
|
|
39
|
+
"""Return (shipped_dirs, shipped_files) from package.json#files."""
|
|
40
|
+
data = json.loads(PACKAGE_JSON.read_text(encoding="utf-8"))
|
|
41
|
+
dirs: set[str] = set()
|
|
42
|
+
files: set[str] = set()
|
|
43
|
+
for entry in data.get("files", []):
|
|
44
|
+
if entry.endswith("/"):
|
|
45
|
+
dirs.add(entry.rstrip("/"))
|
|
46
|
+
else:
|
|
47
|
+
files.add(entry)
|
|
48
|
+
return dirs, files
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _resolve(href: str) -> Path | None:
|
|
52
|
+
href = href.split("#", 1)[0]
|
|
53
|
+
if not href or href.startswith(("http://", "https://", "mailto:", "tel:")):
|
|
54
|
+
return None
|
|
55
|
+
target = (CATALOG.parent / href).resolve()
|
|
56
|
+
try:
|
|
57
|
+
return target.relative_to(ROOT.resolve())
|
|
58
|
+
except ValueError:
|
|
59
|
+
return None
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _under_shipped_surface(rel: Path, dirs: set[str], files: set[str]) -> bool:
|
|
63
|
+
s = str(rel)
|
|
64
|
+
if s in files:
|
|
65
|
+
return True
|
|
66
|
+
return any(s == d or s.startswith(d + "/") for d in dirs)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def main() -> int:
|
|
70
|
+
if not CATALOG.exists():
|
|
71
|
+
print(f"❌ {CATALOG.relative_to(ROOT)} not found")
|
|
72
|
+
return 1
|
|
73
|
+
|
|
74
|
+
dirs, files = _shipped_roots()
|
|
75
|
+
text = CATALOG.read_text(encoding="utf-8")
|
|
76
|
+
|
|
77
|
+
forbidden: list[tuple[int, str]] = []
|
|
78
|
+
missing: list[tuple[int, str]] = []
|
|
79
|
+
unshipped: list[tuple[int, str]] = []
|
|
80
|
+
|
|
81
|
+
for lineno, line in enumerate(text.splitlines(), 1):
|
|
82
|
+
for m in LINK_RE.finditer(line):
|
|
83
|
+
href = m.group("href")
|
|
84
|
+
if FORBIDDEN_PREFIX in href:
|
|
85
|
+
forbidden.append((lineno, href))
|
|
86
|
+
continue
|
|
87
|
+
rel = _resolve(href)
|
|
88
|
+
if rel is None:
|
|
89
|
+
continue # external / non-resolvable
|
|
90
|
+
if not (ROOT / rel).exists():
|
|
91
|
+
missing.append((lineno, href))
|
|
92
|
+
continue
|
|
93
|
+
if not _under_shipped_surface(rel, dirs, files):
|
|
94
|
+
unshipped.append((lineno, href))
|
|
95
|
+
|
|
96
|
+
total_violations = len(forbidden) + len(missing) + len(unshipped)
|
|
97
|
+
if not total_violations:
|
|
98
|
+
print(f"✅ docs/catalog.md — all links resolve to shipped surfaces.")
|
|
99
|
+
return 0
|
|
100
|
+
|
|
101
|
+
print(f"❌ docs/catalog.md — {total_violations} violation(s):")
|
|
102
|
+
if forbidden:
|
|
103
|
+
print(f"\n {len(forbidden)} link(s) point at unshipped `.agent-src.uncompressed/`:")
|
|
104
|
+
for ln, href in forbidden[:10]:
|
|
105
|
+
print(f" line {ln}: {href}")
|
|
106
|
+
if len(forbidden) > 10:
|
|
107
|
+
print(f" … and {len(forbidden) - 10} more")
|
|
108
|
+
if missing:
|
|
109
|
+
print(f"\n {len(missing)} link(s) do not resolve on disk:")
|
|
110
|
+
for ln, href in missing[:10]:
|
|
111
|
+
print(f" line {ln}: {href}")
|
|
112
|
+
if unshipped:
|
|
113
|
+
print(f"\n {len(unshipped)} link(s) point outside `package.json#files`:")
|
|
114
|
+
for ln, href in unshipped[:10]:
|
|
115
|
+
print(f" line {ln}: {href}")
|
|
116
|
+
print("\nFix: update `scripts/generate_index.py` _to_shipped_path() / catalog renderer,")
|
|
117
|
+
print("then re-run `python3 scripts/generate_index.py`.")
|
|
118
|
+
return 1
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
if __name__ == "__main__":
|
|
122
|
+
sys.exit(main())
|
|
@@ -32,7 +32,10 @@ class BrokenRef:
|
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
SCAN_DIRS = [".agent-src", "agents"]
|
|
35
|
-
SKIP_DIRS = [
|
|
35
|
+
SKIP_DIRS = [
|
|
36
|
+
"agents/roadmaps/archive", # archived roadmaps have historical refs
|
|
37
|
+
"agents/council-sessions", # per-user audit trail (gitignored), captured provider output
|
|
38
|
+
]
|
|
36
39
|
ROOT = Path(".")
|
|
37
40
|
|
|
38
41
|
# YAML memory files (engineering-memory layer) live under `agents/memory/`.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""CI guard for the `roadmap-progress-sync` rule's trackability Iron Law.
|
|
3
|
+
|
|
4
|
+
Every non-draft file under `agents/roadmaps/` (excluding `archive/`,
|
|
5
|
+
`skipped/`, template/README/open-questions) MUST:
|
|
6
|
+
|
|
7
|
+
1. Be parseable by the dashboard's `PHASE_RE` — i.e. contain at least
|
|
8
|
+
one `## Phase <id>` or `### Phase <id>` heading.
|
|
9
|
+
2. Have at least one trackable checkbox (`- [ ]`, `[x]`, `[~]`, `[-]`)
|
|
10
|
+
under every parsed phase.
|
|
11
|
+
|
|
12
|
+
A roadmap that fails (1) is invisible to `agents/roadmaps-progress.md`
|
|
13
|
+
and silently lies to the next reader. A phase that fails (2) shows as
|
|
14
|
+
`⬜ empty` and contributes nothing to progress percentages.
|
|
15
|
+
|
|
16
|
+
Both failure modes are rule violations per
|
|
17
|
+
`.augment/rules/roadmap-progress-sync.md` § "Iron Law — every active
|
|
18
|
+
roadmap is trackable". This script is the CI backstop so the rule
|
|
19
|
+
cannot be quietly broken again.
|
|
20
|
+
|
|
21
|
+
Exit codes:
|
|
22
|
+
0 — every active roadmap has parseable phases with at least one
|
|
23
|
+
checkbox per phase.
|
|
24
|
+
1 — at least one violation found; details printed to stdout.
|
|
25
|
+
|
|
26
|
+
Invocation (from project root):
|
|
27
|
+
python3 scripts/check_roadmap_trackable.py
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
from __future__ import annotations
|
|
31
|
+
|
|
32
|
+
import sys
|
|
33
|
+
from pathlib import Path
|
|
34
|
+
|
|
35
|
+
# Reuse the dashboard's regexes and helpers — single source of truth so
|
|
36
|
+
# the linter cannot drift from what the dashboard actually parses.
|
|
37
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / ".augment" / "scripts"))
|
|
38
|
+
from update_roadmap_progress import ( # noqa: E402
|
|
39
|
+
CHECKBOX_RE,
|
|
40
|
+
PHASE_RE,
|
|
41
|
+
is_draft,
|
|
42
|
+
is_roadmap_candidate,
|
|
43
|
+
parse_frontmatter,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
ROADMAP_ROOT = Path("agents/roadmaps")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def find_active_roadmaps(root: Path) -> list[Path]:
|
|
50
|
+
"""Return every non-draft roadmap candidate under root."""
|
|
51
|
+
out: list[Path] = []
|
|
52
|
+
for path in sorted(root.rglob("*.md")):
|
|
53
|
+
if not path.is_file() or not is_roadmap_candidate(path):
|
|
54
|
+
continue
|
|
55
|
+
text = path.read_text(encoding="utf-8")
|
|
56
|
+
if is_draft(parse_frontmatter(text)):
|
|
57
|
+
continue
|
|
58
|
+
out.append(path)
|
|
59
|
+
return out
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def violations_for(path: Path) -> list[str]:
|
|
63
|
+
"""Return human-readable violation strings for a single roadmap."""
|
|
64
|
+
text = path.read_text(encoding="utf-8")
|
|
65
|
+
matches = list(PHASE_RE.finditer(text))
|
|
66
|
+
if not matches:
|
|
67
|
+
return [
|
|
68
|
+
f"{path}: no `## Phase <id>` or `### Phase <id>` heading "
|
|
69
|
+
"matched the dashboard's PHASE_RE — roadmap is invisible "
|
|
70
|
+
"to agents/roadmaps-progress.md. Either rename headings to "
|
|
71
|
+
"the canonical `Phase <id>` form or add `status: draft` to "
|
|
72
|
+
"the frontmatter."
|
|
73
|
+
]
|
|
74
|
+
out: list[str] = []
|
|
75
|
+
for i, pm in enumerate(matches):
|
|
76
|
+
start = pm.end()
|
|
77
|
+
end = matches[i + 1].start() if i + 1 < len(matches) else len(text)
|
|
78
|
+
if not CHECKBOX_RE.search(text[start:end]):
|
|
79
|
+
phase_id = pm.group(2)
|
|
80
|
+
name = (pm.group(3) or "").strip() or f"Phase {phase_id}"
|
|
81
|
+
out.append(
|
|
82
|
+
f"{path}: Phase {phase_id} ({name[:60]}) has zero "
|
|
83
|
+
"trackable checkboxes — add at least one `- [ ]` (or "
|
|
84
|
+
"`[x]`/`[~]`/`[-]`) item or remove the phase."
|
|
85
|
+
)
|
|
86
|
+
return out
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def main() -> int:
|
|
90
|
+
if not ROADMAP_ROOT.is_dir():
|
|
91
|
+
print(f"❌ {ROADMAP_ROOT} not found — run from project root.", file=sys.stderr)
|
|
92
|
+
return 1
|
|
93
|
+
findings: list[str] = []
|
|
94
|
+
for path in find_active_roadmaps(ROADMAP_ROOT):
|
|
95
|
+
findings.extend(violations_for(path))
|
|
96
|
+
if findings:
|
|
97
|
+
print("❌ Trackable-roadmap rule violations:\n")
|
|
98
|
+
for f in findings:
|
|
99
|
+
print(f" - {f}")
|
|
100
|
+
print(
|
|
101
|
+
"\nRule: .augment/rules/roadmap-progress-sync.md "
|
|
102
|
+
'§ "Iron Law — every active roadmap is trackable"'
|
|
103
|
+
)
|
|
104
|
+
return 1
|
|
105
|
+
count = len(find_active_roadmaps(ROADMAP_ROOT))
|
|
106
|
+
print(f"✅ {count} active roadmap(s) — all parseable, all phases have checkboxes.")
|
|
107
|
+
return 0
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
if __name__ == "__main__":
|
|
111
|
+
sys.exit(main())
|
|
@@ -31,7 +31,7 @@ def is_explicit_slash_invocation(message: str) -> bool:
|
|
|
31
31
|
|
|
32
32
|
Per the `command-suggestion` rule, explicit slash invocations
|
|
33
33
|
bypass the suggestion layer entirely \u2014 they're handled by
|
|
34
|
-
`slash-
|
|
34
|
+
`slash-command-routing-policy` directly. The engine should not score in that
|
|
35
35
|
case. Helper exposed for the runtime caller and the GT-CS4
|
|
36
36
|
golden.
|
|
37
37
|
"""
|