@event4u/agent-config 5.7.0 → 5.9.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 +1 -1
- package/.agent-src/commands/agent-status.md +1 -1
- package/.agent-src/commands/agents/audit.md +1 -1
- package/.agent-src/commands/agents/init.md +1 -1
- package/.agent-src/commands/agents/user/accept.md +3 -3
- package/.agent-src/commands/agents/user/init.md +4 -4
- package/.agent-src/commands/agents/user/show.md +3 -3
- package/.agent-src/commands/agents/user/update.md +3 -3
- package/.agent-src/commands/agents/user.md +1 -1
- package/.agent-src/commands/agents.md +1 -1
- package/.agent-src/commands/analytics/prune.md +1 -1
- package/.agent-src/commands/analytics/show.md +1 -1
- package/.agent-src/commands/analytics.md +1 -1
- package/.agent-src/commands/bug-fix.md +1 -1
- package/.agent-src/commands/challenge-me.md +1 -1
- package/.agent-src/commands/chat-history/import.md +1 -1
- package/.agent-src/commands/chat-history/learn.md +1 -1
- package/.agent-src/commands/chat-history/show.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/condense.md +1 -1
- package/.agent-src/commands/context.md +1 -1
- package/.agent-src/commands/cost-report.md +1 -1
- package/.agent-src/commands/council.md +3 -3
- package/.agent-src/commands/create-pr/description-only.md +1 -1
- package/.agent-src/commands/create-pr.md +1 -1
- package/.agent-src/commands/e2e-heal.md +1 -1
- package/.agent-src/commands/e2e-plan.md +1 -1
- package/.agent-src/commands/feature.md +1 -1
- package/.agent-src/commands/fix/ci.md +1 -1
- package/.agent-src/commands/fix/portability.md +1 -1
- package/.agent-src/commands/fix/pr-bot-comments.md +1 -1
- package/.agent-src/commands/fix/pr-comments.md +1 -1
- package/.agent-src/commands/fix/pr-developer-comments.md +1 -1
- package/.agent-src/commands/fix/refs.md +1 -1
- package/.agent-src/commands/fix/seeder.md +1 -1
- package/.agent-src/commands/fix.md +1 -1
- package/.agent-src/commands/judge.md +1 -1
- package/.agent-src/commands/knowledge/cross-repo.md +1 -1
- package/.agent-src/commands/knowledge/forget.md +1 -1
- package/.agent-src/commands/knowledge/ingest.md +1 -1
- package/.agent-src/commands/knowledge/list.md +1 -1
- package/.agent-src/commands/knowledge.md +1 -1
- package/.agent-src/commands/memory/add.md +1 -1
- package/.agent-src/commands/memory/learn-low-impact.md +1 -1
- package/.agent-src/commands/memory/load.md +1 -1
- package/.agent-src/commands/memory/mine-session.md +1 -1
- package/.agent-src/commands/memory/promote.md +1 -1
- package/.agent-src/commands/memory/propose.md +1 -1
- package/.agent-src/commands/memory.md +1 -1
- package/.agent-src/commands/mode.md +1 -1
- package/.agent-src/commands/optimize/agents-dir.md +1 -1
- package/.agent-src/commands/optimize/augmentignore.md +1 -1
- package/.agent-src/commands/optimize/rtk.md +1 -1
- package/.agent-src/commands/optimize/skills.md +1 -1
- package/.agent-src/commands/optimize.md +1 -1
- package/.agent-src/commands/orchestrate.md +1 -1
- package/.agent-src/commands/override/create.md +1 -1
- package/.agent-src/commands/override/manage.md +1 -1
- package/.agent-src/commands/override.md +1 -1
- package/.agent-src/commands/package-reset.md +1 -1
- package/.agent-src/commands/prediction-pool.md +31 -12
- package/.agent-src/commands/profile/activate.md +81 -0
- package/.agent-src/commands/profile/deactivate.md +68 -0
- package/.agent-src/commands/profile/show.md +70 -0
- package/.agent-src/commands/profile.md +68 -0
- package/.agent-src/commands/project-health.md +1 -1
- package/.agent-src/commands/quality-fix.md +1 -1
- package/.agent-src/commands/roadmap/process-full.md +1 -1
- package/.agent-src/commands/roadmap/process-phase.md +1 -1
- package/.agent-src/commands/roadmap/process-step.md +1 -1
- package/.agent-src/commands/roadmap.md +1 -1
- package/.agent-src/commands/set-cost-profile.md +1 -1
- package/.agent-src/commands/skill/preview.md +3 -3
- package/.agent-src/commands/skill.md +1 -1
- package/.agent-src/commands/skills/discover.md +1 -1
- package/.agent-src/commands/skills.md +1 -1
- package/.agent-src/commands/sync-agent-settings.md +1 -1
- package/.agent-src/commands/sync-gitignore/fix.md +1 -1
- package/.agent-src/commands/sync-gitignore.md +1 -1
- package/.agent-src/commands/update-form-request-messages.md +1 -1
- package/.agent-src/skills/check-refs/SKILL.md +1 -1
- package/.agent-src/skills/finishing-a-development-branch/SKILL.md +1 -1
- package/.agent-src/skills/git-workflow/SKILL.md +1 -1
- package/.agent-src/skills/jira-integration/SKILL.md +1 -1
- package/.agent-src/skills/markitdown/SKILL.md +1 -1
- package/.agent-src/skills/prediction-pool-optimizer/SKILL.md +195 -77
- package/.agent-src/skills/prediction-pool-optimizer/evals/triggers.json +3 -1
- package/.agent-src/skills/prediction-pool-optimizer/reference/ev-fixtures.md +111 -16
- package/.agent-src/skills/prediction-pool-optimizer/reference/odds-and-bonus.md +109 -0
- package/.agent-src/skills/rtk-output-filtering/SKILL.md +1 -1
- package/.agent-src/skills/script-writing/SKILL.md +1 -1
- package/.agent-src/skills/token-optimizer/SKILL.md +1 -1
- package/.agent-src/skills/using-git-worktrees/SKILL.md +1 -1
- package/.agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/.agent-src/templates/scripts/work_engine/_lib/agent_settings.py +52 -5
- package/.claude-plugin/marketplace.json +370 -366
- package/CHANGELOG.md +77 -0
- package/README.md +2 -2
- package/config/discovery/session-profiles.yml +37 -0
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +183 -95
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +9 -5
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +8 -4
- package/dist/mcp/registry-manifest.json +3 -3
- package/docs/architecture.md +1 -1
- package/docs/catalog.md +7 -3
- package/docs/contracts/command-clusters.md +2 -0
- package/docs/contracts/session-profile-overlay.md +120 -0
- package/docs/customization.md +26 -0
- package/docs/decisions/ADR-010-profile-pack-preset-boundary.md +36 -0
- package/docs/decisions/ADR-038-canonical-settings-path.md +66 -0
- package/docs/decisions/ADR-039-claude-skills-untracked.md +139 -0
- package/docs/decisions/INDEX.md +2 -0
- package/docs/development.md +12 -0
- package/docs/getting-started.md +1 -1
- package/docs/guidelines/agent-infra/layered-settings.md +8 -2
- package/docs/skills-catalog.md +5 -1
- package/llms.txt +4 -0
- package/package.json +1 -1
- package/scripts/__pycache__/validate_frontmatter.cpython-312.pyc +0 -0
- package/scripts/_cli/cmd_doctor.py +180 -16
- package/scripts/_cli/cmd_versions.py +2 -2
- package/scripts/_lib/__pycache__/__init__.cpython-312.pyc +0 -0
- package/scripts/_lib/__pycache__/agent_src.cpython-312.pyc +0 -0
- package/scripts/_lib/agent_settings.py +52 -5
- package/scripts/_lib/agent_src.py +30 -0
- package/scripts/ai_council/session.py +5 -1
- package/scripts/audit_command_surface.py +7 -1
- package/scripts/audit_initial_context.py +10 -2
- package/scripts/check_gate_paths.py +117 -0
- package/scripts/check_references.py +51 -2
- package/scripts/check_release_published.py +145 -0
- package/scripts/check_test_coverage_diff.py +180 -0
- package/scripts/compile_router.py +5 -1
- package/scripts/condense.py +79 -2
- package/scripts/config/session_profiles.py +492 -0
- package/scripts/council_cli.py +5 -1
- package/scripts/hook_manifest.yaml +15 -7
- package/scripts/hooks/dispatch_hook.py +8 -0
- package/scripts/install-hooks.sh +2 -1
- package/scripts/install.py +76 -5
- package/scripts/inventory_abstraction_budget.py +6 -1
- package/scripts/lint_agents_md.py +11 -4
- package/scripts/lint_hook_concern_budget.py +5 -1
- package/scripts/lint_marketplace.py +18 -7
- package/scripts/lint_roadmap_ci_steps.py +5 -1
- package/scripts/lint_roadmap_complexity.py +5 -1
- package/scripts/mcp_server/prompts.py +5 -1
- package/scripts/prediction-pool/pool_winsim.py +236 -0
- package/scripts/prediction-pool/score_ev.py +188 -0
- package/scripts/profile_staleness_hook.py +69 -0
- package/scripts/release.py +54 -31
- package/scripts/roadmap_progress_hook.py +56 -6
- package/scripts/smoke_quickstart.py +3 -2
- package/scripts/sync_agent_settings.py +8 -3
- package/scripts/validate_agent_settings.py +5 -1
- package/scripts/validate_decision_engine.py +5 -1
- package/scripts/measure_roadmap_trajectory.py +0 -112
- package/scripts/verify_roadmap_closure.py +0 -327
package/docs/development.md
CHANGED
|
@@ -127,6 +127,18 @@ task dev:link # Symlink this repo as the global @event4u/agent-
|
|
|
127
127
|
task dev:unlink # Remove the global symlink
|
|
128
128
|
```
|
|
129
129
|
|
|
130
|
+
**Switch the global install between dev and release** — one-shot toggles
|
|
131
|
+
that flip BOTH the `agent-config` bin on PATH and the user-scope content:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
task install:use-dev # global = THIS working tree (npm link + dev-build content)
|
|
135
|
+
task install:use-release # global = latest npm release (npm i -g @latest + release content)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Run `install:use-dev` to test the working tree as the live global install,
|
|
139
|
+
then `install:use-release` to switch back to the published version. They are
|
|
140
|
+
symmetric — whichever you run last is the active global `agent-config`.
|
|
141
|
+
|
|
130
142
|
**Typical flow:**
|
|
131
143
|
|
|
132
144
|
1. In this repo: `task dev:link` — once. The `agent-config` bin on PATH
|
package/docs/getting-started.md
CHANGED
|
@@ -169,7 +169,7 @@ Your agent now understands slash commands:
|
|
|
169
169
|
| `/quality-fix` | Run and fix all quality checks |
|
|
170
170
|
| `/chat-history` | Inspect the persistent chat-history log (read-only `show`) |
|
|
171
171
|
|
|
172
|
-
→ [Browse all
|
|
172
|
+
→ [Browse all 150 active commands](../.agent-src/commands/)
|
|
173
173
|
|
|
174
174
|
---
|
|
175
175
|
|
|
@@ -19,7 +19,13 @@ on user request.
|
|
|
19
19
|
|---|---|---|---|---|
|
|
20
20
|
| `.agent-project-settings.yml` | **committed** | team / repo | lead maintainer | `project.stack`, `quality.php.tools`, `memory.dogfood` |
|
|
21
21
|
| `~/.event4u/agent-config/agent-settings.yml` | **n/a** (outside repo) | individual developer · cross-project | individual | `name`, `ide`, `rule_loading_tier`, `personal.bot_icon`, `personal.autonomy`, `telegraph.speak_scope` (legacy `~/.config/agent-config/agent-settings.yml` read as fallback) |
|
|
22
|
-
|
|
|
22
|
+
| `agents/settings/.agent-settings.yml` | **gitignored** | individual developer · this project | individual | `personal.ide`, `personal.user_name`, `subagents.max_parallel`, `onboarding.onboarded` |
|
|
23
|
+
|
|
24
|
+
> **Canonical location (ADR-038):** the developer file lives in the settings
|
|
25
|
+
> layer at `agents/settings/.agent-settings.yml` (alongside
|
|
26
|
+
> `.agent-settings.local.yml`, `contexts/`, `policies/`). A repo-root
|
|
27
|
+
> `.agent-settings.yml` is read as a **back-compat fallback** and is migrated
|
|
28
|
+
> into the canonical location by `install` on the next run.
|
|
23
29
|
|
|
24
30
|
All three are YAML. Schemas:
|
|
25
31
|
|
|
@@ -36,7 +42,7 @@ Lowest priority → highest priority:
|
|
|
36
42
|
1. Package defaults (shipped by event4u/agent-config)
|
|
37
43
|
2. ~/.event4u/agent-config/agent-settings.yml (user-global · whitelist-filtered · legacy ~/.config/agent-config/ read as fallback)
|
|
38
44
|
3. .agent-project-settings.yml (team file, committed)
|
|
39
|
-
4.
|
|
45
|
+
4. agents/settings/.agent-settings.yml (developer file, gitignored; legacy repo-root .agent-settings.yml read as fallback — ADR-038)
|
|
40
46
|
```
|
|
41
47
|
|
|
42
48
|
Keys from higher layers win unless a lower layer marks them
|
package/docs/skills-catalog.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Skills Catalog
|
|
2
2
|
|
|
3
|
-
All **
|
|
3
|
+
All **223 skills** available in this package, in alphabetical order.
|
|
4
4
|
Click a skill name to open its SKILL.md and read the full guidance.
|
|
5
5
|
|
|
6
6
|
> **Regenerate:** `python3 scripts/generate_catalog.py`
|
|
@@ -89,6 +89,8 @@ Click a skill name to open its SKILL.md and read the full guidance.
|
|
|
89
89
|
| [`gtm-launch`](../.agent-src/skills/gtm-launch/SKILL.md) | Use when sequencing a launch — alpha / beta / GA waves, audience-by-wave logic, narrative beats per wave, engineering-readiness gates. Triggers on 'plan the launch', 'sequence GA'. |
|
|
90
90
|
| [`guideline-writing`](../.agent-src/skills/guideline-writing/SKILL.md) | Use when creating or editing a guideline in docs/guidelines/ — reference material cited by skills, no auto-triggers — even when the user just says 'write up our naming conventions'. |
|
|
91
91
|
| [`hiring-loop-design`](../.agent-src/skills/hiring-loop-design/SKILL.md) | Use when shaping an engineering hiring loop — stages, take-home vs live, calibration, bar-raiser, signal-vs-noise audit. Triggers on 'design our interview loop', 'audit our hiring bar'. |
|
|
92
|
+
| [`image-analyser`](../.agent-src/skills/image-analyser/SKILL.md) | Use to analyse a character image down to the smallest mole and diff against a canon — per-feature spec, OCR-reads tattoo text, flags drift. Triggers 'analyse this image', 'match the canon'. |
|
|
93
|
+
| [`image-creator`](../.agent-src/skills/image-creator/SKILL.md) | Use to generate a character image to spec — max-fidelity reproducible prompt from a Canon Spec, anchors-first, provider/governance-gated. Triggers 'generate this character', 'render to spec'. |
|
|
92
94
|
| [`incident-commander`](../.agent-src/skills/incident-commander/SKILL.md) | Use during or right after an incident — frames severity, sets comms cadence, drafts the post-mortem skeleton — even when the user just says 'production is down' or 'wir haben einen Vorfall'. |
|
|
93
95
|
| [`jira-integration`](../.agent-src/skills/jira-integration/SKILL.md) | Use when the user says "check Jira", "create ticket", "update issue", or needs JQL queries, ticket transitions, or branch-to-ticket linking. |
|
|
94
96
|
| [`jobs-events`](../.agent-src/skills/jobs-events/SKILL.md) | Use when creating Laravel jobs, queued workflows, events, or listeners. Covers clear responsibilities, safe serialization, and retry/failure handling. |
|
|
@@ -152,6 +154,7 @@ Click a skill name to open its SKILL.md and read the full guidance.
|
|
|
152
154
|
| [`playwright-testing`](../.agent-src/skills/playwright-testing/SKILL.md) | Use when writing Playwright E2E tests — browser automation, visual regression testing, Page Objects, fixtures, and reliable test patterns. |
|
|
153
155
|
| [`po-discovery`](../.agent-src/skills/po-discovery/SKILL.md) | Use when shaping a fuzzy product ask into a refined backlog item — problem framing, user-story rewrite, AC tightening — even if the user just says 'help me write this ticket'. |
|
|
154
156
|
| [`positioning-strategy`](../.agent-src/skills/positioning-strategy/SKILL.md) | Use when locking the market frame — category, segment, alternative, point-of-view — before messaging, launch, or pricing rides on it. Triggers on 'who are we for', 'opposable audit'. |
|
|
157
|
+
| [`prediction-pool-optimizer`](../.agent-src/skills/prediction-pool-optimizer/SKILL.md) | Optimize prediction-pool tips (kicktipp etc.): rules + multi-book consensus odds → expected-points-max answer for every question, scores AND bonus. Triggers 'optimize my pool tips', 'predict'. |
|
|
155
158
|
| [`privacy-review`](../.agent-src/skills/privacy-review/SKILL.md) | Use when reviewing data flows, support macros, refund templates for GDPR/CCPA/HIPAA fit — regime, consent, PII redaction (email, order-id), breach triage. Triggers 'is this GDPR-safe', 'PII redact'. |
|
|
156
159
|
| [`project-analysis-core`](../.agent-src/skills/project-analysis-core/SKILL.md) | Raw discovery primitives — project discovery, version resolution, docs loading, architecture mapping, execution flow. Called by `universal-project-analysis`. Single-pass scan → `project-analyzer`. |
|
|
157
160
|
| [`project-analysis-hypothesis-driven`](../.agent-src/skills/project-analysis-hypothesis-driven/SKILL.md) | Use when a bug has multiple plausible causes across layers — competing hypotheses, validation loops, evidence-based conclusions — even when the user just says 'why is this happening?'. |
|
|
@@ -199,6 +202,7 @@ Click a skill name to open its SKILL.md and read the full guidance.
|
|
|
199
202
|
| [`skill-management`](../.agent-src/skills/skill-management/SKILL.md) | Use when condensing, decondenseing, refactoring, or improving existing skills. Covers the full skill lifecycle from verbose → sharp → maintained. |
|
|
200
203
|
| [`skill-reviewer`](../.agent-src/skills/skill-reviewer/SKILL.md) | Use when reviewing, auditing, or optimizing skills — validates against the 7 Skill Killers checklist and produces fix recommendations. |
|
|
201
204
|
| [`skill-writing`](../.agent-src/skills/skill-writing/SKILL.md) | Use when deciding 'should this be a skill or a rule?', creating/improving/reviewing agent skills, SKILL.md frontmatter, or procedure sections — even without saying 'skill-writing'. |
|
|
205
|
+
| [`song-to-script`](../.agent-src/skills/song-to-script/SKILL.md) | Turn an audio track into a timed `## Scene N` script: song sections → per-scene durations, auto mode adds mood + lip-sync lines. Triggers 'music video', 'from the song', 'cut to the beat'. |
|
|
202
206
|
| [`sql-writing`](../.agent-src/skills/sql-writing/SKILL.md) | Use when writing raw SQL — MariaDB/MySQL syntax, parameterization, raw migrations, seeders with `DB::statement` — even when the user just pastes a query and asks 'why is this slow' without naming SQL. |
|
|
203
207
|
| [`stakeholder-tradeoff`](../.agent-src/skills/stakeholder-tradeoff/SKILL.md) | Use when stakeholders pull a decision in different directions — frames each lens, builds a trade-off matrix, surfaces the cost of every choice — even if the user just says 'PO and ops disagree'. |
|
|
204
208
|
| [`subagent-orchestration`](../.agent-src/skills/subagent-orchestration/SKILL.md) | Use when orchestrating implementer/judge subagents — seven modes (do-and-judge ±two-stage, do-in-steps/parallel/worktrees, do-competitively, judge-with-debate) — models from .agent-settings.yml. |
|
package/llms.txt
CHANGED
|
@@ -87,6 +87,8 @@ grafana: Use when working with Grafana — dashboards, Loki LogQL queries, alert
|
|
|
87
87
|
gtm-launch: Use when sequencing a launch — alpha / beta / GA waves, audience-by-wave logic, narrative beats per wave, engineering-readiness gates. Triggers on 'plan the launch', 'sequence GA'.
|
|
88
88
|
guideline-writing: Use when creating or editing a guideline in docs/guidelines/ — reference material cited by skills, no auto-triggers — even when the user just says 'write up our naming conventions'.
|
|
89
89
|
hiring-loop-design: Use when shaping an engineering hiring loop — stages, take-home vs live, calibration, bar-raiser, signal-vs-noise audit. Triggers on 'design our interview loop', 'audit our hiring bar'.
|
|
90
|
+
image-analyser: Use to analyse a character image down to the smallest mole and diff against a canon — per-feature spec, OCR-reads tattoo text, flags drift. Triggers 'analyse this image', 'match the canon'.
|
|
91
|
+
image-creator: Use to generate a character image to spec — max-fidelity reproducible prompt from a Canon Spec, anchors-first, provider/governance-gated. Triggers 'generate this character', 'render to spec'.
|
|
90
92
|
incident-commander: Use during or right after an incident — frames severity, sets comms cadence, drafts the post-mortem skeleton — even when the user just says 'production is down' or 'wir haben einen Vorfall'.
|
|
91
93
|
jira-integration: Use when the user says "check Jira", "create ticket", "update issue", or needs JQL queries, ticket transitions, or branch-to-ticket linking.
|
|
92
94
|
jobs-events: Use when creating Laravel jobs, queued workflows, events, or listeners. Covers clear responsibilities, safe serialization, and retry/failure handling.
|
|
@@ -150,6 +152,7 @@ playwright-architect: Use when shaping a Playwright suite — locator strategy,
|
|
|
150
152
|
playwright-testing: Use when writing Playwright E2E tests — browser automation, visual regression testing, Page Objects, fixtures, and reliable test patterns.
|
|
151
153
|
po-discovery: Use when shaping a fuzzy product ask into a refined backlog item — problem framing, user-story rewrite, AC tightening — even if the user just says 'help me write this ticket'.
|
|
152
154
|
positioning-strategy: Use when locking the market frame — category, segment, alternative, point-of-view — before messaging, launch, or pricing rides on it. Triggers on 'who are we for', 'opposable audit'.
|
|
155
|
+
prediction-pool-optimizer: Optimize prediction-pool tips (kicktipp etc.): rules + multi-book consensus odds → expected-points-max answer for every question, scores AND bonus. Triggers 'optimize my pool tips', 'predict'.
|
|
153
156
|
privacy-review: Use when reviewing data flows, support macros, refund templates for GDPR/CCPA/HIPAA fit — regime, consent, PII redaction (email, order-id), breach triage. Triggers 'is this GDPR-safe', 'PII redact'.
|
|
154
157
|
project-analysis-core: Raw discovery primitives — project discovery, version resolution, docs loading, architecture mapping, execution flow. Called by `universal-project-analysis`. Single-pass scan → `project-analyzer`.
|
|
155
158
|
project-analysis-hypothesis-driven: Use when a bug has multiple plausible causes across layers — competing hypotheses, validation loops, evidence-based conclusions — even when the user just says 'why is this happening?'.
|
|
@@ -197,6 +200,7 @@ skill-improvement-pipeline: ONLY when user explicitly requests: run the skill im
|
|
|
197
200
|
skill-management: Use when condensing, decondenseing, refactoring, or improving existing skills. Covers the full skill lifecycle from verbose → sharp → maintained.
|
|
198
201
|
skill-reviewer: Use when reviewing, auditing, or optimizing skills — validates against the 7 Skill Killers checklist and produces fix recommendations.
|
|
199
202
|
skill-writing: Use when deciding 'should this be a skill or a rule?', creating/improving/reviewing agent skills, SKILL.md frontmatter, or procedure sections — even without saying 'skill-writing'.
|
|
203
|
+
song-to-script: Turn an audio track into a timed `## Scene N` script: song sections → per-scene durations, auto mode adds mood + lip-sync lines. Triggers 'music video', 'from the song', 'cut to the beat'.
|
|
200
204
|
sql-writing: Use when writing raw SQL — MariaDB/MySQL syntax, parameterization, raw migrations, seeders with `DB::statement` — even when the user just pastes a query and asks 'why is this slow' without naming SQL.
|
|
201
205
|
stakeholder-tradeoff: Use when stakeholders pull a decision in different directions — frames each lens, builds a trade-off matrix, surfaces the cost of every choice — even if the user just says 'PO and ops disagree'.
|
|
202
206
|
subagent-orchestration: Use when orchestrating implementer/judge subagents — seven modes (do-and-judge ±two-stage, do-in-steps/parallel/worktrees, do-competitively, judge-with-debate) — models from .agent-settings.yml.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@event4u/agent-config",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.9.0",
|
|
4
4
|
"description": "Universal AI Agent OS \u2014 audited skills, governance rules, commands, and templates for AI coding tools (Claude Code, Cursor, Windsurf, Copilot).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
Binary file
|
|
@@ -23,8 +23,16 @@ mcp-mode · mcp-beta-readiness · offline-readiness · python-runtime ·
|
|
|
23
23
|
tier-usage-readiness · council-cli · unsupported-combos ·
|
|
24
24
|
wizard-state.
|
|
25
25
|
Each emits a structured ``{id, status, message, remedy}`` record with
|
|
26
|
-
``status`` ∈ ``ok`` / ``warn`` / ``fail``
|
|
27
|
-
``❌``). ``--check <id>`` runs a single check.
|
|
26
|
+
``status`` ∈ ``ok`` / ``warn`` / ``fail`` / ``skipped`` (rendered
|
|
27
|
+
``✅`` / ``⚠️`` / ``❌`` / ``⏭️``). ``--check <id>`` runs a single check.
|
|
28
|
+
|
|
29
|
+
Checks are split by scope (:data:`GLOBAL_CHECK_IDS` vs
|
|
30
|
+
:data:`MANIFEST_REQUIRED_CHECK_IDS`) so an ADR-020 global-only consumer
|
|
31
|
+
(bridge marker present, no ``agents/installed-tools.lock``) gets a
|
|
32
|
+
green-capable report instead of a hard bail: the global checks run, the
|
|
33
|
+
manifest-required checks report ``skipped``, and ``bridge-drift`` returns
|
|
34
|
+
a scope-aware "drift not applicable" verdict. See :func:`main` for the
|
|
35
|
+
no-manifest branch and exit-code contract.
|
|
28
36
|
|
|
29
37
|
Repair affordances: ``--repair wizard-state`` resets a malformed or
|
|
30
38
|
orphaned ``state/wizard-state.json`` under the user-global root (the
|
|
@@ -55,6 +63,7 @@ from scripts._lib.agent_settings import (
|
|
|
55
63
|
ROOT_OVERRIDE_ENV,
|
|
56
64
|
ProjectRootError,
|
|
57
65
|
find_project_root_with_trace,
|
|
66
|
+
project_settings_path,
|
|
58
67
|
resolve_project_root,
|
|
59
68
|
)
|
|
60
69
|
|
|
@@ -131,7 +140,7 @@ def _settings_layer_chain(project_root: Path) -> list[str]:
|
|
|
131
140
|
user_global = user_global_paths.resolve_with_fallback("agent-settings.yml")
|
|
132
141
|
if user_global is not None and user_global.is_file():
|
|
133
142
|
layers.append(str(user_global))
|
|
134
|
-
project_settings = project_root
|
|
143
|
+
project_settings = project_settings_path(project_root)
|
|
135
144
|
if project_settings.is_file():
|
|
136
145
|
layers.append(str(project_settings))
|
|
137
146
|
return layers
|
|
@@ -454,6 +463,41 @@ CHECK_IDS = (
|
|
|
454
463
|
"wizard-state",
|
|
455
464
|
)
|
|
456
465
|
|
|
466
|
+
#: Checks that need only the project root (or no input at all) and run
|
|
467
|
+
#: regardless of whether a project lockfile exists. Under ADR-020
|
|
468
|
+
#: global-only (bridge marker present, no ``installed-tools.lock``) these
|
|
469
|
+
#: still produce a real verdict. ``scope`` lives here because
|
|
470
|
+
#: :func:`_check_scope` reads only ``project_root`` — the roadmap prose
|
|
471
|
+
#: that grouped it with the manifest checks predates this code reality
|
|
472
|
+
#: (AI council, claude-sonnet-4-5 + gpt-4o, design lens, 2026-06-02).
|
|
473
|
+
GLOBAL_CHECK_IDS: frozenset[str] = frozenset({
|
|
474
|
+
"scope",
|
|
475
|
+
"global-binary",
|
|
476
|
+
"mcp-mode",
|
|
477
|
+
"mcp-beta-readiness",
|
|
478
|
+
"offline-readiness",
|
|
479
|
+
"python-runtime",
|
|
480
|
+
"tier-usage-readiness",
|
|
481
|
+
"council-cli",
|
|
482
|
+
"wizard-state",
|
|
483
|
+
})
|
|
484
|
+
|
|
485
|
+
#: Checks that genuinely cannot run without the project manifest. Without
|
|
486
|
+
#: a lockfile they report ``skipped`` rather than a misleading verdict.
|
|
487
|
+
#: ``bridge-drift`` is deliberately **not** here: it is scope-aware —
|
|
488
|
+
#: a manifest-derived drift roll-up when the lockfile exists, and a
|
|
489
|
+
#: "drift not applicable (global-only consumer)" verdict when it does
|
|
490
|
+
#: not (computed in :func:`_check_bridge_drift_no_manifest`, keeping
|
|
491
|
+
#: :func:`_check_bridge_drift` a pure roll-up per the council's SRP point).
|
|
492
|
+
MANIFEST_REQUIRED_CHECK_IDS: frozenset[str] = frozenset({
|
|
493
|
+
"manifest-integrity",
|
|
494
|
+
"lockfile-freshness",
|
|
495
|
+
"unsupported-combos",
|
|
496
|
+
})
|
|
497
|
+
|
|
498
|
+
#: Project-root-relative path of the ADR-020 global-only consumer marker.
|
|
499
|
+
BRIDGE_MARKER_RELATIVE = "agents/.event4u-bridge.yml"
|
|
500
|
+
|
|
457
501
|
#: Repair targets that ``--repair <id>`` accepts. Each id maps to a
|
|
458
502
|
#: function in :func:`_run_repair` that resets the named artefact and
|
|
459
503
|
#: returns an exit code. Additive set: introduce by adding a new id
|
|
@@ -475,7 +519,7 @@ MCP_BETA_GATES: tuple[tuple[str, str], ...] = (
|
|
|
475
519
|
|
|
476
520
|
#: Visible status → glyph map. ``warn`` keeps a trailing space so the
|
|
477
521
|
#: rendered output stays in a single visual column with the other glyphs.
|
|
478
|
-
STATUS_SYMBOLS = {"ok": "✅", "warn": "⚠️ ", "fail": "❌"}
|
|
522
|
+
STATUS_SYMBOLS = {"ok": "✅", "warn": "⚠️ ", "fail": "❌", "skipped": "⏭️ "}
|
|
479
523
|
|
|
480
524
|
#: Minimum Python interpreter the CLI targets. Bumped in lockstep with
|
|
481
525
|
#: ``from __future__ import annotations`` + PEP-604 syntax usage.
|
|
@@ -778,7 +822,7 @@ def _check_tier_usage_readiness(project_root: Path) -> dict[str, Any]:
|
|
|
778
822
|
|
|
779
823
|
Contract: ``docs/contracts/command-clusters.md`` § tier-usage signal.
|
|
780
824
|
"""
|
|
781
|
-
settings_file = project_root
|
|
825
|
+
settings_file = project_settings_path(project_root)
|
|
782
826
|
log_path = project_root / ".agent-tier-usage.jsonl"
|
|
783
827
|
enabled = False
|
|
784
828
|
if settings_file.is_file():
|
|
@@ -1158,6 +1202,131 @@ def _run_checks(
|
|
|
1158
1202
|
return out
|
|
1159
1203
|
|
|
1160
1204
|
|
|
1205
|
+
def _skipped_manifest_check(check_id: str) -> dict[str, Any]:
|
|
1206
|
+
"""A ``skipped`` verdict for a manifest-required check with no lockfile.
|
|
1207
|
+
|
|
1208
|
+
Explicit machine-readable record (not omitted, not ``null``) so the
|
|
1209
|
+
``--json`` ``checks`` array keeps a stable shape for a global-only
|
|
1210
|
+
consumer — a council convergence point (2026-06-02).
|
|
1211
|
+
"""
|
|
1212
|
+
return {
|
|
1213
|
+
"id": check_id, "status": "skipped",
|
|
1214
|
+
"message": "requires a project lockfile (agents/installed-tools.lock)",
|
|
1215
|
+
"remedy": "run `agent-config init` to create a project lockfile, "
|
|
1216
|
+
"then re-run this check",
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
|
|
1220
|
+
def _check_bridge_drift_no_manifest(bridge_present: bool) -> dict[str, Any]:
|
|
1221
|
+
"""Scope-aware ``bridge-drift`` verdict when no project manifest exists.
|
|
1222
|
+
|
|
1223
|
+
Kept out of :func:`_check_bridge_drift` (which stays a pure
|
|
1224
|
+
manifest-derived roll-up) per the council's single-responsibility
|
|
1225
|
+
point. A global-only consumer has no distributed tools to drift, so
|
|
1226
|
+
a bridge-present repo reports ``ok`` ("not applicable"); a repo with
|
|
1227
|
+
neither lockfile nor bridge marker reports ``skipped``.
|
|
1228
|
+
"""
|
|
1229
|
+
if bridge_present:
|
|
1230
|
+
return {
|
|
1231
|
+
"id": "bridge-drift", "status": "ok",
|
|
1232
|
+
"message": "no project lockfile → distributed-tool drift not "
|
|
1233
|
+
"applicable (global-only consumer)",
|
|
1234
|
+
"remedy": "",
|
|
1235
|
+
}
|
|
1236
|
+
return {
|
|
1237
|
+
"id": "bridge-drift", "status": "skipped",
|
|
1238
|
+
"message": "no project lockfile and no bridge marker → drift check "
|
|
1239
|
+
"not applicable",
|
|
1240
|
+
"remedy": "run `agent-config init` (project install) or "
|
|
1241
|
+
"`agent-config refresh --project` (global-only consumer)",
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
|
|
1245
|
+
def _run_checks_no_manifest(
|
|
1246
|
+
project_root: Path,
|
|
1247
|
+
bridge_present: bool,
|
|
1248
|
+
only: str | None = None,
|
|
1249
|
+
) -> list[dict[str, Any]]:
|
|
1250
|
+
"""Run the registry with no project manifest available.
|
|
1251
|
+
|
|
1252
|
+
Mirrors :func:`_run_checks` and preserves :data:`CHECK_IDS` order.
|
|
1253
|
+
Global checks (:data:`GLOBAL_CHECK_IDS`) run unchanged; manifest-required
|
|
1254
|
+
checks (:data:`MANIFEST_REQUIRED_CHECK_IDS`) report ``skipped``;
|
|
1255
|
+
``bridge-drift`` gets the scope-aware no-manifest verdict.
|
|
1256
|
+
"""
|
|
1257
|
+
runners: dict[str, Any] = {
|
|
1258
|
+
"scope": lambda: _check_scope(project_root),
|
|
1259
|
+
"global-binary": lambda: _check_global_binary(project_root),
|
|
1260
|
+
"manifest-integrity": lambda: _skipped_manifest_check("manifest-integrity"),
|
|
1261
|
+
"lockfile-freshness": lambda: _skipped_manifest_check("lockfile-freshness"),
|
|
1262
|
+
"bridge-drift": lambda: _check_bridge_drift_no_manifest(bridge_present),
|
|
1263
|
+
"mcp-mode": lambda: _check_mcp_mode(project_root),
|
|
1264
|
+
"mcp-beta-readiness": lambda: _check_mcp_beta_readiness(project_root),
|
|
1265
|
+
"offline-readiness": lambda: _check_offline_readiness(),
|
|
1266
|
+
"python-runtime": lambda: _check_python_runtime(),
|
|
1267
|
+
"tier-usage-readiness": lambda: _check_tier_usage_readiness(project_root),
|
|
1268
|
+
"council-cli": lambda: _check_council_cli(project_root),
|
|
1269
|
+
"unsupported-combos": lambda: _skipped_manifest_check("unsupported-combos"),
|
|
1270
|
+
"wizard-state": _check_wizard_state,
|
|
1271
|
+
}
|
|
1272
|
+
out: list[dict[str, Any]] = []
|
|
1273
|
+
for cid in CHECK_IDS:
|
|
1274
|
+
if only is not None and cid != only:
|
|
1275
|
+
continue
|
|
1276
|
+
out.append(runners[cid]())
|
|
1277
|
+
return out
|
|
1278
|
+
|
|
1279
|
+
|
|
1280
|
+
def _run_no_manifest(
|
|
1281
|
+
opts: argparse.Namespace,
|
|
1282
|
+
project_root: Path,
|
|
1283
|
+
origin: str,
|
|
1284
|
+
bridge_present: bool,
|
|
1285
|
+
) -> int:
|
|
1286
|
+
"""Handle the no-project-lockfile path without the old hard bail.
|
|
1287
|
+
|
|
1288
|
+
Exit-code contract (council-defined, 2026-06-02):
|
|
1289
|
+
|
|
1290
|
+
* ``0`` — bare report for a recognised global-only consumer
|
|
1291
|
+
(bridge marker present), or a single global ``--check`` that passed.
|
|
1292
|
+
* ``1`` — a runnable health check requested via ``--check`` failed.
|
|
1293
|
+
* ``2`` — a requested ``--check`` cannot run (manifest-required check
|
|
1294
|
+
with no lockfile, or ``bridge-drift`` with neither lockfile nor
|
|
1295
|
+
bridge marker), or a bare report in an **uninitialised** repo
|
|
1296
|
+
(neither lockfile nor bridge marker) — preserves the spirit of the
|
|
1297
|
+
pre-existing "run init" signal while still printing a real report.
|
|
1298
|
+
"""
|
|
1299
|
+
checks = _run_checks_no_manifest(project_root, bridge_present, only=opts.check)
|
|
1300
|
+
fail_check = any(c["status"] == "fail" for c in checks)
|
|
1301
|
+
skipped_requested = opts.check is not None and any(
|
|
1302
|
+
c["id"] == opts.check and c["status"] == "skipped" for c in checks
|
|
1303
|
+
)
|
|
1304
|
+
|
|
1305
|
+
if opts.json:
|
|
1306
|
+
_emit_json(project_root, [], [], [], [], checks=checks, origin=origin)
|
|
1307
|
+
elif opts.check is None:
|
|
1308
|
+
print(f" 📍 project_root: {project_root} (origin: {origin})")
|
|
1309
|
+
if bridge_present:
|
|
1310
|
+
print(" ℹ️ global-only consumer: bridge marker present, no "
|
|
1311
|
+
"project lockfile (expected under ADR-020)")
|
|
1312
|
+
print(" project-manifest checks are skipped — they apply only "
|
|
1313
|
+
"to project-local distributed tools")
|
|
1314
|
+
else:
|
|
1315
|
+
print(" ⚠️ no project lockfile and no bridge marker at "
|
|
1316
|
+
f"{project_root}", file=sys.stderr)
|
|
1317
|
+
print(" run `agent-config init` (project install) or "
|
|
1318
|
+
"`agent-config refresh --project` (global-only consumer)",
|
|
1319
|
+
file=sys.stderr)
|
|
1320
|
+
_emit_checks_text(checks)
|
|
1321
|
+
else:
|
|
1322
|
+
_emit_checks_text(checks)
|
|
1323
|
+
|
|
1324
|
+
if opts.check is not None:
|
|
1325
|
+
if skipped_requested:
|
|
1326
|
+
return 2
|
|
1327
|
+
return 1 if fail_check else 0
|
|
1328
|
+
return 0 if bridge_present else 2
|
|
1329
|
+
|
|
1161
1330
|
|
|
1162
1331
|
def _emit_json(
|
|
1163
1332
|
project_root: Path,
|
|
@@ -1370,17 +1539,12 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
1370
1539
|
manifest_pth = installed_tools.manifest_path(project_root)
|
|
1371
1540
|
manifest = installed_tools.read_manifest(manifest_pth)
|
|
1372
1541
|
if manifest is None:
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
file=sys.stderr,
|
|
1380
|
-
)
|
|
1381
|
-
print(" run `./agent-config init` to create one",
|
|
1382
|
-
file=sys.stderr)
|
|
1383
|
-
return 2
|
|
1542
|
+
# No project lockfile. Under ADR-020 global-only this is a
|
|
1543
|
+
# legitimate state, not an error — run the lockfile-independent
|
|
1544
|
+
# checks and report consumer state instead of a hard bail. The
|
|
1545
|
+
# per-scope split + exit-code contract live in _run_no_manifest.
|
|
1546
|
+
bridge_present = (project_root / BRIDGE_MARKER_RELATIVE).is_file()
|
|
1547
|
+
return _run_no_manifest(opts, project_root, origin, bridge_present)
|
|
1384
1548
|
|
|
1385
1549
|
records, known = _collect_manifest_entries(project_root, manifest)
|
|
1386
1550
|
missing, modified, tag_drift = _classify(records)
|
|
@@ -18,7 +18,7 @@ import subprocess
|
|
|
18
18
|
import sys
|
|
19
19
|
from pathlib import Path
|
|
20
20
|
|
|
21
|
-
from scripts._lib.agent_settings import resolve_project_root
|
|
21
|
+
from scripts._lib.agent_settings import project_settings_path, resolve_project_root
|
|
22
22
|
|
|
23
23
|
PACKAGE_NAME = "@event4u/agent-config"
|
|
24
24
|
|
|
@@ -51,7 +51,7 @@ def _local_package_version() -> str:
|
|
|
51
51
|
|
|
52
52
|
def _pinned_version() -> str:
|
|
53
53
|
"""Return the ``agent_config_version`` pin from ``.agent-settings.yml``."""
|
|
54
|
-
settings = _project_root()
|
|
54
|
+
settings = project_settings_path(_project_root())
|
|
55
55
|
if not settings.exists():
|
|
56
56
|
return ""
|
|
57
57
|
try:
|
|
Binary file
|
|
Binary file
|
|
@@ -76,6 +76,45 @@ def _local_settings_path(project_root: Path) -> Path:
|
|
|
76
76
|
return project_root.joinpath(*LOCAL_PROJECT_SUBDIR, LOCAL_PROJECT_FILE)
|
|
77
77
|
|
|
78
78
|
|
|
79
|
+
def _canonical_settings_path(project_root: Path) -> Path:
|
|
80
|
+
"""Canonical project settings file: ``<root>/agents/settings/.agent-settings.yml``.
|
|
81
|
+
|
|
82
|
+
The project settings file lives in the project's settings layer
|
|
83
|
+
(``agents/settings/``, alongside ``contexts/`` and ``policies/`` and
|
|
84
|
+
the ``.agent-settings.local.yml`` override), NOT at the repo root.
|
|
85
|
+
The repo-root ``.agent-settings.yml`` is a legacy location read only
|
|
86
|
+
as a back-compat fallback (see :func:`project_settings_path`).
|
|
87
|
+
"""
|
|
88
|
+
return project_root.joinpath(*LOCAL_PROJECT_SUBDIR, DEFAULT_PROJECT_FILE)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def project_settings_path(project_root: Path) -> Path:
|
|
92
|
+
"""Resolve the project settings file for **reading**.
|
|
93
|
+
|
|
94
|
+
Returns the canonical ``agents/settings/.agent-settings.yml`` when it
|
|
95
|
+
exists; otherwise the legacy repo-root ``.agent-settings.yml`` when
|
|
96
|
+
that exists (back-compat for installs predating the relocation);
|
|
97
|
+
otherwise the canonical path (so the caller still names the right
|
|
98
|
+
target on a fresh repo). Existence-checked, never writes.
|
|
99
|
+
"""
|
|
100
|
+
canonical = _canonical_settings_path(project_root)
|
|
101
|
+
if canonical.exists():
|
|
102
|
+
return canonical
|
|
103
|
+
legacy = project_root / DEFAULT_PROJECT_FILE
|
|
104
|
+
if legacy.exists():
|
|
105
|
+
return legacy
|
|
106
|
+
return canonical
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def canonical_settings_write_path(project_root: Path) -> Path:
|
|
110
|
+
"""Always the canonical **write** target: ``agents/settings/.agent-settings.yml``.
|
|
111
|
+
|
|
112
|
+
Writers (install, sync, migrate) target this unconditionally; the
|
|
113
|
+
legacy root file is migrated into it, never written afresh.
|
|
114
|
+
"""
|
|
115
|
+
return _canonical_settings_path(project_root)
|
|
116
|
+
|
|
117
|
+
|
|
79
118
|
DEFAULT_TEAM_FILE = ".agent-project-settings.yml"
|
|
80
119
|
USER_GLOBAL_FILENAME = "agent-settings.yml"
|
|
81
120
|
|
|
@@ -431,12 +470,14 @@ def _resolve_cascade_paths(
|
|
|
431
470
|
"""
|
|
432
471
|
if cwd is None:
|
|
433
472
|
legacy = Path(project_path) if project_path else Path(DEFAULT_PROJECT_FILE)
|
|
434
|
-
return [legacy,
|
|
473
|
+
return [legacy, _canonical_settings_path(legacy.parent),
|
|
474
|
+
_local_settings_path(legacy.parent)]
|
|
435
475
|
|
|
436
476
|
root = find_project_root(cwd)
|
|
437
477
|
if root is None:
|
|
438
478
|
legacy = Path(project_path) if project_path else Path(DEFAULT_PROJECT_FILE)
|
|
439
|
-
return [legacy,
|
|
479
|
+
return [legacy, _canonical_settings_path(legacy.parent),
|
|
480
|
+
_local_settings_path(legacy.parent)]
|
|
440
481
|
|
|
441
482
|
cwd_resolved = cwd.resolve()
|
|
442
483
|
# Build the chain root → … → cwd (shallowest first, deepest last).
|
|
@@ -451,9 +492,15 @@ def _resolve_cascade_paths(
|
|
|
451
492
|
break
|
|
452
493
|
cursor = parent
|
|
453
494
|
chain.reverse()
|
|
454
|
-
#
|
|
455
|
-
#
|
|
456
|
-
|
|
495
|
+
# Legacy per-dir cascade root → cwd (repo-root .agent-settings.yml is the
|
|
496
|
+
# shallowest, back-compat), then the canonical project settings file under
|
|
497
|
+
# agents/settings/ (wins over the legacy root location), then the
|
|
498
|
+
# per-machine local override under agents/settings/ as the deepest (winning)
|
|
499
|
+
# layer.
|
|
500
|
+
return (
|
|
501
|
+
[d / DEFAULT_PROJECT_FILE for d in chain]
|
|
502
|
+
+ [_canonical_settings_path(root), _local_settings_path(root)]
|
|
503
|
+
)
|
|
457
504
|
|
|
458
505
|
|
|
459
506
|
def load_agent_settings(
|
|
@@ -30,6 +30,7 @@ from typing import Iterator
|
|
|
30
30
|
ROOT = Path(__file__).resolve().parents[2]
|
|
31
31
|
LEGACY_SRC = ROOT / ".agent-src.uncondensed"
|
|
32
32
|
PACKAGES = ROOT / "packages"
|
|
33
|
+
PACKAGE_CORE = PACKAGES / "core"
|
|
33
34
|
|
|
34
35
|
# Repo-relative POSIX path prefixes that anchor an artefact source tree.
|
|
35
36
|
# Order: legacy first (kept until the move lands), then packages/*. Each
|
|
@@ -155,3 +156,32 @@ def strip_source_prefix(rel: str) -> str | None:
|
|
|
155
156
|
def is_artefact_path(rel: str) -> bool:
|
|
156
157
|
"""``True`` if a repo-relative POSIX path sits under any source root."""
|
|
157
158
|
return strip_source_prefix(rel) is not None
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def resolve_package_core_path(relative_target: str) -> Path:
|
|
162
|
+
"""Return the canonical ``packages/core/<relative_target>`` path.
|
|
163
|
+
|
|
164
|
+
The single resolution point for every gate that enforces something
|
|
165
|
+
against a fixed ``packages/core/`` target. A future move of the
|
|
166
|
+
``packages/core/`` tree updates :data:`PACKAGE_CORE` here — one
|
|
167
|
+
resolver — instead of N hard-coded ``REPO_ROOT / "packages" / "core"``
|
|
168
|
+
constants scattered across gate scripts (the ``aab5755`` silent-no-op
|
|
169
|
+
class this eliminates).
|
|
170
|
+
|
|
171
|
+
Pure resolver: deterministic, **no filesystem I/O**. ``agent_src`` is
|
|
172
|
+
imported by scanners that must stay usable in the legacy-only and
|
|
173
|
+
pack-only layouts (see :func:`artefact_roots`), so this MUST NOT
|
|
174
|
+
assert existence at import or call time — a packages/core existence
|
|
175
|
+
check here would break those layouts. Callers that need existence
|
|
176
|
+
check it themselves; ``scripts/check_gate_paths.py`` is the single
|
|
177
|
+
gate that asserts the enforced targets resolve under ``packages/core/``.
|
|
178
|
+
|
|
179
|
+
Examples:
|
|
180
|
+
``resolve_package_core_path(".agent-src.uncondensed")``
|
|
181
|
+
→ ``<repo>/packages/core/.agent-src.uncondensed``
|
|
182
|
+
``resolve_package_core_path(".agent-src.uncondensed/commands")``
|
|
183
|
+
→ ``<repo>/packages/core/.agent-src.uncondensed/commands``
|
|
184
|
+
``resolve_package_core_path("")`` → ``<repo>/packages/core``
|
|
185
|
+
"""
|
|
186
|
+
rel = relative_target.replace("\\", "/").lstrip("/")
|
|
187
|
+
return PACKAGE_CORE / rel if rel else PACKAGE_CORE
|
|
@@ -28,6 +28,10 @@ import shutil
|
|
|
28
28
|
import sys
|
|
29
29
|
from dataclasses import dataclass, field
|
|
30
30
|
from pathlib import Path
|
|
31
|
+
try: # invocation-agnostic import (repo-root-on-path vs scripts-on-path)
|
|
32
|
+
from scripts._lib.agent_settings import project_settings_path
|
|
33
|
+
except ModuleNotFoundError: # pragma: no cover
|
|
34
|
+
from _lib.agent_settings import project_settings_path
|
|
31
35
|
from typing import Iterable
|
|
32
36
|
|
|
33
37
|
from scripts.ai_council.clients import CouncilResponse
|
|
@@ -37,7 +41,7 @@ REPO_ROOT = Path(__file__).resolve().parents[2]
|
|
|
37
41
|
SESSIONS_DIR = REPO_ROOT / "agents" / "runtime" / "council" / "sessions"
|
|
38
42
|
QUESTIONS_DIR = REPO_ROOT / "agents" / "runtime" / "council" / "questions"
|
|
39
43
|
RESPONSES_DIR = REPO_ROOT / "agents" / "runtime" / "council" / "responses"
|
|
40
|
-
SETTINGS_FILE = REPO_ROOT
|
|
44
|
+
SETTINGS_FILE = project_settings_path(REPO_ROOT)
|
|
41
45
|
|
|
42
46
|
# Default retention for all council artefacts (questions, responses,
|
|
43
47
|
# sessions). Overridden by `ai_council.session_retention_days`
|
|
@@ -37,12 +37,18 @@ from pathlib import Path
|
|
|
37
37
|
from typing import List
|
|
38
38
|
|
|
39
39
|
REPO_ROOT = Path(__file__).resolve().parent.parent
|
|
40
|
+
sys.path.insert(0, str(REPO_ROOT / "scripts"))
|
|
41
|
+
from _lib.agent_src import resolve_package_core_path # noqa: E402
|
|
42
|
+
|
|
40
43
|
# Pre-monorepo: REPO_ROOT/.agent-src.uncondensed/commands. Post-move (ADR-017)
|
|
41
44
|
# the core command surface lives under packages/core/.agent-src.uncondensed.
|
|
42
45
|
# Fall back to the legacy path only if the packages layout is absent.
|
|
43
|
-
_CORE_COMMANDS =
|
|
46
|
+
_CORE_COMMANDS = resolve_package_core_path(".agent-src.uncondensed/commands")
|
|
44
47
|
_LEGACY_COMMANDS = REPO_ROOT / ".agent-src.uncondensed" / "commands"
|
|
45
48
|
DEFAULT_ROOT = _CORE_COMMANDS if _CORE_COMMANDS.is_dir() else _LEGACY_COMMANDS
|
|
49
|
+
# Enforced packages/core target — read by scripts/check_gate_paths.py so a
|
|
50
|
+
# future move that desyncs this path fails CI instead of silently no-opping.
|
|
51
|
+
GATE_CORE_PATHS = (_CORE_COMMANDS,)
|
|
46
52
|
REPORT_DIR = REPO_ROOT / "agents" / "reports"
|
|
47
53
|
OUT_JSON = REPORT_DIR / "command-surface.json"
|
|
48
54
|
OUT_MD = REPORT_DIR / "command-surface.md"
|
|
@@ -35,6 +35,13 @@ from pathlib import Path
|
|
|
35
35
|
REPO_ROOT = Path(__file__).resolve().parent.parent
|
|
36
36
|
sys.path.insert(0, str(REPO_ROOT / "scripts"))
|
|
37
37
|
from _lib import token_count # noqa: E402
|
|
38
|
+
from _lib.agent_src import resolve_package_core_path # noqa: E402
|
|
39
|
+
|
|
40
|
+
_CORE_SRC = resolve_package_core_path(".agent-src.uncondensed")
|
|
41
|
+
# Enforced packages/core targets — the skills + commands dirs the
|
|
42
|
+
# description-catalog globs scan. Read by scripts/check_gate_paths.py so a
|
|
43
|
+
# future move that desyncs them fails CI instead of silently no-opping.
|
|
44
|
+
GATE_CORE_PATHS = (_CORE_SRC / "skills", _CORE_SRC / "commands")
|
|
38
45
|
|
|
39
46
|
try:
|
|
40
47
|
import yaml
|
|
@@ -111,10 +118,11 @@ def _catalog(glob_pat: str) -> dict:
|
|
|
111
118
|
|
|
112
119
|
def description_catalog() -> dict:
|
|
113
120
|
"""0B.4 — description-catalog cost (eager progressive-disclosure surface)."""
|
|
121
|
+
core_rel = _CORE_SRC.relative_to(REPO_ROOT).as_posix()
|
|
114
122
|
return {
|
|
115
123
|
"skills_projected": _catalog(".claude/skills/*/SKILL.md"),
|
|
116
|
-
"skills_core_source": _catalog("
|
|
117
|
-
"commands_core_source": _catalog("
|
|
124
|
+
"skills_core_source": _catalog(f"{core_rel}/skills/*/SKILL.md"),
|
|
125
|
+
"commands_core_source": _catalog(f"{core_rel}/commands/**/*.md"),
|
|
118
126
|
}
|
|
119
127
|
|
|
120
128
|
|