@event4u/agent-config 1.22.0 → 1.23.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/cleanup.md +31 -17
- package/.agent-src/commands/commit/in-chunks.md +30 -10
- package/.agent-src/commands/commit.md +46 -6
- package/.agent-src/commands/compress.md +19 -13
- package/.agent-src/commands/cost-report.md +120 -0
- package/.agent-src/commands/create-pr/description-only.md +8 -0
- package/.agent-src/commands/create-pr.md +95 -80
- package/.agent-src/commands/feature/plan.md +13 -7
- package/.agent-src/commands/memory/add.md +16 -8
- package/.agent-src/commands/memory/promote.md +17 -9
- package/.agent-src/commands/optimize/rtk.md +16 -11
- package/.agent-src/commands/prepare-for-review.md +12 -6
- package/.agent-src/commands/project-analyze.md +31 -20
- package/.agent-src/commands/review-changes.md +24 -15
- package/.agent-src/commands/roadmap/create.md +14 -9
- package/.agent-src/contexts/contracts/frugality-charter.md +57 -0
- package/.agent-src/rules/architecture.md +9 -0
- package/.agent-src/rules/ask-when-uncertain.md +3 -13
- package/.agent-src/rules/caveman-speak.md +78 -0
- package/.agent-src/rules/direct-answers.md +5 -14
- package/.agent-src/rules/markdown-safe-codeblocks.md +6 -7
- package/.agent-src/rules/no-cheap-questions.md +4 -14
- package/.agent-src/rules/token-efficiency.md +5 -7
- package/.agent-src/skills/adr-create/SKILL.md +197 -0
- package/.agent-src/skills/agent-docs-writing/SKILL.md +23 -1
- package/.agent-src/skills/command-writing/SKILL.md +23 -0
- package/.agent-src/skills/context-authoring/SKILL.md +23 -0
- package/.agent-src/skills/conventional-commits-writing/SKILL.md +23 -0
- package/.agent-src/skills/guideline-writing/SKILL.md +22 -0
- package/.agent-src/skills/persona-writing/SKILL.md +153 -0
- package/.agent-src/skills/readme-writing/SKILL.md +20 -0
- package/.agent-src/skills/readme-writing-package/SKILL.md +19 -0
- package/.agent-src/skills/roadmap-writing/SKILL.md +157 -0
- package/.agent-src/skills/rule-writing/SKILL.md +22 -0
- package/.agent-src/skills/script-writing/SKILL.md +226 -0
- package/.agent-src/skills/skill-writing/SKILL.md +23 -0
- package/.agent-src/skills/test-driven-development/SKILL.md +24 -0
- package/.agent-src/templates/agent-settings.md +73 -0
- package/.agent-src/templates/command.md +15 -10
- package/.agent-src/templates/rule.md +6 -0
- package/.agent-src/templates/skill.md +32 -0
- package/.claude-plugin/marketplace.json +6 -1
- package/AGENTS.md +3 -3
- package/CHANGELOG.md +35 -0
- package/README.md +5 -5
- package/docs/architecture.md +4 -4
- package/docs/customization.md +72 -0
- package/docs/decisions/INDEX.md +15 -0
- package/docs/getting-started.md +2 -2
- package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +27 -19
- package/docs/guidelines/agent-infra/carve-out-predicates.md +17 -0
- package/docs/guidelines/agent-infra/mcp-request-signing.md +199 -0
- package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +11 -4
- package/package.json +1 -1
- package/scripts/_lib/__init__.py +5 -0
- package/scripts/_lib/script_output.py +140 -0
- package/scripts/adr/regenerate_index.py +79 -0
- package/scripts/ai_council/one_off_archive/2026-05/_one_off_add_quiet.py +149 -0
- package/scripts/ai_council/one_off_archive/2026-05/_one_off_inject_quiet_flag.py +33 -0
- package/scripts/ai_council/one_off_archive/2026-05/_one_off_measure_v2.sh +36 -0
- package/scripts/ai_council/one_off_archive/2026-05/_one_off_measure_verbosity.sh +26 -0
- package/scripts/ai_council/one_off_archive/2026-05/_one_off_per_task.sh +41 -0
- package/scripts/ai_council/one_off_archive/2026-05/_one_off_silent_taskfiles.py +98 -0
- package/scripts/check_augmentignore.py +4 -1
- package/scripts/check_command_count_messaging.py +4 -1
- package/scripts/check_compressed_paths.py +4 -1
- package/scripts/check_council_layout.py +4 -1
- package/scripts/check_council_references.py +4 -1
- package/scripts/check_iron_law_prominence.py +3 -1
- package/scripts/check_md_language.py +3 -1
- package/scripts/check_memory_proposal.py +3 -1
- package/scripts/check_public_catalog_links.py +4 -1
- package/scripts/check_reply_consistency.py +8 -2
- package/scripts/check_roadmap_trackable.py +4 -1
- package/scripts/compile_router.py +27 -0
- package/scripts/compress.py +33 -19
- package/scripts/cost/budget.mjs +152 -0
- package/scripts/cost/track.mjs +144 -0
- package/scripts/first-run.sh +3 -9
- package/scripts/install-hooks.sh +19 -1
- package/scripts/install.py +17 -12
- package/scripts/install.sh +19 -8
- package/scripts/lint_examples.py +6 -2
- package/scripts/lint_handoffs.py +4 -1
- package/scripts/lint_load_context.py +4 -1
- package/scripts/lint_roadmap_complexity.py +6 -2
- package/scripts/lint_rule_interactions.py +4 -1
- package/scripts/lint_rule_tiers.py +4 -1
- package/scripts/measure_frugality_savings.py +164 -0
- package/scripts/runtime_dispatcher.py +11 -0
- package/scripts/skill_linter.py +207 -2
package/scripts/skill_linter.py
CHANGED
|
@@ -76,6 +76,26 @@ RULE_BAD_SIGNS = [
|
|
|
76
76
|
"## Gotchas",
|
|
77
77
|
]
|
|
78
78
|
|
|
79
|
+
# --- Frugality charter validator (see road-to-token-frugality Phase 0.4) ---
|
|
80
|
+
# Layer 1 = writer-cite check (every writer skill carries the section + link).
|
|
81
|
+
# Layer 2 = charter index integrity (the four canonical rules referenced by
|
|
82
|
+
# the charter resolve to real H2/H3 anchors in the rule files).
|
|
83
|
+
|
|
84
|
+
FRUGALITY_WRITER_SKILLS = {
|
|
85
|
+
"skill-writing", "rule-writing", "command-writing",
|
|
86
|
+
"guideline-writing", "context-authoring", "agent-docs-writing",
|
|
87
|
+
"conventional-commits-writing", "readme-writing",
|
|
88
|
+
"readme-writing-package", "adr-create",
|
|
89
|
+
"persona-writing", "roadmap-writing", "script-writing",
|
|
90
|
+
}
|
|
91
|
+
FRUGALITY_CHARTER_RELPATH = "contexts/communication/frugality-charter.md"
|
|
92
|
+
FRUGALITY_CHARTER_INDEX_RULES = {
|
|
93
|
+
"direct-answers.md": "iron-law-3",
|
|
94
|
+
"user-interaction.md": "iron-law-1",
|
|
95
|
+
"no-cheap-questions.md": "pre-send-self-check",
|
|
96
|
+
"token-efficiency.md": "the-iron-laws",
|
|
97
|
+
}
|
|
98
|
+
|
|
79
99
|
VAGUE_VALIDATION_PATTERNS = [
|
|
80
100
|
r"\bcheck if it works\b",
|
|
81
101
|
r"\bverify it works\b",
|
|
@@ -1381,6 +1401,15 @@ def gather_all_candidate_files(root: Path) -> list[Path]:
|
|
|
1381
1401
|
if not f.is_symlink():
|
|
1382
1402
|
candidates.append(f)
|
|
1383
1403
|
|
|
1404
|
+
# Frugality charter (Phase 0.4 Layer 2). Lives in contexts/, not
|
|
1405
|
+
# walked by the artifact-type loops above, but still needs the
|
|
1406
|
+
# index-integrity check.
|
|
1407
|
+
for base in (root / ".agent-src.uncompressed", root / ".agent-src"):
|
|
1408
|
+
charter = base / FRUGALITY_CHARTER_RELPATH
|
|
1409
|
+
if charter.exists() and not charter.is_symlink():
|
|
1410
|
+
candidates.append(charter)
|
|
1411
|
+
break
|
|
1412
|
+
|
|
1384
1413
|
return sorted(set(candidates))
|
|
1385
1414
|
|
|
1386
1415
|
|
|
@@ -1860,6 +1889,156 @@ def lint_verification_maturity(path: Path, text: str, artifact_type: str) -> Lis
|
|
|
1860
1889
|
# --- Governance & packaging checks ---
|
|
1861
1890
|
|
|
1862
1891
|
|
|
1892
|
+
# --- Frugality validator helpers + Layers 1 & 2 ---
|
|
1893
|
+
|
|
1894
|
+
def _heading_to_slug(heading: str) -> str:
|
|
1895
|
+
"""Slugify a markdown heading using GitHub's algorithm: lowercase,
|
|
1896
|
+
drop punctuation (em-dash, period, etc.), spaces -> hyphens,
|
|
1897
|
+
preserve adjacent hyphens (so `Iron Law 3 — Brevity` becomes
|
|
1898
|
+
`iron-law-3--brevity`, matching the anchor GitHub renders)."""
|
|
1899
|
+
s = heading.strip().lower()
|
|
1900
|
+
s = re.sub(r"[^a-z0-9 \-]", "", s)
|
|
1901
|
+
s = s.replace(" ", "-")
|
|
1902
|
+
return s.strip("-")
|
|
1903
|
+
|
|
1904
|
+
|
|
1905
|
+
def _extract_heading_slugs(text: str) -> set[str]:
|
|
1906
|
+
"""Return the set of slugs for every H2/H3 heading in a markdown body."""
|
|
1907
|
+
slugs: set[str] = set()
|
|
1908
|
+
for line in text.splitlines():
|
|
1909
|
+
if line.startswith("## ") or line.startswith("### "):
|
|
1910
|
+
heading = line.split(" ", 1)[1].strip()
|
|
1911
|
+
slugs.add(_heading_to_slug(heading))
|
|
1912
|
+
return slugs
|
|
1913
|
+
|
|
1914
|
+
|
|
1915
|
+
def _skill_id_from_path(path: Path) -> Optional[str]:
|
|
1916
|
+
"""Extract the writer-skill id from a SKILL.md path. Returns the
|
|
1917
|
+
parent-directory name, or None if the file is not a SKILL.md."""
|
|
1918
|
+
if path.name.lower() != "skill.md":
|
|
1919
|
+
return None
|
|
1920
|
+
return path.parent.name
|
|
1921
|
+
|
|
1922
|
+
|
|
1923
|
+
def _is_frugality_charter(path: Path) -> bool:
|
|
1924
|
+
"""True iff the path ends in the canonical charter relpath, regardless
|
|
1925
|
+
of whether it lives under .agent-src/ or .agent-src.uncompressed/."""
|
|
1926
|
+
norm = str(path).replace("\\", "/")
|
|
1927
|
+
return norm.endswith("/" + FRUGALITY_CHARTER_RELPATH)
|
|
1928
|
+
|
|
1929
|
+
|
|
1930
|
+
# Section header recognised by Layer 1. Literal H2 only — sub-headings
|
|
1931
|
+
# inside the section do not count as the section itself.
|
|
1932
|
+
_FRUGALITY_STANDARDS_PATTERN = re.compile(
|
|
1933
|
+
r"^##\s+Frugality Standards\s*$", re.MULTILINE
|
|
1934
|
+
)
|
|
1935
|
+
_FRUGALITY_CHARTER_LINK_PATTERN = re.compile(
|
|
1936
|
+
r"\]\([^)]*frugality-charter\.md[^)]*\)"
|
|
1937
|
+
)
|
|
1938
|
+
|
|
1939
|
+
|
|
1940
|
+
def lint_frugality_writer_cite(path: Path, text: str,
|
|
1941
|
+
artifact_type: str) -> List[Issue]:
|
|
1942
|
+
"""Layer 1 — every writer skill must carry a `## Frugality Standards`
|
|
1943
|
+
section that links to the charter. No-op for non-writer skills and
|
|
1944
|
+
non-skill artifacts."""
|
|
1945
|
+
if artifact_type != "skill":
|
|
1946
|
+
return []
|
|
1947
|
+
skill_id = _skill_id_from_path(path)
|
|
1948
|
+
if skill_id is None or skill_id not in FRUGALITY_WRITER_SKILLS:
|
|
1949
|
+
return []
|
|
1950
|
+
issues: List[Issue] = []
|
|
1951
|
+
section_match = _FRUGALITY_STANDARDS_PATTERN.search(text)
|
|
1952
|
+
if not section_match:
|
|
1953
|
+
issues.append(Issue(
|
|
1954
|
+
"error", "frugality_section_missing",
|
|
1955
|
+
"Writer skill must carry a `## Frugality Standards` section "
|
|
1956
|
+
"(road-to-token-frugality Phase 0.4 Layer 1)",
|
|
1957
|
+
))
|
|
1958
|
+
return issues
|
|
1959
|
+
# Section body = from match-end to next H2 or EOF.
|
|
1960
|
+
body_start = section_match.end()
|
|
1961
|
+
next_h2 = re.search(r"^##\s+", text[body_start:], re.MULTILINE)
|
|
1962
|
+
body_end = body_start + next_h2.start() if next_h2 else len(text)
|
|
1963
|
+
body = text[body_start:body_end]
|
|
1964
|
+
if not _FRUGALITY_CHARTER_LINK_PATTERN.search(body):
|
|
1965
|
+
issues.append(Issue(
|
|
1966
|
+
"error", "frugality_charter_cite_missing",
|
|
1967
|
+
"`## Frugality Standards` section must link to "
|
|
1968
|
+
"`frugality-charter.md` (road-to-token-frugality Phase 0.4 "
|
|
1969
|
+
"Layer 1)",
|
|
1970
|
+
))
|
|
1971
|
+
return issues
|
|
1972
|
+
|
|
1973
|
+
|
|
1974
|
+
# Markdown link pattern: [text](path#anchor) — anchor optional.
|
|
1975
|
+
_MD_LINK_PATTERN = re.compile(
|
|
1976
|
+
r"\[[^\]]+\]\(([^)#]+)(?:#([^)]+))?\)"
|
|
1977
|
+
)
|
|
1978
|
+
|
|
1979
|
+
|
|
1980
|
+
def lint_frugality_charter_index(path: Path, text: str) -> List[Issue]:
|
|
1981
|
+
"""Layer 2 — every cited anchor must resolve to a real H2/H3 heading
|
|
1982
|
+
in the target rule file, AND each of the four canonical rules must
|
|
1983
|
+
be cited at least once with the required canonical anchor substring.
|
|
1984
|
+
Additional citations to the same rule (net-new sections referencing
|
|
1985
|
+
other anchors) are validated for resolution but do not need the
|
|
1986
|
+
canonical substring."""
|
|
1987
|
+
if not _is_frugality_charter(path):
|
|
1988
|
+
return []
|
|
1989
|
+
issues: List[Issue] = []
|
|
1990
|
+
rules_dir = path.parent.parent.parent / "rules"
|
|
1991
|
+
rule_slugs_cache: dict[str, set[str]] = {}
|
|
1992
|
+
canonical_satisfied: set[str] = set()
|
|
1993
|
+
for link_match in _MD_LINK_PATTERN.finditer(text):
|
|
1994
|
+
link_path, link_anchor = link_match.group(1), link_match.group(2)
|
|
1995
|
+
rule_name = Path(link_path).name
|
|
1996
|
+
if rule_name not in FRUGALITY_CHARTER_INDEX_RULES:
|
|
1997
|
+
continue
|
|
1998
|
+
if link_anchor is None:
|
|
1999
|
+
continue
|
|
2000
|
+
anchor_lc = link_anchor.lower()
|
|
2001
|
+
required_substr = FRUGALITY_CHARTER_INDEX_RULES[rule_name]
|
|
2002
|
+
if required_substr in anchor_lc:
|
|
2003
|
+
canonical_satisfied.add(rule_name)
|
|
2004
|
+
if rule_name not in rule_slugs_cache:
|
|
2005
|
+
rule_file = rules_dir / rule_name
|
|
2006
|
+
if not rule_file.exists():
|
|
2007
|
+
issues.append(Issue(
|
|
2008
|
+
"error", "frugality_charter_rule_missing",
|
|
2009
|
+
f"Charter cites {rule_name} but the rule file does "
|
|
2010
|
+
f"not exist at {rule_file}",
|
|
2011
|
+
))
|
|
2012
|
+
rule_slugs_cache[rule_name] = set()
|
|
2013
|
+
continue
|
|
2014
|
+
try:
|
|
2015
|
+
rule_text = rule_file.read_text(encoding="utf-8")
|
|
2016
|
+
except OSError as e:
|
|
2017
|
+
issues.append(Issue(
|
|
2018
|
+
"error", "frugality_charter_rule_unreadable",
|
|
2019
|
+
f"Cannot read {rule_name}: {e}",
|
|
2020
|
+
))
|
|
2021
|
+
rule_slugs_cache[rule_name] = set()
|
|
2022
|
+
continue
|
|
2023
|
+
rule_slugs_cache[rule_name] = _extract_heading_slugs(rule_text)
|
|
2024
|
+
if anchor_lc not in rule_slugs_cache[rule_name]:
|
|
2025
|
+
issues.append(Issue(
|
|
2026
|
+
"error", "frugality_charter_anchor_unresolved",
|
|
2027
|
+
f"Charter cites {rule_name}#{link_anchor} but no H2/H3 "
|
|
2028
|
+
f"heading with that slug exists in the rule file",
|
|
2029
|
+
))
|
|
2030
|
+
missing = set(FRUGALITY_CHARTER_INDEX_RULES) - canonical_satisfied
|
|
2031
|
+
for rule_name in sorted(missing):
|
|
2032
|
+
required_substr = FRUGALITY_CHARTER_INDEX_RULES[rule_name]
|
|
2033
|
+
issues.append(Issue(
|
|
2034
|
+
"error", "frugality_charter_canonical_missing",
|
|
2035
|
+
f"Charter index lacks a canonical citation of {rule_name} "
|
|
2036
|
+
f"with anchor containing '{required_substr}' "
|
|
2037
|
+
f"(road-to-token-frugality Phase 0.4 Layer 2)",
|
|
2038
|
+
))
|
|
2039
|
+
return issues
|
|
2040
|
+
|
|
2041
|
+
|
|
1863
2042
|
def lint_governance(path: Path, text: str, artifact_type: str, repo_root: Path | None = None) -> List[Issue]:
|
|
1864
2043
|
"""Check governance and packaging consistency.
|
|
1865
2044
|
|
|
@@ -2139,6 +2318,17 @@ def lint_file(path: Path, repo_root: Path | None = None) -> LintResult:
|
|
|
2139
2318
|
elif artifact_type == "persona":
|
|
2140
2319
|
result = lint_persona(display_path, text)
|
|
2141
2320
|
else:
|
|
2321
|
+
# Frugality charter lives in contexts/ (artifact_type == unknown)
|
|
2322
|
+
# but still needs Layer 2 index-integrity validation.
|
|
2323
|
+
if _is_frugality_charter(path):
|
|
2324
|
+
charter_issues = lint_frugality_charter_index(path, text)
|
|
2325
|
+
return LintResult(
|
|
2326
|
+
file=str(display_path),
|
|
2327
|
+
artifact_type="unknown",
|
|
2328
|
+
status=classify_status(charter_issues),
|
|
2329
|
+
issues=charter_issues,
|
|
2330
|
+
suggestions=[],
|
|
2331
|
+
)
|
|
2142
2332
|
return lint_unknown(display_path, text)
|
|
2143
2333
|
|
|
2144
2334
|
# Post-processing: frontmatter schema validation (errors). Runs first
|
|
@@ -2195,10 +2385,20 @@ def lint_file(path: Path, repo_root: Path | None = None) -> LintResult:
|
|
|
2195
2385
|
result.issues.extend(malice_issues)
|
|
2196
2386
|
result.status = classify_status(result.issues)
|
|
2197
2387
|
|
|
2388
|
+
# Post-processing: frugality validator Layer 1 (writer-cite). Errors
|
|
2389
|
+
# if a writer skill lacks the `## Frugality Standards` section or its
|
|
2390
|
+
# link to the charter.
|
|
2391
|
+
frugality_issues = lint_frugality_writer_cite(
|
|
2392
|
+
display_path, text, artifact_type
|
|
2393
|
+
)
|
|
2394
|
+
if frugality_issues:
|
|
2395
|
+
result.issues.extend(frugality_issues)
|
|
2396
|
+
result.status = classify_status(result.issues)
|
|
2397
|
+
|
|
2198
2398
|
return result
|
|
2199
2399
|
|
|
2200
2400
|
|
|
2201
|
-
def format_text(results: list[LintResult]) -> str:
|
|
2401
|
+
def format_text(results: list[LintResult], quiet: bool = False) -> str:
|
|
2202
2402
|
lines: list[str] = []
|
|
2203
2403
|
# Phase 5.2: malice findings render in the spec shape
|
|
2204
2404
|
# ``<path>:<line>:malice:<pattern>:<matched>`` ahead of the badge
|
|
@@ -2216,7 +2416,10 @@ def format_text(results: list[LintResult]) -> str:
|
|
|
2216
2416
|
if malice_total:
|
|
2217
2417
|
lines.append("")
|
|
2218
2418
|
|
|
2419
|
+
# P10.5: quiet mode skips PASS-without-issues; malice + WARN/FAIL still rendered.
|
|
2219
2420
|
for result in results:
|
|
2421
|
+
if quiet and result.status == "pass" and not result.issues and not result.suggestions:
|
|
2422
|
+
continue
|
|
2220
2423
|
badge = {"pass": "[PASS]", "pass_with_warnings": "[WARN]", "fail": "[FAIL]"}[result.status]
|
|
2221
2424
|
lines.append(f"{badge} {result.file} ({result.artifact_type})")
|
|
2222
2425
|
if result.issues:
|
|
@@ -2458,6 +2661,8 @@ def parse_args() -> argparse.Namespace:
|
|
|
2458
2661
|
parser.add_argument("--strict-warnings", action="store_true", help="Return non-zero on warnings")
|
|
2459
2662
|
parser.add_argument("--report", action="store_true", help="Output quality score report")
|
|
2460
2663
|
parser.add_argument("--repo-root", default=".", help="Repository root")
|
|
2664
|
+
parser.add_argument("--quiet", action="store_true",
|
|
2665
|
+
help="suppress per-file PASS lines; keep malice + WARN/FAIL + summary (P10.5)")
|
|
2461
2666
|
return parser.parse_args()
|
|
2462
2667
|
|
|
2463
2668
|
|
|
@@ -2604,7 +2809,7 @@ def main() -> int:
|
|
|
2604
2809
|
elif args.format == "json":
|
|
2605
2810
|
print(format_json(results))
|
|
2606
2811
|
else:
|
|
2607
|
-
print(format_text(results))
|
|
2812
|
+
print(format_text(results, quiet=args.quiet))
|
|
2608
2813
|
|
|
2609
2814
|
return compute_exit_code(results, strict_warnings=args.strict_warnings)
|
|
2610
2815
|
|