@event4u/agent-config 3.0.0 → 3.1.1
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/install-via-agent.md +129 -0
- package/.agent-src/commands/video/from-script.md +1 -1
- package/.agent-src/commands/video.md +1 -1
- package/.agent-src/contexts/execution/cheap-question-mechanics.md +81 -0
- package/.agent-src/rules/caveman-speak.md +2 -2
- package/.agent-src/rules/context-hygiene.md +36 -0
- package/.agent-src/rules/engineering-safety-floor.md +102 -0
- package/.agent-src/rules/finance-safety-floor.md +114 -0
- package/.agent-src/rules/git-history-discipline.md +1 -1
- package/.agent-src/rules/no-cheap-questions.md +34 -32
- package/.agent-src/rules/provider-lifecycle-discipline.md +4 -4
- package/.agent-src/rules/strategy-safety-floor.md +114 -0
- package/.agent-src/skills/agents-md-thin-root/SKILL.md +15 -9
- package/.agent-src/skills/async-python-patterns/SKILL.md +1 -1
- package/.agent-src/skills/project-analysis-node-express/SKILL.md +1 -1
- package/.agent-src/skills/readme-reviewer/SKILL.md +52 -3
- package/.agent-src/skills/readme-writing/SKILL.md +52 -4
- package/.agent-src/skills/readme-writing-package/SKILL.md +48 -5
- package/.agent-src/skills/systematic-debugging/SKILL.md +41 -0
- package/.agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/.agent-src/templates/hooks/pre-commit-frontmatter +66 -0
- package/.agent-src/templates/hooks/pre-commit-roadmap-progress +78 -39
- package/.agent-src/templates/scripts/work_engine/_lib/agent_settings.py +4 -1
- package/.agent-src/templates/scripts/work_engine/orchestration.py +25 -11
- package/.claude-plugin/marketplace.json +2 -1
- package/AGENTS.md +10 -8
- package/CHANGELOG.md +233 -123
- package/README.md +165 -553
- package/config/agent-settings.template.yml +0 -7
- package/config/discovery/packs.yml +20 -0
- package/config/discovery/unassigned-artefacts.yml +2 -0
- package/config/gitignore-block.txt +19 -3
- package/dist/cli/commands/uiServe.js +13 -4
- package/dist/cli/commands/uiServe.js.map +1 -1
- package/dist/cli/registry.js +2 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/discovery/deprecation-report.md +7 -0
- package/dist/discovery/discovery-manifest.json +2107 -1409
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +9 -9
- package/dist/discovery/orphan-report.md +10 -0
- package/dist/discovery/packs.json +1002 -0
- package/dist/discovery/trust-report.md +26 -0
- package/dist/discovery/workspaces.json +705 -0
- package/dist/mcp/registry-manifest.json +4 -4
- package/dist/router.json +1623 -0
- package/dist/server/app.js +11 -3
- package/dist/server/app.js.map +1 -1
- package/dist/server/io/atomicMultiWrite.js +3 -1
- package/dist/server/io/atomicMultiWrite.js.map +1 -1
- package/dist/server/io/yamlIO.js +22 -0
- package/dist/server/io/yamlIO.js.map +1 -1
- package/dist/server/routes/ping.js +8 -0
- package/dist/server/routes/ping.js.map +1 -1
- package/dist/server/routes/schema.js +2 -2
- package/dist/server/routes/schema.js.map +1 -1
- package/dist/server/routes/settings.js +104 -23
- package/dist/server/routes/settings.js.map +1 -1
- package/dist/server/routes/userMd.js +37 -27
- package/dist/server/routes/userMd.js.map +1 -1
- package/dist/server/routes/wizard.js +256 -20
- package/dist/server/routes/wizard.js.map +1 -1
- package/dist/server/schemas/settings.js +0 -1
- package/dist/server/schemas/settings.js.map +1 -1
- package/dist/server/token.js +10 -3
- package/dist/server/token.js.map +1 -1
- package/dist/server/writeRoot.js +28 -11
- package/dist/server/writeRoot.js.map +1 -1
- package/dist/server/writeRoot.test.js +22 -4
- package/dist/server/writeRoot.test.js.map +1 -1
- package/dist/shared/userMd/formAdapter.js +29 -51
- package/dist/shared/userMd/formAdapter.js.map +1 -1
- package/dist/shared/userMd/schema.js +32 -104
- package/dist/shared/userMd/schema.js.map +1 -1
- package/dist/shared/userMd/utils.js +64 -50
- package/dist/shared/userMd/utils.js.map +1 -1
- package/dist/ui/assets/index-D-DY1ywI.js +35 -0
- package/dist/ui/assets/index-D-DY1ywI.js.map +1 -0
- package/dist/ui/index.html +1 -1
- package/docs/adrs/router/0001-three-tier-routing.md +5 -5
- package/docs/adrs/smoke/0001-per-tier-smoke-scripts.md +1 -1
- package/docs/architecture.md +3 -3
- package/docs/archive/CHANGELOG-pre-3.1.0.md +167 -0
- package/docs/catalog.md +30 -26
- package/docs/contracts/CHANGELOG-conventions.md +1 -1
- package/docs/contracts/agent-user-schema.md +6 -9
- package/docs/contracts/consumer-bridge.md +79 -0
- package/docs/contracts/discovery-manifest.md +209 -0
- package/docs/contracts/discovery-manifest.schema.json +77 -4
- package/docs/contracts/explain-trace.schema.json +1 -1
- package/docs/contracts/file-ownership-matrix.json +197 -13
- package/docs/contracts/frontmatter-contract.md +140 -0
- package/docs/contracts/gui-wizard.md +223 -0
- package/docs/contracts/installer-agent-mode.md +137 -0
- package/docs/contracts/kernel-membership.md +1 -1
- package/docs/contracts/mcp-tool-inventory.md +9 -9
- package/docs/contracts/namespace.md +6 -6
- package/docs/contracts/provider-lifecycle.md +5 -5
- package/docs/contracts/rule-router.md +4 -4
- package/docs/contracts/settings-api.md +53 -6
- package/docs/contracts/smoke-contracts.md +3 -3
- package/docs/contracts/trust-and-safety.md +144 -0
- package/docs/customization.md +2 -2
- package/docs/decisions/ADR-007-agent-discovery-scopes.md +12 -0
- package/docs/decisions/ADR-013-discovery-frontmatter-contract.md +24 -0
- package/docs/decisions/ADR-015-discovery-manifest-contract.md +146 -0
- package/docs/decisions/ADR-016-installer-architecture.md +189 -0
- package/docs/decisions/ADR-017-monorepo-physical-layout.md +261 -0
- package/docs/decisions/ADR-018-trust-and-safety-layer.md +159 -0
- package/docs/decisions/ADR-019-router-json-dist-location.md +124 -0
- package/docs/decisions/ADR-020-global-only-consumer-scope.md +123 -0
- package/docs/decisions/ADR-021-deployment-shape.md +153 -0
- package/docs/decisions/INDEX.md +7 -0
- package/docs/deploy/connector-setup.md +129 -0
- package/docs/deploy/env-vars.md +70 -0
- package/docs/deploy/policy-cookbook.md +130 -0
- package/docs/deploy/quickstart.md +112 -0
- package/docs/distribution/public-install-smoke.md +68 -0
- package/docs/distribution/registries.md +55 -0
- package/docs/distribution/telemetry-privacy.md +128 -0
- package/docs/distribution/telemetry-schema.md +174 -0
- package/docs/featured-skills.md +95 -0
- package/docs/getting-started-by-role.md +19 -1
- package/docs/getting-started.md +2 -2
- package/docs/guidelines/agent-infra/installed-tools-manifest.md +11 -8
- package/docs/guidelines/docs/readme-size-and-splitting.md +53 -1
- package/docs/installation.md +27 -14
- package/docs/maintainers/dev-mode.md +105 -0
- package/docs/setup/per-ide/claude-desktop.md +3 -2
- package/docs/wizard.md +39 -4
- package/package.json +18 -1
- package/scripts/__pycache__/validate_frontmatter.cpython-312.pyc +0 -0
- package/scripts/_cli/cmd_doctor.py +150 -2
- package/scripts/_cli/cmd_explain.py +2 -1
- package/scripts/_cli/cmd_migrate_to_global.py +415 -0
- package/scripts/_cli/cmd_settings_migrate.py +146 -0
- package/scripts/_cli/explain_last/route.py +2 -1
- package/scripts/_dispatch.bash +36 -3
- 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 +4 -1
- package/scripts/_lib/agent_src.py +157 -0
- package/scripts/agent-config +17 -6
- package/scripts/audit_skill_descriptions.py +18 -6
- package/scripts/build_discovery_manifest.py +373 -17
- package/scripts/check_artefact_checksums.py +104 -0
- package/scripts/check_cluster_patterns.py +20 -4
- package/scripts/check_command_count_messaging.py +33 -14
- package/scripts/check_council_references.py +43 -4
- package/scripts/check_overlay_cascade_subdirs.py +7 -3
- package/scripts/check_references.py +5 -2
- package/scripts/check_reply_consistency.py +32 -9
- package/scripts/check_template_pin_drift.py +24 -7
- package/scripts/check_token_optimizer_freshness.py +18 -3
- package/scripts/compile_router.py +34 -2
- package/scripts/compress.py +162 -44
- package/scripts/config/presets.py +19 -1
- package/scripts/config/profiles.py +16 -1
- package/scripts/discovery_stats.py +70 -0
- package/scripts/expected_perms.json +47 -0
- package/scripts/generate_index.py +78 -46
- package/scripts/generate_ownership_matrix.py +98 -43
- package/scripts/generate_pack_manifests.py +183 -0
- package/scripts/install +18 -1
- package/scripts/install.py +934 -59
- package/scripts/install.sh +27 -9
- package/scripts/lint_agents_layout.py +93 -13
- package/scripts/lint_agents_md.py +1 -1
- package/scripts/lint_archived_skills.py +32 -16
- package/scripts/lint_bench_corpus.py +14 -2
- package/scripts/lint_command_tiers.py +15 -2
- package/scripts/lint_featured_skills.py +139 -0
- package/scripts/lint_framework_leakage.py +33 -6
- package/scripts/lint_global_paths.py +147 -0
- package/scripts/lint_orchestration_dsl.py +6 -3
- package/scripts/lint_pack_boundaries.py +147 -0
- package/scripts/lint_pack_first_win.py +103 -0
- package/scripts/lint_readme_jargon.py +131 -0
- package/scripts/lint_readme_size.py +33 -0
- package/scripts/lint_rule_interactions.py +23 -5
- package/scripts/lint_rule_tiers.py +12 -3
- package/scripts/lint_trust_coherence.py +212 -0
- package/scripts/measure_rule_budget.py +22 -4
- package/scripts/move_artefact.py +143 -0
- package/scripts/new_skill.py +148 -0
- package/scripts/plan_physical_move.py +353 -0
- package/scripts/refine_ticket_detect.py +30 -7
- package/scripts/release.py +22 -2
- package/scripts/schemas/command.schema.json +4 -0
- package/scripts/skill_linter.py +248 -118
- package/scripts/skill_trigger_eval.py +28 -8
- package/scripts/smoke/kernel.sh +1 -1
- package/scripts/smoke/router.sh +24 -5
- package/scripts/smoke/skills.sh +15 -7
- package/scripts/smoke_quickstart.py +11 -2
- package/scripts/snapshot_agent_outputs.py +144 -0
- package/scripts/update_counts.py +45 -17
- package/scripts/validate_decision_engine.py +9 -1
- package/scripts/validate_discovery_manifest.py +94 -0
- package/scripts/validate_frontmatter.py +39 -20
- package/scripts/verify_physical_move.py +185 -0
- package/templates/agent-user.md +0 -1
- package/templates/agent-user.yml +21 -0
- package/templates/minimal/agents-overrides-readme.md +46 -0
- package/templates/minimal/overrides-gitkeep +2 -0
- package/dist/ui/assets/index-BTRcKDlB.js +0 -39
- package/dist/ui/assets/index-BTRcKDlB.js.map +0 -1
- package/templates/minimal/agents-gitkeep +0 -2
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Maintainer Dev Mode (`AGENT_CONFIG_DEV_MODE=1`)
|
|
2
|
+
|
|
3
|
+
**Audience.** Maintainers of `@event4u/agent-config` working **inside**
|
|
4
|
+
the package repo. Consumers never see this flag; consumer installs
|
|
5
|
+
land in `~/.event4u/agent-config/` per [ADR-020](../decisions/ADR-020-global-only-consumer-scope.md).
|
|
6
|
+
|
|
7
|
+
**Status.** Forward-looking — the gate ships in Phase 3 of the
|
|
8
|
+
`road-to-global-only-install` roadmap. This document is the
|
|
9
|
+
canonical reference once Phase 3 lands.
|
|
10
|
+
|
|
11
|
+
## Why the flag exists
|
|
12
|
+
|
|
13
|
+
Phase 3 of `road-to-global-only-install` flips `SCOPE_SUPPORT` so that
|
|
14
|
+
**every** consumer scope on `scripts/install.py` is global. The
|
|
15
|
+
package repo itself is structurally identical to a consumer repo
|
|
16
|
+
(same `.augment/`, `.claude/`, `.cursor/` projection layout) which
|
|
17
|
+
means maintainer dev-installs would otherwise be blocked by the same
|
|
18
|
+
gate.
|
|
19
|
+
|
|
20
|
+
`AGENT_CONFIG_DEV_MODE=1` is the explicit, audit-visible opt-out.
|
|
21
|
+
With the flag set, the installer:
|
|
22
|
+
|
|
23
|
+
1. Allows project-scope writes back into the repo tree (so a
|
|
24
|
+
maintainer can run `task dev:install-global` and iterate on the
|
|
25
|
+
working copy).
|
|
26
|
+
2. **Skips** writing `agents/.event4u-bridge.yml` into the package
|
|
27
|
+
repo (per `consumer-bridge § Writer contract`). The repo is the
|
|
28
|
+
source, not a consumer of itself.
|
|
29
|
+
3. Treats `~/.event4u/agent-config/` as a peer install — touches are
|
|
30
|
+
limited to the working-copy projection.
|
|
31
|
+
|
|
32
|
+
Without the flag, `scripts/install.py` refuses to write anywhere
|
|
33
|
+
under the repo tree and points at this document.
|
|
34
|
+
|
|
35
|
+
## When to set it
|
|
36
|
+
|
|
37
|
+
Set the flag for these workflows, and **only** these:
|
|
38
|
+
|
|
39
|
+
- `task dev:install-global` — refresh the user-scope projection from the working tree.
|
|
40
|
+
- `task dev:install:gui` — iterate the unified Setup-Wizard / Installer-GUI before merge.
|
|
41
|
+
- `task dev:setup` / `task dev:setup:dry-run` — exercise the onboarding wizard.
|
|
42
|
+
- `task release` rehearsal — verify the published shape matches the dev shape.
|
|
43
|
+
|
|
44
|
+
Do **not** set it for:
|
|
45
|
+
|
|
46
|
+
- Consumer project work (the flag is undefined behaviour outside this repo).
|
|
47
|
+
- CI runs on the package itself (CI uses the flag transparently via the dev tasks above; bare runs MUST NOT export it).
|
|
48
|
+
- Production maintainer machines that also consume the package as a user (set per-shell, not in `~/.zshrc`).
|
|
49
|
+
|
|
50
|
+
## How to set it
|
|
51
|
+
|
|
52
|
+
Per-command (preferred):
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
AGENT_CONFIG_DEV_MODE=1 task dev:install-global
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Per-shell session:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
export AGENT_CONFIG_DEV_MODE=1
|
|
62
|
+
task dev:install:gui
|
|
63
|
+
unset AGENT_CONFIG_DEV_MODE
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The `unset` discipline matters: a stale `=1` in your shell environment
|
|
67
|
+
is the most common way a project-scope write sneaks into a consumer
|
|
68
|
+
repo. Future work (`agent-config doctor`, Phase 5.4) will warn when
|
|
69
|
+
the flag is set outside the package repo.
|
|
70
|
+
|
|
71
|
+
## Safety properties
|
|
72
|
+
|
|
73
|
+
- **Audit-visible.** Every install run logs whether the flag was set
|
|
74
|
+
at the top of the transaction log.
|
|
75
|
+
- **No silent fallback.** If `scripts/install.py` detects the
|
|
76
|
+
package repo signature (presence of `.agent-src.uncompressed/` plus
|
|
77
|
+
`dist/router.json`) and the flag is **not** set, the install
|
|
78
|
+
refuses with a one-line error pointing here.
|
|
79
|
+
- **Not for consumers.** Setting the flag in a consumer project is
|
|
80
|
+
defined as undefined behaviour. The installer will not actively
|
|
81
|
+
refuse (because it cannot distinguish a misconfigured shell from a
|
|
82
|
+
legitimate vendored maintainer install), but it will print a single
|
|
83
|
+
warning line on every run.
|
|
84
|
+
|
|
85
|
+
## Interaction with the bridge marker
|
|
86
|
+
|
|
87
|
+
Per [`consumer-bridge`](../contracts/consumer-bridge.md), the bridge
|
|
88
|
+
marker is the in-repo pointer to the global root. Under
|
|
89
|
+
`AGENT_CONFIG_DEV_MODE=1`:
|
|
90
|
+
|
|
91
|
+
- The marker is **not** written into the package repo — the repo's
|
|
92
|
+
`agents/` directory is the project surface, not a consumer surface.
|
|
93
|
+
- A pre-existing marker in the package repo is treated as stale and
|
|
94
|
+
removed on the next dev install (with an audit log line).
|
|
95
|
+
- Consumer adapters reading the marker from inside the package repo
|
|
96
|
+
during local development should expand `global_root` against the
|
|
97
|
+
current user's `$HOME` per the reader contract — same as in a
|
|
98
|
+
consumer repo.
|
|
99
|
+
|
|
100
|
+
## References
|
|
101
|
+
|
|
102
|
+
- [ADR-020](../decisions/ADR-020-global-only-consumer-scope.md) — the global-only decision.
|
|
103
|
+
- [`consumer-bridge`](../contracts/consumer-bridge.md) — bridge marker schema.
|
|
104
|
+
- [`road-to-global-only-install`](../../agents/roadmaps/road-to-global-only-install.md) — Phase 3 SCOPE_SUPPORT flip + Phase 5 migration order.
|
|
105
|
+
- [`taskfiles/dev.yml`](../../taskfiles/dev.yml) — `dev:install-global`, `dev:install:gui`, `dev:setup` task entries.
|
|
@@ -9,8 +9,9 @@ server inside Claude Desktop. macOS / Windows / Linux. ~10 minutes.
|
|
|
9
9
|
> ZIP per skill under
|
|
10
10
|
> `~/.event4u/agent-config/claude-desktop/bundles/` so you can drag /
|
|
11
11
|
> drop them into the Customize panel. The v1 npm / composer install
|
|
12
|
-
> scheme is retired; the
|
|
13
|
-
>
|
|
12
|
+
> scheme is retired; the current global-only scheme follows ADR-007 +
|
|
13
|
+
> [ADR-020](../../decisions/ADR-020-global-only-consumer-scope.md) and
|
|
14
|
+
> writes through `~/.event4u/agent-config/installed.lock` (legacy
|
|
14
15
|
> `~/.config/agent-config/installed.lock` read as fallback).
|
|
15
16
|
|
|
16
17
|
## Prerequisites
|
package/docs/wizard.md
CHANGED
|
@@ -83,10 +83,30 @@ for the full failure-mode matrix.
|
|
|
83
83
|
|
|
84
84
|
## Auto-launch from `npx … init`
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
`scripts/install.py` acts as a supervisor at the tail of a successful
|
|
87
|
+
install: it evaluates a gate (TTY, `CI`, `--no-ui`,
|
|
88
|
+
`AGENT_CONFIG_NO_UI`), then spawns `node <pkg>/.../cli.js gui
|
|
89
|
+
--project-root <root>` and waits for the child's
|
|
90
|
+
`WIZARD_READY url=<http://127.0.0.1:PORT/>` handshake on stdout
|
|
91
|
+
(strict regex
|
|
92
|
+
`^WIZARD_READY url=(http://(?:127\.0\.0\.1|localhost):\d+/)\r?$`).
|
|
93
|
+
On match, the parent prints a banner and blocks on the child until
|
|
94
|
+
the user closes the tab or sends Ctrl-C.
|
|
95
|
+
|
|
96
|
+
Progressive readiness backoff: `10s → 20s → 40s → 80s` (cumulative
|
|
97
|
+
budget 150s) — generous enough for cold-start `node_modules`
|
|
98
|
+
extraction on slow disks. On timeout the parent kills the child,
|
|
99
|
+
prints the last 20 stderr lines, and exits 0 — the install itself
|
|
100
|
+
is unaffected.
|
|
101
|
+
|
|
102
|
+
Suppress the auto-launch with `--no-ui`, `AGENT_CONFIG_NO_UI=1`, or
|
|
103
|
+
by running in CI (`CI=1`). Preview the gate verdict without
|
|
104
|
+
installing anything via `python3 scripts/install.py --dry-run`,
|
|
105
|
+
which prints a plan summary and exits 0 with zero filesystem
|
|
106
|
+
writes.
|
|
107
|
+
|
|
108
|
+
Skill: [`agents/roadmaps/archive/wizard-install-py-wiring.md`](../agents/roadmaps/archive/wizard-install-py-wiring.md)
|
|
109
|
+
(archived after ship).
|
|
90
110
|
|
|
91
111
|
## Accessibility
|
|
92
112
|
|
|
@@ -99,6 +119,21 @@ Tracked under
|
|
|
99
119
|
receives `tabIndex={-1}` and `.focus()` so screen readers
|
|
100
120
|
announce the new heading.
|
|
101
121
|
|
|
122
|
+
## Headless / CI / no-browser
|
|
123
|
+
|
|
124
|
+
When the wizard cannot or should not open — CI runs, SSH sessions
|
|
125
|
+
without X forwarding, headless servers, automated provisioning —
|
|
126
|
+
take the flag path instead. Three equivalent ways to suppress the
|
|
127
|
+
GUI: pass `--no-ui` to `npx … init`, export `AGENT_CONFIG_NO_UI=1`
|
|
128
|
+
in the environment, or run inside a `CI=1` context (auto-detected).
|
|
129
|
+
With the GUI suppressed, pass profile + pack on the command line —
|
|
130
|
+
`npx -y @event4u/agent-config init --no-ui --profile=developer
|
|
131
|
+
--pack=engineering-base` — or hand-edit `.agent-settings.yml`
|
|
132
|
+
directly. Preview the gate verdict and the planned writes with
|
|
133
|
+
`python3 scripts/install.py --dry-run` (zero filesystem writes,
|
|
134
|
+
exits 0). Settings can still be hand-edited at any time; the GUI
|
|
135
|
+
is opt-in, not required.
|
|
136
|
+
|
|
102
137
|
## Disabling the GUI
|
|
103
138
|
|
|
104
139
|
Set `AGENT_CONFIG_NO_UI=1` in the environment to skip every
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@event4u/agent-config",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.1",
|
|
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,
|
|
@@ -13,6 +13,21 @@
|
|
|
13
13
|
"url": "https://github.com/event4u-app/agent-config/issues"
|
|
14
14
|
},
|
|
15
15
|
"homepage": "https://github.com/event4u-app/agent-config#readme",
|
|
16
|
+
"keywords": [
|
|
17
|
+
"ai-agent",
|
|
18
|
+
"mcp",
|
|
19
|
+
"claude-code",
|
|
20
|
+
"cursor",
|
|
21
|
+
"windsurf",
|
|
22
|
+
"copilot",
|
|
23
|
+
"llm",
|
|
24
|
+
"agent-governance",
|
|
25
|
+
"ai-video",
|
|
26
|
+
"skills",
|
|
27
|
+
"prompt-engineering",
|
|
28
|
+
"typescript",
|
|
29
|
+
"python"
|
|
30
|
+
],
|
|
16
31
|
"files": [
|
|
17
32
|
".agent-src/",
|
|
18
33
|
".augment-plugin/",
|
|
@@ -60,6 +75,8 @@
|
|
|
60
75
|
}
|
|
61
76
|
},
|
|
62
77
|
"devDependencies": {
|
|
78
|
+
"@inquirer/prompts": "^7.10.1",
|
|
79
|
+
"@playwright/test": "^1.60.0",
|
|
63
80
|
"@preact/preset-vite": "^2.10.5",
|
|
64
81
|
"@testing-library/preact": "^3.2.4",
|
|
65
82
|
"@types/js-yaml": "^4.0.9",
|
|
Binary file
|
|
@@ -17,14 +17,21 @@ Drift categories (manifest ↔ filesystem):
|
|
|
17
17
|
(P5.2). Hand-edited tags or accidental cross-package writes show up
|
|
18
18
|
here; files without frontmatter are skipped (P5.1 contract).
|
|
19
19
|
|
|
20
|
-
Health checks (
|
|
20
|
+
Health checks (see :data:`CHECK_IDS`):
|
|
21
21
|
scope · manifest-integrity · lockfile-freshness · bridge-drift ·
|
|
22
22
|
mcp-mode · mcp-beta-readiness · offline-readiness · python-runtime ·
|
|
23
|
-
unsupported-combos
|
|
23
|
+
tier-usage-readiness · council-cli · unsupported-combos ·
|
|
24
|
+
wizard-state.
|
|
24
25
|
Each emits a structured ``{id, status, message, remedy}`` record with
|
|
25
26
|
``status`` ∈ ``ok`` / ``warn`` / ``fail`` (rendered ``✅`` / ``⚠️`` /
|
|
26
27
|
``❌``). ``--check <id>`` runs a single check.
|
|
27
28
|
|
|
29
|
+
Repair affordances: ``--repair wizard-state`` resets a malformed or
|
|
30
|
+
orphaned ``state/wizard-state.json`` under the user-global root (the
|
|
31
|
+
file the unified Setup-Wizard uses for resume continuity). Used as the
|
|
32
|
+
recovery path when ``1.9``'s npm downgrade is not viable
|
|
33
|
+
(road-to-global-only-install § 1.10 / A6).
|
|
34
|
+
|
|
28
35
|
Exit codes: ``0`` (clean) · ``1`` (drift or any ``fail`` check) · ``2``
|
|
29
36
|
(error such as "manifest missing"). Both human and ``--json`` output
|
|
30
37
|
emit the drift category lists and the structured checks array. Every
|
|
@@ -443,8 +450,16 @@ CHECK_IDS = (
|
|
|
443
450
|
"tier-usage-readiness",
|
|
444
451
|
"council-cli",
|
|
445
452
|
"unsupported-combos",
|
|
453
|
+
"wizard-state",
|
|
446
454
|
)
|
|
447
455
|
|
|
456
|
+
#: Repair targets that ``--repair <id>`` accepts. Each id maps to a
|
|
457
|
+
#: function in :func:`_run_repair` that resets the named artefact and
|
|
458
|
+
#: returns an exit code. Additive set: introduce by adding a new id
|
|
459
|
+
#: here, a runner inside :func:`_run_repair`, and (optionally) a
|
|
460
|
+
#: matching health check above.
|
|
461
|
+
REPAIR_IDS = ("wizard-state",)
|
|
462
|
+
|
|
448
463
|
#: Six gates that govern the MCP `experimental → beta` promotion. The
|
|
449
464
|
#: artefact path under each gate id mirrors `tests/test_mcp_beta_gates.py`
|
|
450
465
|
#: and the contract in `docs/contracts/mcp-beta-criteria.md`.
|
|
@@ -983,6 +998,88 @@ def _check_unsupported_combos(manifest: dict[str, Any]) -> dict[str, Any]:
|
|
|
983
998
|
}
|
|
984
999
|
|
|
985
1000
|
|
|
1001
|
+
def _wizard_state_path() -> Path:
|
|
1002
|
+
"""Return the on-disk location of the unified Setup-Wizard state file.
|
|
1003
|
+
|
|
1004
|
+
Mirrors ``STATE_REL`` in :mod:`src/server/routes/wizard.ts` — the
|
|
1005
|
+
server writes ``<writeRoot>/state/wizard-state.json``. Under the
|
|
1006
|
+
global-only install scope (ADR-020) ``writeRoot`` resolves to
|
|
1007
|
+
:func:`user_global_paths.event4u_root` (typically
|
|
1008
|
+
``~/.event4u/agent-config/``); the ``EVENT4U_CONFIG_HOME`` override
|
|
1009
|
+
is honoured implicitly so tests stay hermetic.
|
|
1010
|
+
"""
|
|
1011
|
+
from scripts._lib.user_global_paths import event4u_root
|
|
1012
|
+
return event4u_root() / "state" / "wizard-state.json"
|
|
1013
|
+
|
|
1014
|
+
|
|
1015
|
+
def _check_wizard_state() -> dict[str, Any]:
|
|
1016
|
+
"""Health-check the resumable Setup-Wizard state file.
|
|
1017
|
+
|
|
1018
|
+
Returns ``ok`` when the file is absent (no active session) or when
|
|
1019
|
+
its JSON shape matches the contract from
|
|
1020
|
+
:mod:`src/server/routes/wizard.ts` (``step: int``, ``partial: dict``,
|
|
1021
|
+
optional ``totalSteps: int``, ``startedAt: str | null``).
|
|
1022
|
+
Returns ``fail`` when the file exists but is unreadable, not valid
|
|
1023
|
+
JSON, or violates the shape — ``--repair wizard-state`` resets it.
|
|
1024
|
+
"""
|
|
1025
|
+
state_pth = _wizard_state_path()
|
|
1026
|
+
if not state_pth.exists():
|
|
1027
|
+
return {
|
|
1028
|
+
"id": "wizard-state", "status": "ok",
|
|
1029
|
+
"message": "no active wizard session",
|
|
1030
|
+
"remedy": "",
|
|
1031
|
+
}
|
|
1032
|
+
try:
|
|
1033
|
+
raw = state_pth.read_text(encoding="utf-8")
|
|
1034
|
+
except OSError as exc:
|
|
1035
|
+
return {
|
|
1036
|
+
"id": "wizard-state", "status": "fail",
|
|
1037
|
+
"message": f"unreadable wizard-state at {state_pth}: {exc}",
|
|
1038
|
+
"remedy": "agent-config doctor --repair wizard-state",
|
|
1039
|
+
}
|
|
1040
|
+
try:
|
|
1041
|
+
data = json.loads(raw)
|
|
1042
|
+
except json.JSONDecodeError as exc:
|
|
1043
|
+
return {
|
|
1044
|
+
"id": "wizard-state", "status": "fail",
|
|
1045
|
+
"message": f"malformed JSON in wizard-state ({exc.msg} at line {exc.lineno})",
|
|
1046
|
+
"remedy": "agent-config doctor --repair wizard-state",
|
|
1047
|
+
}
|
|
1048
|
+
if not isinstance(data, dict):
|
|
1049
|
+
return {
|
|
1050
|
+
"id": "wizard-state", "status": "fail",
|
|
1051
|
+
"message": f"wizard-state root is {type(data).__name__}, expected object",
|
|
1052
|
+
"remedy": "agent-config doctor --repair wizard-state",
|
|
1053
|
+
}
|
|
1054
|
+
step = data.get("step")
|
|
1055
|
+
partial = data.get("partial", {})
|
|
1056
|
+
if not isinstance(step, int) or step < 0:
|
|
1057
|
+
return {
|
|
1058
|
+
"id": "wizard-state", "status": "fail",
|
|
1059
|
+
"message": f"wizard-state.step is {step!r}, expected non-negative integer",
|
|
1060
|
+
"remedy": "agent-config doctor --repair wizard-state",
|
|
1061
|
+
}
|
|
1062
|
+
if not isinstance(partial, dict):
|
|
1063
|
+
return {
|
|
1064
|
+
"id": "wizard-state", "status": "fail",
|
|
1065
|
+
"message": f"wizard-state.partial is {type(partial).__name__}, expected object",
|
|
1066
|
+
"remedy": "agent-config doctor --repair wizard-state",
|
|
1067
|
+
}
|
|
1068
|
+
total = data.get("totalSteps")
|
|
1069
|
+
if total is not None and (not isinstance(total, int) or total < 1):
|
|
1070
|
+
return {
|
|
1071
|
+
"id": "wizard-state", "status": "fail",
|
|
1072
|
+
"message": f"wizard-state.totalSteps is {total!r}, expected positive integer or omitted",
|
|
1073
|
+
"remedy": "agent-config doctor --repair wizard-state",
|
|
1074
|
+
}
|
|
1075
|
+
suffix = f" of {total}" if isinstance(total, int) else ""
|
|
1076
|
+
return {
|
|
1077
|
+
"id": "wizard-state", "status": "ok",
|
|
1078
|
+
"message": f"resumable wizard session at step {step + 1}{suffix}",
|
|
1079
|
+
"remedy": "",
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
|
|
986
1083
|
def _run_checks(
|
|
987
1084
|
project_root: Path,
|
|
988
1085
|
manifest: dict[str, Any],
|
|
@@ -1008,6 +1105,7 @@ def _run_checks(
|
|
|
1008
1105
|
"tier-usage-readiness": lambda: _check_tier_usage_readiness(project_root),
|
|
1009
1106
|
"council-cli": lambda: _check_council_cli(project_root),
|
|
1010
1107
|
"unsupported-combos": lambda: _check_unsupported_combos(manifest),
|
|
1108
|
+
"wizard-state": _check_wizard_state,
|
|
1011
1109
|
}
|
|
1012
1110
|
out: list[dict[str, Any]] = []
|
|
1013
1111
|
for cid in CHECK_IDS:
|
|
@@ -1115,6 +1213,14 @@ def _parse(argv: list[str]) -> argparse.Namespace:
|
|
|
1115
1213
|
"layer chain, wrapper, and install-mode; short-circuits "
|
|
1116
1214
|
"the drift report"),
|
|
1117
1215
|
)
|
|
1216
|
+
parser.add_argument(
|
|
1217
|
+
"--repair", default=None, metavar="ID",
|
|
1218
|
+
choices=list(REPAIR_IDS),
|
|
1219
|
+
help=("reset a recoverable artefact and exit "
|
|
1220
|
+
f"({' · '.join(REPAIR_IDS)}); short-circuits the drift "
|
|
1221
|
+
"report. Idempotent — absent files report 'nothing to "
|
|
1222
|
+
"repair' and exit 0."),
|
|
1223
|
+
)
|
|
1118
1224
|
return parser.parse_args(argv)
|
|
1119
1225
|
|
|
1120
1226
|
|
|
@@ -1165,8 +1271,50 @@ def _run_context(opts: argparse.Namespace) -> int:
|
|
|
1165
1271
|
return 0
|
|
1166
1272
|
|
|
1167
1273
|
|
|
1274
|
+
def _run_repair(opts: argparse.Namespace) -> int:
|
|
1275
|
+
"""Handle ``--repair <id>``: reset the named artefact, no drift report.
|
|
1276
|
+
|
|
1277
|
+
Currently the only target is ``wizard-state`` — unlinks the
|
|
1278
|
+
resumable session file so the next ``agent-config setup`` boots
|
|
1279
|
+
from step 1. Absent files are a no-op (idempotent re-run).
|
|
1280
|
+
"""
|
|
1281
|
+
target = opts.repair
|
|
1282
|
+
if target == "wizard-state":
|
|
1283
|
+
state_pth = _wizard_state_path()
|
|
1284
|
+
payload = {
|
|
1285
|
+
"id": "wizard-state",
|
|
1286
|
+
"path": str(state_pth),
|
|
1287
|
+
"action": "remove" if state_pth.exists() else "noop",
|
|
1288
|
+
}
|
|
1289
|
+
if state_pth.exists():
|
|
1290
|
+
try:
|
|
1291
|
+
state_pth.unlink()
|
|
1292
|
+
except OSError as exc:
|
|
1293
|
+
payload["action"] = "error"
|
|
1294
|
+
payload["error"] = str(exc)
|
|
1295
|
+
if opts.json:
|
|
1296
|
+
print(json.dumps(payload, indent=2))
|
|
1297
|
+
else:
|
|
1298
|
+
print(f"❌ doctor: could not remove {state_pth}: {exc}",
|
|
1299
|
+
file=sys.stderr)
|
|
1300
|
+
return 2
|
|
1301
|
+
if opts.json:
|
|
1302
|
+
print(json.dumps(payload, indent=2))
|
|
1303
|
+
else:
|
|
1304
|
+
if payload["action"] == "remove":
|
|
1305
|
+
print(f"✅ doctor: reset wizard-state ({state_pth})")
|
|
1306
|
+
else:
|
|
1307
|
+
print(f"✅ doctor: nothing to repair (no wizard-state at {state_pth})")
|
|
1308
|
+
return 0
|
|
1309
|
+
# argparse `choices=` already constrains target; defensive default.
|
|
1310
|
+
print(f"❌ doctor: unknown repair target {target!r}", file=sys.stderr)
|
|
1311
|
+
return 2
|
|
1312
|
+
|
|
1313
|
+
|
|
1168
1314
|
def main(argv: list[str] | None = None) -> int:
|
|
1169
1315
|
opts = _parse(list(argv) if argv is not None else sys.argv[1:])
|
|
1316
|
+
if opts.repair is not None:
|
|
1317
|
+
return _run_repair(opts)
|
|
1170
1318
|
if opts.trace_root:
|
|
1171
1319
|
return _run_trace_root(opts)
|
|
1172
1320
|
if opts.context:
|
|
@@ -42,6 +42,7 @@ from scripts._lib.agent_settings import (
|
|
|
42
42
|
from scripts.config import presets, profiles
|
|
43
43
|
|
|
44
44
|
ROUTER_FILENAME = "router.json"
|
|
45
|
+
ROUTER_RELATIVE = Path("dist") / ROUTER_FILENAME
|
|
45
46
|
|
|
46
47
|
|
|
47
48
|
def _resolve_root(arg: str | None) -> tuple[Path, str]:
|
|
@@ -60,7 +61,7 @@ def _load_user_settings(project_root: Path) -> dict[str, Any]:
|
|
|
60
61
|
|
|
61
62
|
|
|
62
63
|
def _load_router(project_root: Path) -> dict[str, Any]:
|
|
63
|
-
path = project_root /
|
|
64
|
+
path = project_root / ROUTER_RELATIVE
|
|
64
65
|
if not path.exists():
|
|
65
66
|
return {}
|
|
66
67
|
try:
|