@event4u/agent-config 1.13.0 → 1.14.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/agent-handoff.md +3 -0
- package/.agent-src/commands/agent-status.md +3 -0
- package/.agent-src/commands/agents-audit.md +4 -0
- package/.agent-src/commands/agents-cleanup.md +6 -1
- package/.agent-src/commands/agents-prepare.md +3 -0
- package/.agent-src/commands/analyze-reference-repo.md +4 -0
- package/.agent-src/commands/bug-fix.md +5 -1
- package/.agent-src/commands/bug-investigate.md +4 -0
- package/.agent-src/commands/chat-history-checkpoint.md +126 -0
- package/.agent-src/commands/chat-history-clear.md +5 -0
- package/.agent-src/commands/chat-history-resume.md +5 -0
- package/.agent-src/commands/chat-history.md +5 -0
- package/.agent-src/commands/check-current-md.md +126 -0
- package/.agent-src/commands/commit-in-chunks.md +98 -0
- package/.agent-src/commands/commit.md +4 -0
- package/.agent-src/commands/compress.md +3 -0
- package/.agent-src/commands/context-create.md +4 -0
- package/.agent-src/commands/context-refactor.md +4 -0
- package/.agent-src/commands/copilot-agents-init.md +3 -0
- package/.agent-src/commands/copilot-agents-optimize.md +3 -0
- package/.agent-src/commands/create-pr-description.md +4 -0
- package/.agent-src/commands/create-pr.md +4 -0
- package/.agent-src/commands/do-and-judge.md +4 -1
- package/.agent-src/commands/do-in-steps.md +3 -0
- package/.agent-src/commands/e2e-heal.md +4 -0
- package/.agent-src/commands/e2e-plan.md +4 -0
- package/.agent-src/commands/estimate-ticket.md +4 -1
- package/.agent-src/commands/feature-dev.md +4 -0
- package/.agent-src/commands/feature-explore.md +4 -0
- package/.agent-src/commands/feature-plan.md +4 -0
- package/.agent-src/commands/feature-refactor.md +4 -0
- package/.agent-src/commands/feature-roadmap.md +6 -0
- package/.agent-src/commands/fix-ci.md +4 -0
- package/.agent-src/commands/fix-portability.md +3 -0
- package/.agent-src/commands/fix-pr-bot-comments.md +4 -0
- package/.agent-src/commands/fix-pr-comments.md +4 -0
- package/.agent-src/commands/fix-pr-developer-comments.md +4 -0
- package/.agent-src/commands/fix-references.md +3 -0
- package/.agent-src/commands/fix-seeder.md +4 -0
- package/.agent-src/commands/implement-ticket.md +39 -13
- package/.agent-src/commands/jira-ticket.md +4 -0
- package/.agent-src/commands/judge.md +3 -0
- package/.agent-src/commands/memory-add.md +5 -3
- package/.agent-src/commands/memory-full.md +5 -2
- package/.agent-src/commands/memory-promote.md +7 -6
- package/.agent-src/commands/mode.md +3 -0
- package/.agent-src/commands/module-create.md +4 -0
- package/.agent-src/commands/module-explore.md +4 -0
- package/.agent-src/commands/onboard.md +24 -0
- package/.agent-src/commands/optimize-agents.md +4 -0
- package/.agent-src/commands/optimize-augmentignore.md +3 -0
- package/.agent-src/commands/optimize-rtk-filters.md +3 -0
- package/.agent-src/commands/optimize-skills.md +4 -0
- package/.agent-src/commands/override-create.md +4 -0
- package/.agent-src/commands/override-manage.md +4 -0
- package/.agent-src/commands/package-reset.md +3 -0
- package/.agent-src/commands/package-test.md +3 -0
- package/.agent-src/commands/prepare-for-review.md +4 -0
- package/.agent-src/commands/project-analyze.md +4 -0
- package/.agent-src/commands/project-health.md +4 -0
- package/.agent-src/commands/propose-memory.md +6 -8
- package/.agent-src/commands/quality-fix.md +4 -0
- package/.agent-src/commands/refine-ticket.md +4 -1
- package/.agent-src/commands/review-changes.md +4 -0
- package/.agent-src/commands/review-routing.md +4 -0
- package/.agent-src/commands/roadmap-create.md +7 -0
- package/.agent-src/commands/roadmap-execute.md +12 -1
- package/.agent-src/commands/rule-compliance-audit.md +4 -0
- package/.agent-src/commands/set-cost-profile.md +3 -0
- package/.agent-src/commands/sync-agent-settings.md +3 -0
- package/.agent-src/commands/sync-gitignore.md +3 -0
- package/.agent-src/commands/tests-create.md +4 -0
- package/.agent-src/commands/tests-execute.md +4 -0
- package/.agent-src/commands/threat-model.md +4 -0
- package/.agent-src/commands/update-form-request-messages.md +4 -0
- package/.agent-src/commands/upstream-contribute.md +4 -0
- package/.agent-src/commands/work.md +161 -0
- package/.agent-src/guidelines/agent-infra/engineering-memory-data-format.md +2 -6
- package/.agent-src/guidelines/agent-infra/layered-settings.md +0 -1
- package/.agent-src/guidelines/agent-infra/memory-access.md +0 -7
- package/.agent-src/guidelines/agent-infra/role-contracts.md +2 -4
- package/.agent-src/guidelines/agent-infra/self-improvement-pipeline.md +0 -1
- package/.agent-src/guidelines/php/patterns/strategy.md +180 -2
- package/.agent-src/personas/README.md +0 -1
- package/.agent-src/rules/artifact-drafting-protocol.md +7 -2
- package/.agent-src/rules/artifact-engagement-recording.md +133 -0
- package/.agent-src/rules/ask-when-uncertain.md +18 -13
- package/.agent-src/rules/augment-portability.md +8 -0
- package/.agent-src/rules/autonomous-execution.md +158 -0
- package/.agent-src/rules/chat-history.md +147 -118
- package/.agent-src/rules/cli-output-handling.md +26 -3
- package/.agent-src/rules/command-suggestion.md +133 -0
- package/.agent-src/rules/commit-policy.md +99 -0
- package/.agent-src/rules/direct-answers.md +114 -0
- package/.agent-src/rules/docs-sync.md +36 -0
- package/.agent-src/rules/downstream-changes.md +10 -9
- package/.agent-src/rules/improve-before-implement.md +9 -6
- package/.agent-src/rules/language-and-tone.md +81 -6
- package/.agent-src/rules/non-destructive-by-default.md +117 -0
- package/.agent-src/rules/package-ci-checks.md +4 -0
- package/.agent-src/rules/preservation-guard.md +20 -0
- package/.agent-src/rules/roadmap-progress-sync.md +103 -30
- package/.agent-src/rules/scope-control.md +42 -1
- package/.agent-src/rules/size-enforcement.md +1 -3
- package/.agent-src/rules/skill-quality.md +3 -8
- package/.agent-src/rules/ui-audit-before-build.md +106 -0
- package/.agent-src/rules/user-interaction.md +82 -50
- package/.agent-src/scripts/update_roadmap_progress.py +17 -5
- package/.agent-src/skills/blade-ui/SKILL.md +30 -5
- package/.agent-src/skills/command-routing/SKILL.md +32 -0
- package/.agent-src/skills/command-writing/SKILL.md +41 -2
- package/.agent-src/skills/description-assist/SKILL.md +21 -0
- package/.agent-src/skills/estimate-ticket/SKILL.md +0 -1
- package/.agent-src/skills/existing-ui-audit/SKILL.md +187 -0
- package/.agent-src/skills/fe-design/SKILL.md +72 -60
- package/.agent-src/skills/finishing-a-development-branch/SKILL.md +4 -0
- package/.agent-src/skills/flux/SKILL.md +31 -4
- package/.agent-src/skills/guideline-writing/SKILL.md +24 -2
- package/.agent-src/skills/learning-to-rule-or-skill/SKILL.md +51 -9
- package/.agent-src/skills/livewire/SKILL.md +30 -4
- package/.agent-src/skills/md-language-check/SKILL.md +103 -0
- package/.agent-src/skills/php-coder/SKILL.md +24 -0
- package/.agent-src/skills/react-shadcn-ui/SKILL.md +121 -0
- package/.agent-src/skills/refine-prompt/SKILL.md +220 -0
- package/.agent-src/skills/refine-ticket/SKILL.md +2 -4
- package/.agent-src/skills/roadmap-management/SKILL.md +10 -3
- package/.agent-src/skills/rule-writing/SKILL.md +23 -1
- package/.agent-src/skills/skill-writing/SKILL.md +1 -3
- package/.agent-src/skills/upstream-contribute/SKILL.md +1 -1
- package/.agent-src/skills/using-git-worktrees/SKILL.md +3 -1
- package/.agent-src/templates/AGENTS.md +24 -6
- package/.agent-src/templates/agent-settings.md +149 -0
- package/.agent-src/templates/roadmaps.md +8 -2
- package/.agent-src/templates/scripts/implement_ticket/__init__.py +63 -26
- package/.agent-src/templates/scripts/implement_ticket/__main__.py +8 -2
- package/.agent-src/templates/scripts/telemetry/__init__.py +42 -0
- package/.agent-src/templates/scripts/telemetry/aggregator.py +154 -0
- package/.agent-src/templates/scripts/telemetry/boundary.py +171 -0
- package/.agent-src/templates/scripts/telemetry/engagement.py +238 -0
- package/.agent-src/templates/scripts/telemetry/report_renderer.py +170 -0
- package/.agent-src/templates/scripts/telemetry/settings.py +112 -0
- package/.agent-src/templates/scripts/telemetry_record.py +166 -0
- package/.agent-src/templates/scripts/telemetry_report.py +161 -0
- package/.agent-src/templates/scripts/telemetry_status.py +142 -0
- package/.agent-src/templates/scripts/work_engine/__init__.py +58 -0
- package/.agent-src/templates/scripts/work_engine/__main__.py +9 -0
- package/.agent-src/templates/scripts/work_engine/cli.py +592 -0
- package/.agent-src/templates/scripts/{implement_ticket → work_engine}/delivery_state.py +7 -0
- package/.agent-src/templates/scripts/work_engine/directives/__init__.py +33 -0
- package/.agent-src/templates/scripts/work_engine/directives/backend/__init__.py +98 -0
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/analyze.py +1 -1
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/implement.py +2 -2
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/memory.py +1 -1
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/plan.py +1 -1
- package/.agent-src/templates/scripts/work_engine/directives/backend/refine.py +396 -0
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/report.py +36 -4
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/test.py +2 -2
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/verify.py +2 -2
- package/.agent-src/templates/scripts/work_engine/directives/mixed/__init__.py +116 -0
- package/.agent-src/templates/scripts/work_engine/directives/mixed/contract.py +254 -0
- package/.agent-src/templates/scripts/work_engine/directives/mixed/stitch.py +229 -0
- package/.agent-src/templates/scripts/work_engine/directives/mixed/ui.py +231 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/__init__.py +113 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/_passthrough.py +44 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/apply.py +241 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/audit.py +414 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/design.py +335 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/polish.py +510 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/review.py +468 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/__init__.py +119 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/_skipped.py +37 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/apply.py +165 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/refine.py +66 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/report.py +62 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/test.py +115 -0
- package/.agent-src/templates/scripts/work_engine/dispatcher.py +331 -0
- package/.agent-src/templates/scripts/work_engine/hooks/__init__.py +54 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/__init__.py +32 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/_chat_history_base.py +103 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_append.py +44 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_halt_append.py +42 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_heartbeat.py +50 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_turn_check.py +49 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/directive_set_guard.py +53 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/halt_surface_audit.py +50 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/state_shape_validation.py +52 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/trace.py +84 -0
- package/.agent-src/templates/scripts/work_engine/hooks/context.py +66 -0
- package/.agent-src/templates/scripts/work_engine/hooks/events.py +44 -0
- package/.agent-src/templates/scripts/work_engine/hooks/exceptions.py +79 -0
- package/.agent-src/templates/scripts/work_engine/hooks/registry.py +60 -0
- package/.agent-src/templates/scripts/work_engine/hooks/runner.py +73 -0
- package/.agent-src/templates/scripts/work_engine/hooks/settings.py +141 -0
- package/.agent-src/templates/scripts/work_engine/intent/__init__.py +47 -0
- package/.agent-src/templates/scripts/work_engine/intent/classify.py +280 -0
- package/.agent-src/templates/scripts/work_engine/migration/__init__.py +8 -0
- package/.agent-src/templates/scripts/work_engine/migration/v0_to_v1.py +199 -0
- package/.agent-src/templates/scripts/work_engine/resolvers/__init__.py +22 -0
- package/.agent-src/templates/scripts/work_engine/resolvers/diff.py +106 -0
- package/.agent-src/templates/scripts/work_engine/resolvers/file.py +113 -0
- package/.agent-src/templates/scripts/work_engine/resolvers/prompt.py +90 -0
- package/.agent-src/templates/scripts/work_engine/scoring/__init__.py +14 -0
- package/.agent-src/templates/scripts/work_engine/scoring/confidence.py +300 -0
- package/.agent-src/templates/scripts/work_engine/stack/__init__.py +31 -0
- package/.agent-src/templates/scripts/work_engine/stack/detect.py +187 -0
- package/.agent-src/templates/scripts/work_engine/state.py +641 -0
- package/.claude-plugin/marketplace.json +105 -2
- package/AGENTS.md +36 -8
- package/CHANGELOG.md +534 -0
- package/README.md +125 -4
- package/config/agent-settings.template.yml +45 -0
- package/config/gitignore-block.txt +4 -0
- package/docs/architecture.md +28 -1
- package/docs/development.md +1 -1
- package/docs/getting-started.md +2 -2
- package/docs/installation.md +86 -0
- package/docs/showcase.md +204 -0
- package/package.json +1 -1
- package/scripts/agent-config +199 -0
- package/scripts/audit_cloud_compatibility.py +288 -0
- package/scripts/build_cloud_bundle.py +458 -0
- package/scripts/build_linear_digest.py +263 -0
- package/scripts/chat_history.py +796 -7
- package/scripts/check_compression.py +139 -0
- package/scripts/check_iron_law_prominence.py +143 -0
- package/scripts/check_md_language.py +159 -0
- package/scripts/check_portability.py +36 -0
- package/scripts/check_reply_consistency.py +140 -0
- package/scripts/command_suggester/__init__.py +51 -0
- package/scripts/command_suggester/cooldown.py +132 -0
- package/scripts/command_suggester/loader.py +70 -0
- package/scripts/command_suggester/match.py +180 -0
- package/scripts/command_suggester/rank.py +120 -0
- package/scripts/command_suggester/render.py +86 -0
- package/scripts/command_suggester/sanitize.py +113 -0
- package/scripts/command_suggester/settings.py +125 -0
- package/scripts/command_suggester/types.py +78 -0
- package/scripts/hooks/augment-chat-history.sh +56 -0
- package/scripts/install-hooks.sh +67 -0
- package/scripts/install.py +150 -33
- package/scripts/lint_marketplace.py +27 -0
- package/scripts/migrate_command_suggestions.py +151 -0
- package/scripts/schemas/command.schema.json +41 -0
- package/scripts/skill_linter.py +67 -0
- package/scripts/sync_agent_settings.py +42 -12
- package/templates/consumer-settings/augment-cli-hooks.json +54 -0
- package/templates/consumer-settings/claude-settings.json +55 -1
- package/.agent-src/templates/scripts/implement_ticket/cli.py +0 -171
- package/.agent-src/templates/scripts/implement_ticket/dispatcher.py +0 -134
- package/.agent-src/templates/scripts/implement_ticket/steps/__init__.py +0 -49
- package/.agent-src/templates/scripts/implement_ticket/steps/refine.py +0 -140
- /package/.agent-src/templates/scripts/{implement_ticket → work_engine}/persona_policy.py +0 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""build_linear_digest.py — build the Linear AI rules digest.
|
|
3
|
+
|
|
4
|
+
Concatenates a curated set of cloud-safe rules from
|
|
5
|
+
`.agent-src.uncompressed/rules/` into three Markdown files under
|
|
6
|
+
`dist/linear/`:
|
|
7
|
+
|
|
8
|
+
workspace.md — universal coding posture (18 rules)
|
|
9
|
+
team.md — framework-specific (4 rules; paste only where stack matches)
|
|
10
|
+
personal.md — empty stub for individual preferences
|
|
11
|
+
|
|
12
|
+
Per-rule inclusion + mode is the source of truth in
|
|
13
|
+
`agents/contexts/linear-ai-rules-inclusion.md`. This script encodes the
|
|
14
|
+
same lists so a drift between the two surfaces is caught by the digest
|
|
15
|
+
audit (Phase 3 Step 4) — the markdown doc is the human-readable spec,
|
|
16
|
+
this script is the executable.
|
|
17
|
+
|
|
18
|
+
Transformations applied to every included rule:
|
|
19
|
+
|
|
20
|
+
1. Strip YAML frontmatter.
|
|
21
|
+
2. Demote the rule's H1 to H2 (H1 stays for the digest's own title).
|
|
22
|
+
3. Replace `[text](path.md...)` links with plain `text` — paths do
|
|
23
|
+
not resolve outside the repo. External `http(s)` links are kept.
|
|
24
|
+
4. For rules tagged ``degraded`` in DEGRADE_RULES, strip the named
|
|
25
|
+
H2/H3 sections (cloud-irrelevant content like `.agent-settings.yml`
|
|
26
|
+
references, rtk Iron Law, English-`.md`-files clause, etc.).
|
|
27
|
+
|
|
28
|
+
Outputs and exit code:
|
|
29
|
+
|
|
30
|
+
- Writes to dist/linear/{workspace,team,personal}.md
|
|
31
|
+
- Stdout: per-digest size summary (chars, rules, sections stripped)
|
|
32
|
+
- Exit 0 on success
|
|
33
|
+
- Exit 2 if any digest exceeds --max-bytes (Phase 3 Step 4 budget gate)
|
|
34
|
+
- Exit 3 if a referenced rule file is missing
|
|
35
|
+
"""
|
|
36
|
+
from __future__ import annotations
|
|
37
|
+
|
|
38
|
+
import argparse
|
|
39
|
+
import re
|
|
40
|
+
import sys
|
|
41
|
+
from dataclasses import dataclass, field
|
|
42
|
+
from pathlib import Path
|
|
43
|
+
|
|
44
|
+
ROOT = Path(__file__).resolve().parent.parent
|
|
45
|
+
# Compressed source is the shipped form — denser, sharper section
|
|
46
|
+
# structure; better fit for a guidance field than the verbose authoring
|
|
47
|
+
# layer. The inclusion list at agents/contexts/linear-ai-rules-inclusion.md
|
|
48
|
+
# remains the human-readable spec.
|
|
49
|
+
SOURCE = ROOT / ".agent-src" / "rules"
|
|
50
|
+
OUT_DIR = ROOT / "dist" / "linear"
|
|
51
|
+
|
|
52
|
+
# Linear does not publish a hard cap on agent-guidance fields. 100 KB
|
|
53
|
+
# is generous for every observed agent surface (Linear Agent, Codegen,
|
|
54
|
+
# Charlie); tighten via --max-bytes once the actual cap is researched
|
|
55
|
+
# (Open Question #1 in road-to-universal-distribution.md).
|
|
56
|
+
DEFAULT_MAX_BYTES = 100_000
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclass
|
|
60
|
+
class RuleEntry:
|
|
61
|
+
name: str
|
|
62
|
+
mode: str = "as-is" # "as-is" | "degraded"
|
|
63
|
+
strip_sections: list[str] = field(default_factory=list)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# Workspace digest — universal coding posture. Maps 1:1 to the
|
|
67
|
+
# "Workspace digest" table in agents/contexts/linear-ai-rules-inclusion.md.
|
|
68
|
+
WORKSPACE: list[RuleEntry] = [
|
|
69
|
+
RuleEntry("ask-when-uncertain"),
|
|
70
|
+
RuleEntry("commit-conventions"),
|
|
71
|
+
RuleEntry("context-hygiene", "degraded",
|
|
72
|
+
strip_sections=["Augment-specific: Ignored Skills Recovery"]),
|
|
73
|
+
RuleEntry("direct-answers"),
|
|
74
|
+
RuleEntry("markdown-safe-codeblocks"),
|
|
75
|
+
RuleEntry("minimal-safe-diff"),
|
|
76
|
+
RuleEntry("reviewer-awareness"),
|
|
77
|
+
RuleEntry("scope-control"),
|
|
78
|
+
RuleEntry("security-sensitive-stop"),
|
|
79
|
+
RuleEntry("think-before-action", "degraded",
|
|
80
|
+
strip_sections=["Consult memory before editing"]),
|
|
81
|
+
RuleEntry("verify-before-complete"),
|
|
82
|
+
RuleEntry("cli-output-handling", "degraded",
|
|
83
|
+
strip_sections=["Iron Law — rtk first, tail/grep fallback"]),
|
|
84
|
+
RuleEntry("downstream-changes"),
|
|
85
|
+
RuleEntry("improve-before-implement"),
|
|
86
|
+
RuleEntry("language-and-tone", "degraded",
|
|
87
|
+
strip_sections=["`.md` files are ALWAYS English — no exceptions"]),
|
|
88
|
+
RuleEntry("missing-tool-handling"),
|
|
89
|
+
RuleEntry("token-efficiency"),
|
|
90
|
+
RuleEntry("user-interaction"),
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
# Team digest — framework-specific. Stack already named in each rule's
|
|
94
|
+
# trigger line; no per-rule stripping required.
|
|
95
|
+
TEAM: list[RuleEntry] = [
|
|
96
|
+
RuleEntry("docker-commands"),
|
|
97
|
+
RuleEntry("laravel-translations"),
|
|
98
|
+
RuleEntry("e2e-testing"),
|
|
99
|
+
RuleEntry("php-coding"),
|
|
100
|
+
]
|
|
101
|
+
|
|
102
|
+
# Personal digest is empty by default — just a stub.
|
|
103
|
+
PERSONAL: list[RuleEntry] = []
|
|
104
|
+
|
|
105
|
+
FRONTMATTER_RE = re.compile(r"^---\n.*?\n---\n", re.DOTALL)
|
|
106
|
+
LINK_RE = re.compile(r"\[([^\]]+)\]\((?!https?://)[^)]+\)")
|
|
107
|
+
H1_RE = re.compile(r"^# ", re.MULTILINE)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def strip_frontmatter(text: str) -> str:
|
|
111
|
+
return FRONTMATTER_RE.sub("", text, count=1).lstrip()
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def demote_h1(text: str) -> str:
|
|
115
|
+
"""Promote rule H1 to H2 so the digest H1 stays the only top-level."""
|
|
116
|
+
return H1_RE.sub("## ", text, count=1)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def normalize_links(text: str) -> str:
|
|
120
|
+
"""Replace internal markdown links with their plain anchor text.
|
|
121
|
+
|
|
122
|
+
Internal = relative path or repo-rooted path. External http(s)
|
|
123
|
+
links are preserved verbatim.
|
|
124
|
+
"""
|
|
125
|
+
return LINK_RE.sub(r"\1", text)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def strip_section(text: str, section_title: str) -> tuple[str, bool]:
|
|
129
|
+
"""Strip an H2/H3 section by exact title match (without trailing comments)."""
|
|
130
|
+
pattern = re.compile(
|
|
131
|
+
rf"^(#{{2,3}})\s+{re.escape(section_title)}\s*\n.*?(?=^#{{1,3}}\s|\Z)",
|
|
132
|
+
re.DOTALL | re.MULTILINE,
|
|
133
|
+
)
|
|
134
|
+
new_text, count = pattern.subn("", text)
|
|
135
|
+
return new_text, count > 0
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def render_rule(entry: RuleEntry) -> tuple[str, list[str]]:
|
|
139
|
+
"""Render one rule as a digest section.
|
|
140
|
+
|
|
141
|
+
Returns (markdown, missing_sections). missing_sections is non-empty
|
|
142
|
+
when a strip_sections entry did not match — a likely drift signal
|
|
143
|
+
between this script and the source rule.
|
|
144
|
+
"""
|
|
145
|
+
path = SOURCE / f"{entry.name}.md"
|
|
146
|
+
if not path.is_file():
|
|
147
|
+
raise FileNotFoundError(f"Rule source missing: {path}")
|
|
148
|
+
|
|
149
|
+
text = path.read_text(encoding="utf-8")
|
|
150
|
+
text = strip_frontmatter(text)
|
|
151
|
+
text = demote_h1(text)
|
|
152
|
+
text = normalize_links(text)
|
|
153
|
+
|
|
154
|
+
missing: list[str] = []
|
|
155
|
+
if entry.mode == "degraded":
|
|
156
|
+
for section in entry.strip_sections:
|
|
157
|
+
text, found = strip_section(text, section)
|
|
158
|
+
if not found:
|
|
159
|
+
missing.append(section)
|
|
160
|
+
|
|
161
|
+
# Collapse any double-blank-lines created by stripping.
|
|
162
|
+
text = re.sub(r"\n{3,}", "\n\n", text).rstrip() + "\n"
|
|
163
|
+
return text, missing
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def render_digest(layer: str, entries: list[RuleEntry]) -> tuple[str, dict]:
|
|
167
|
+
parts: list[str] = []
|
|
168
|
+
parts.append(f"# event4u/agent-config — Linear AI {layer.title()} Digest\n")
|
|
169
|
+
parts.append(
|
|
170
|
+
"> Auto-generated by `scripts/build_linear_digest.py` from "
|
|
171
|
+
"`.agent-src/rules/` (compressed source) plus the inclusion list "
|
|
172
|
+
"at `agents/contexts/linear-ai-rules-inclusion.md`. Do not edit "
|
|
173
|
+
"this file by hand — re-run `task build-linear-digest` to "
|
|
174
|
+
"regenerate.\n"
|
|
175
|
+
)
|
|
176
|
+
if layer == "personal":
|
|
177
|
+
parts.append(
|
|
178
|
+
"\nPersonal guidance is intentionally empty — paste your own "
|
|
179
|
+
"preferences (response language overrides, IDE shortcuts, naming "
|
|
180
|
+
"conventions) below this line.\n"
|
|
181
|
+
)
|
|
182
|
+
return "".join(parts), {"layer": layer, "rules": 0, "missing": {}}
|
|
183
|
+
|
|
184
|
+
if not entries:
|
|
185
|
+
parts.append("\n_No rules in this digest._\n")
|
|
186
|
+
return "".join(parts), {"layer": layer, "rules": 0, "missing": {}}
|
|
187
|
+
|
|
188
|
+
parts.append(
|
|
189
|
+
f"\n_{len(entries)} rules included. Order matches the inclusion "
|
|
190
|
+
"list._\n\n---\n\n"
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
missing_per_rule: dict[str, list[str]] = {}
|
|
194
|
+
for i, entry in enumerate(entries):
|
|
195
|
+
body, missing = render_rule(entry)
|
|
196
|
+
if missing:
|
|
197
|
+
missing_per_rule[entry.name] = missing
|
|
198
|
+
parts.append(body)
|
|
199
|
+
if i < len(entries) - 1:
|
|
200
|
+
parts.append("\n---\n\n")
|
|
201
|
+
|
|
202
|
+
return "".join(parts), {
|
|
203
|
+
"layer": layer,
|
|
204
|
+
"rules": len(entries),
|
|
205
|
+
"missing": missing_per_rule,
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def main(argv: list[str] | None = None) -> int:
|
|
210
|
+
p = argparse.ArgumentParser(description=__doc__.split("\n", 1)[0])
|
|
211
|
+
p.add_argument("--max-bytes", type=int, default=DEFAULT_MAX_BYTES,
|
|
212
|
+
help=f"per-digest byte budget (default {DEFAULT_MAX_BYTES})")
|
|
213
|
+
p.add_argument("--out-dir", type=Path, default=OUT_DIR,
|
|
214
|
+
help="output directory (default dist/linear/)")
|
|
215
|
+
p.add_argument("--strict-missing", action="store_true",
|
|
216
|
+
help="exit non-zero if a strip_sections title is unmatched")
|
|
217
|
+
args = p.parse_args(argv)
|
|
218
|
+
|
|
219
|
+
args.out_dir.mkdir(parents=True, exist_ok=True)
|
|
220
|
+
|
|
221
|
+
layers = [("workspace", WORKSPACE), ("team", TEAM), ("personal", PERSONAL)]
|
|
222
|
+
over_budget = False
|
|
223
|
+
drift = False
|
|
224
|
+
|
|
225
|
+
for layer, entries in layers:
|
|
226
|
+
try:
|
|
227
|
+
digest, summary = render_digest(layer, entries)
|
|
228
|
+
except FileNotFoundError as exc:
|
|
229
|
+
print(f"❌ {exc}", file=sys.stderr)
|
|
230
|
+
return 3
|
|
231
|
+
|
|
232
|
+
out_path = args.out_dir / f"{layer}.md"
|
|
233
|
+
out_path.write_text(digest, encoding="utf-8")
|
|
234
|
+
size = len(digest.encode("utf-8"))
|
|
235
|
+
flag = "⚠️ " if size > args.max_bytes else " "
|
|
236
|
+
try:
|
|
237
|
+
display_path = out_path.relative_to(ROOT)
|
|
238
|
+
except ValueError:
|
|
239
|
+
display_path = out_path
|
|
240
|
+
print(f"{flag}{layer:<10} {summary['rules']:>2} rules "
|
|
241
|
+
f"{size:>6} bytes {display_path}")
|
|
242
|
+
if size > args.max_bytes:
|
|
243
|
+
over_budget = True
|
|
244
|
+
if summary["missing"]:
|
|
245
|
+
drift = True
|
|
246
|
+
for name, sections in summary["missing"].items():
|
|
247
|
+
print(f" ⚠️ {name}: unmatched strip_sections: {sections}",
|
|
248
|
+
file=sys.stderr)
|
|
249
|
+
|
|
250
|
+
if over_budget:
|
|
251
|
+
print(f"❌ one or more digests exceed --max-bytes={args.max_bytes}",
|
|
252
|
+
file=sys.stderr)
|
|
253
|
+
return 2
|
|
254
|
+
if drift and args.strict_missing:
|
|
255
|
+
print("❌ --strict-missing: at least one strip_sections title did "
|
|
256
|
+
"not match (digest config drifted from rule source)",
|
|
257
|
+
file=sys.stderr)
|
|
258
|
+
return 4
|
|
259
|
+
return 0
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
if __name__ == "__main__":
|
|
263
|
+
sys.exit(main())
|