@amsterdamdatalabs/enact-extensions 0.1.10 → 0.1.24
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/README.md +11 -12
- package/dist/create/claude.d.ts.map +1 -1
- package/dist/create/claude.js +6 -2
- package/dist/create/claude.js.map +1 -1
- package/dist/create/cursor.d.ts.map +1 -1
- package/dist/create/cursor.js +6 -2
- package/dist/create/cursor.js.map +1 -1
- package/dist/create/enact.js +1 -1
- package/dist/create/enact.js.map +1 -1
- package/dist/create/index.d.ts +4 -3
- package/dist/create/index.d.ts.map +1 -1
- package/dist/create/index.js +9 -2
- package/dist/create/index.js.map +1 -1
- package/dist/index.d.ts +9 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/install.d.ts +5 -0
- package/dist/install.d.ts.map +1 -1
- package/dist/install.js +91 -11
- package/dist/install.js.map +1 -1
- package/dist/internal/agents.d.ts +25 -1
- package/dist/internal/agents.d.ts.map +1 -1
- package/dist/internal/agents.js +81 -4
- package/dist/internal/agents.js.map +1 -1
- package/dist/internal/claude.d.ts +49 -0
- package/dist/internal/claude.d.ts.map +1 -1
- package/dist/internal/claude.js +166 -1
- package/dist/internal/claude.js.map +1 -1
- package/dist/internal/platform.d.ts +11 -1
- package/dist/internal/platform.d.ts.map +1 -1
- package/dist/internal/platform.js +58 -1
- package/dist/internal/platform.js.map +1 -1
- package/dist/internal/types.d.ts +2 -1
- package/dist/internal/types.d.ts.map +1 -1
- package/dist/principles.d.ts +28 -0
- package/dist/principles.d.ts.map +1 -0
- package/dist/principles.js +159 -0
- package/dist/principles.js.map +1 -0
- package/extensions/dev-state/.agents/plugin.json +2 -1
- package/extensions/enact-context/.agents/plugin.json +2 -1
- package/extensions/enact-context/hooks/hooks.json +0 -10
- package/extensions/enact-context/skills/enact-context/SKILL.md +14 -12
- package/extensions/enact-context/skills/enact-context/scripts/install.sh +7 -7
- package/extensions/enact-core/.agents/plugin.json +2 -1
- package/extensions/enact-core/OPERATING-PRINCIPLES.md +7 -0
- package/extensions/enact-core/hooks/hooks.json +12 -0
- package/extensions/enact-evolve/.agents/plugin.json +47 -0
- package/extensions/enact-evolve/agents/evolve-session-analyst.toml +37 -0
- package/extensions/enact-evolve/skills/session-analysis/SKILL.md +98 -0
- package/extensions/enact-evolve/skills/session-analysis/scripts/run-evolve-analysis.sh +343 -0
- package/extensions/enact-factory/.agents/plugin.json +2 -1
- package/extensions/enact-factory/agents/architect.toml +9 -5
- package/extensions/enact-factory/agents/code-reviewer.toml +9 -5
- package/extensions/enact-factory/agents/critic.toml +9 -5
- package/extensions/enact-factory/agents/executor.toml +4 -1
- package/extensions/enact-factory/agents/explore.toml +4 -1
- package/extensions/enact-factory/agents/planner.toml +4 -1
- package/extensions/enact-factory/agents/verifier.toml +9 -5
- package/extensions/enact-factory/skills/advisor/SKILL.md +82 -0
- package/extensions/enact-factory/skills/ai-slop-cleaner/SKILL.md +6 -1
- package/extensions/enact-factory/skills/autonomous-runner/SKILL.md +347 -0
- package/extensions/enact-factory/skills/azdo-ci-strategy/SKILL.md +62 -15
- package/extensions/enact-factory/skills/committee/SKILL.md +80 -0
- package/extensions/enact-factory/skills/deep-interview/SKILL.md +9 -13
- package/extensions/enact-factory/skills/drive-loop/SKILL.md +161 -31
- package/extensions/enact-factory/skills/drive-loop/references/contract-schema.md +26 -6
- package/extensions/enact-factory/skills/handoff/SKILL.md +72 -0
- package/extensions/enact-factory/skills/hyperplan/SKILL.md +11 -3
- package/extensions/enact-factory/skills/looplan/SKILL.md +34 -17
- package/extensions/enact-factory/skills/plan/SKILL.md +40 -8
- package/extensions/enact-factory/skills/remove-deadcode/SKILL.md +6 -1
- package/extensions/enact-factory/skills/research/SKILL.md +14 -4
- package/extensions/enact-factory/skills/review/SKILL.md +21 -2
- package/extensions/enact-factory/skills/security-research/SKILL.md +5 -2
- package/extensions/enact-factory/skills/tdd/SKILL.md +7 -1
- package/extensions/enact-factory/skills/testing-strategy/SKILL.md +5 -0
- package/extensions/enact-factory/skills/trace/SKILL.md +5 -0
- package/extensions/enact-factory/skills/ultraqa/SKILL.md +21 -15
- package/extensions/enact-factory/skills/work-with-workitem/SKILL.md +5 -0
- package/extensions/enact-factory/skills/workitem-triage/SKILL.md +5 -0
- package/extensions/enact-loop/.agents/plugin.json +5 -4
- package/extensions/enact-loop/scripts/validate.mjs +123 -0
- package/extensions/enact-loop/skills/enact-loop/SKILL.md +189 -30
- package/extensions/enact-wiki/.agents/plugin.json +2 -1
- package/extensions/net-revenue-management/.agents/plugin.json +2 -1
- package/extensions/plugin-dev/.agents/plugin.json +2 -1
- package/extensions/plugin-dev/skills/start/SKILL.md +3 -3
- package/package.json +1 -1
- package/scripts/check-hooks.mjs +5 -5
- package/scripts/check-principles.mjs +19 -4
- package/scripts/enact-extensions.mjs +237 -90
- package/scripts/lib/hooks.mjs +61 -217
- package/scripts/lib/migrate-artifacts.mjs +144 -0
- package/scripts/lib/principles.mjs +109 -0
- package/scripts/lib/provision-mcp.mjs +1 -1
- package/scripts/lib/run-install.mjs +72 -2
- package/scripts/lib/run-prune.mjs +23 -2
- package/scripts/lib/run-sync.mjs +4 -1
- package/scripts/postinstall.mjs +6 -6
- package/scripts/setup-enact-context.sh +20 -15
- package/spec/codex.json +5 -0
- package/spec/enact.json +3 -3
- package/spec/enact.md +1 -4
- package/spec/index.json +1 -1
- package/extensions/enact-operator/.agents/plugin.json +0 -56
- package/extensions/enact-operator/.app.json +0 -3
- package/extensions/enact-operator/.mcp.json +0 -10
- package/extensions/enact-operator/_taxonomy.md +0 -86
- package/extensions/enact-operator/agents/README.md +0 -5
- package/extensions/enact-operator/agents/architect.toml +0 -25
- package/extensions/enact-operator/agents/code-reviewer.toml +0 -24
- package/extensions/enact-operator/agents/critic.toml +0 -30
- package/extensions/enact-operator/agents/executor.toml +0 -24
- package/extensions/enact-operator/agents/explore.toml +0 -23
- package/extensions/enact-operator/agents/planner.toml +0 -24
- package/extensions/enact-operator/agents/verifier.toml +0 -24
- package/extensions/enact-operator/docs/skill-variants.md +0 -44
- package/extensions/enact-operator/hooks/hooks.json +0 -91
- package/extensions/enact-operator/skills/ai-slop-cleaner/SKILL.md +0 -50
- package/extensions/enact-operator/skills/analyze/SKILL.md +0 -91
- package/extensions/enact-operator/skills/ask/SKILL.md +0 -47
- package/extensions/enact-operator/skills/autopilot/SKILL.md +0 -170
- package/extensions/enact-operator/skills/autoresearch-goal/SKILL.md +0 -79
- package/extensions/enact-operator/skills/cancel/SKILL.md +0 -99
- package/extensions/enact-operator/skills/configure-notifications/SKILL.md +0 -77
- package/extensions/enact-operator/skills/deep-interview/SKILL.md +0 -80
- package/extensions/enact-operator/skills/doctor/SKILL.md +0 -48
- package/extensions/enact-operator/skills/hud/SKILL.md +0 -49
- package/extensions/enact-operator/skills/hyperplan/SKILL.md +0 -47
- package/extensions/enact-operator/skills/plan/SKILL.md +0 -78
- package/extensions/enact-operator/skills/ralph/SKILL.md +0 -201
- package/extensions/enact-operator/skills/ralph/gemini.md +0 -18
- package/extensions/enact-operator/skills/ralplan/SKILL.md +0 -151
- package/extensions/enact-operator/skills/remove-deadcode/SKILL.md +0 -45
- package/extensions/enact-operator/skills/research/SKILL.md +0 -74
- package/extensions/enact-operator/skills/review/SKILL.md +0 -58
- package/extensions/enact-operator/skills/security-research/SKILL.md +0 -54
- package/extensions/enact-operator/skills/setup/SKILL.md +0 -91
- package/extensions/enact-operator/skills/setup/scripts/install.sh +0 -50
- package/extensions/enact-operator/skills/skill/SKILL.md +0 -82
- package/extensions/enact-operator/skills/tdd/SKILL.md +0 -59
- package/extensions/enact-operator/skills/team/SKILL.md +0 -199
- package/extensions/enact-operator/skills/trace/SKILL.md +0 -41
- package/extensions/enact-operator/skills/ultragoal/SKILL.md +0 -99
- package/extensions/enact-operator/skills/ultraqa/SKILL.md +0 -113
- package/extensions/enact-operator/skills/ultrawork/SKILL.md +0 -145
- package/extensions/enact-operator/skills/ultrawork/planner.md +0 -28
- package/extensions/enact-operator/skills/wiki/SKILL.md +0 -41
- package/extensions/enact-operator/skills/work-with-workitem/SKILL.md +0 -51
- /package/extensions/{enact-operator → enact-evolve}/assets/icon.png +0 -0
- /package/extensions/{enact-operator → enact-evolve}/assets/logo.png +0 -0
|
@@ -5,6 +5,11 @@ description: "Plan-first loop execution wrapper: write a durable plan, enter the
|
|
|
5
5
|
|
|
6
6
|
# Looplan
|
|
7
7
|
|
|
8
|
+
> **Storage is GLOBAL — never write to a repo-local `.enact` dir.** Resolve the project's global dir:
|
|
9
|
+
> 1. `ROOT="$(git rev-parse --show-toplevel)"`
|
|
10
|
+
> 2. In `~/.enact/workspaces.json` → `workspaces`, find the entry whose `.root` == `$ROOT`; its object key is `<name>-<id>` (e.g. `enact-evolve-a38d1e`).
|
|
11
|
+
> 3. Factory planning artifacts go under `~/.enact/factory/projects/<key>/…`; loop runtime state under `~/.enact/loop/projects/<key>/…`.
|
|
12
|
+
|
|
8
13
|
## Purpose
|
|
9
14
|
|
|
10
15
|
Use `$looplan` when the work needs a reviewable execution plan before the loop starts. Looplan gates
|
|
@@ -34,16 +39,22 @@ intent → $plan (write plan + verification map) → user review → $loop start
|
|
|
34
39
|
|
|
35
40
|
Each transition is explicit. Never advance to the loop before the plan artifact exists and is reviewed.
|
|
36
41
|
|
|
42
|
+
## Timestamped Artifact Naming
|
|
43
|
+
|
|
44
|
+
All durable factory markdown artifacts use `YYMMDDHH-<slug>.md` where `YYMMDDHH=$(date +%y%m%d%H)`.
|
|
45
|
+
Use the **same** prefix for the plan and verification map written in one planning pass.
|
|
46
|
+
**Never overwrite** a prior plan file — each looplan run writes fresh timestamped artifacts.
|
|
47
|
+
|
|
37
48
|
## Workflow
|
|
38
49
|
|
|
39
50
|
### Phase 1 — Plan
|
|
40
51
|
|
|
41
|
-
1. Read current artifacts and inspect the repo for brownfield context.
|
|
42
|
-
2. Write the plan to
|
|
52
|
+
1. Read current artifacts and inspect the repo for brownfield context (latest timestamped files per `$plan` resolution rules).
|
|
53
|
+
2. Write the plan to `~/.enact/factory/projects/<key>/plans/<YYMMDDHH>-<phase>.md` following `$plan` conventions:
|
|
43
54
|
- Named files per slice
|
|
44
55
|
- Explicit verification per slice
|
|
45
56
|
- Exit conditions stated
|
|
46
|
-
3. Write the verification map to
|
|
57
|
+
3. Write the verification map to `~/.enact/factory/projects/<key>/plans/<YYMMDDHH>-<phase>-verification.md`.
|
|
47
58
|
4. Present the plan for review. Do not advance until it is approved.
|
|
48
59
|
|
|
49
60
|
### Phase 2 — Execute
|
|
@@ -54,8 +65,12 @@ Each transition is explicit. Never advance to the loop before the plan artifact
|
|
|
54
65
|
```
|
|
55
66
|
6. Confirm the loop is running: `loop_status`
|
|
56
67
|
7. Execute each plan slice.
|
|
57
|
-
- Mechanical stages:
|
|
58
|
-
|
|
68
|
+
- Mechanical stages: `loop_grade({ stageId })` — the engine runs the stage `command` in the
|
|
69
|
+
loop root and records pass/fail from exit code. Do **not** run the command separately and
|
|
70
|
+
self-report `status` or `evidence` (rejected by the runtime).
|
|
71
|
+
- Judgment stages: `loop_grader_dispatch({ stageId })` → independent grader reviews → driver
|
|
72
|
+
relays GO/NO-GO via `loop_grader_verdict` with the minted `continuationId` (default:
|
|
73
|
+
`captureSource: "relayed"`). Grader child sessions have **no closure authority**.
|
|
59
74
|
8. If blocked: `loop_block` with reason, resolve, then `loop_advance` back to `running`.
|
|
60
75
|
|
|
61
76
|
### Phase 3 — Verify and Complete
|
|
@@ -65,7 +80,7 @@ Each transition is explicit. Never advance to the loop before the plan artifact
|
|
|
65
80
|
loop_advance toPhase=verifying
|
|
66
81
|
```
|
|
67
82
|
10. Run `$review` against the completed work and plan artifacts.
|
|
68
|
-
11.
|
|
83
|
+
11. Write the closure summary via `enact-loop summary write` (CLI stamps fingerprint header into a new `YYMMDDHH-loop-summary.md`), then complete the loop:
|
|
69
84
|
```
|
|
70
85
|
loop_complete summary="<one-line summary>"
|
|
71
86
|
```
|
|
@@ -74,30 +89,32 @@ Each transition is explicit. Never advance to the loop before the plan artifact
|
|
|
74
89
|
## State Contract
|
|
75
90
|
|
|
76
91
|
Reads:
|
|
77
|
-
-
|
|
78
|
-
-
|
|
92
|
+
- `~/.enact/factory/projects/<key>/plans/*` (latest timestamped plan + verification map from Phase 1)
|
|
93
|
+
- `~/.enact/loop/projects/<key>/state/loop.json` (loop state)
|
|
94
|
+
- `~/.enact/loop/projects/<key>/state/summary-current.json` (pointer to current closure summary)
|
|
79
95
|
|
|
80
96
|
Writes:
|
|
81
|
-
-
|
|
82
|
-
-
|
|
83
|
-
- Loop state via MCP
|
|
97
|
+
- `~/.enact/factory/projects/<key>/plans/<YYMMDDHH>-<phase>.md`
|
|
98
|
+
- `~/.enact/factory/projects/<key>/plans/<YYMMDDHH>-<phase>-verification.md`
|
|
99
|
+
- Loop state and closure summary via MCP/CLI only (never raw file edits)
|
|
84
100
|
|
|
85
101
|
## MCP Tools
|
|
86
102
|
|
|
87
103
|
- `loop_start` — start a new loop with goal and stages
|
|
88
104
|
- `loop_status` — read current loop state
|
|
89
105
|
- `loop_advance` — transition to a new phase
|
|
90
|
-
- `loop_grade` —
|
|
91
|
-
- `loop_grader_dispatch` — dispatch an independent grader for a judgment stage
|
|
92
|
-
- `loop_grader_verdict` — record
|
|
106
|
+
- `loop_grade` — run a mechanical stage `command` (`stageId` + optional `timeoutMs`); engine-derived pass/fail only
|
|
107
|
+
- `loop_grader_dispatch` — mint `continuationId` and dispatch an independent grader for a judgment stage
|
|
108
|
+
- `loop_grader_verdict` — record GO/NO-GO (driver-relayed default; direct only from registered grader child with valid `continuationId`)
|
|
93
109
|
- `loop_block` — mark blocked with a reason
|
|
94
110
|
- `loop_complete` — close the loop with a summary
|
|
95
111
|
- `loop_abort` — abort with a reason
|
|
96
112
|
|
|
97
113
|
## Final Check
|
|
98
114
|
|
|
99
|
-
- Plan artifact exists at
|
|
100
|
-
-
|
|
101
|
-
- Judgment stages have valid independent grader verdicts
|
|
115
|
+
- Plan artifact exists at `~/.enact/factory/projects/<key>/plans/<YYMMDDHH>-<phase>.md` before loop was started
|
|
116
|
+
- Mechanical stages passed via engine-run `loop_grade` (command exit code), not caller-supplied status
|
|
117
|
+
- Judgment stages have valid independent grader verdicts (minted `continuationId`, driver-relayed or direct with provenance)
|
|
102
118
|
- `$review` verdict is approved
|
|
119
|
+
- `enact-loop summary write` produced a current timestamped closure summary before `loop_complete`
|
|
103
120
|
- `loop_status` shows phase as `completed`
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: plan
|
|
3
|
-
description: "Execution-plan mode that turns intent into small, verifiable slices backed by durable
|
|
3
|
+
description: "Execution-plan mode that turns intent into small, verifiable slices backed by durable global loop artifacts."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Plan
|
|
7
7
|
|
|
8
|
+
> **Storage is GLOBAL — never write to a repo-local `.enact` dir.** Resolve the project's global dir:
|
|
9
|
+
> 1. `ROOT="$(git rev-parse --show-toplevel)"`
|
|
10
|
+
> 2. In `~/.enact/workspaces.json` → `workspaces`, find the entry whose `.root` == `$ROOT`; its object key is `<name>-<id>` (e.g. `enact-evolve-a38d1e`).
|
|
11
|
+
> 3. Factory planning artifacts go under `~/.enact/factory/projects/<key>/…`.
|
|
12
|
+
|
|
8
13
|
## Purpose
|
|
9
14
|
|
|
10
15
|
Use `$plan` to create execution-ready slices. The output is not a strategy memo. It is the
|
|
@@ -29,6 +34,32 @@ prompt-quality plan that downstream execution can follow without improvising cor
|
|
|
29
34
|
- every slice must fit in one focused context window
|
|
30
35
|
- every slice must have explicit verification
|
|
31
36
|
- prefer a small number of high-quality slices over a long TODO dump
|
|
37
|
+
- **never overwrite an existing plan artifact in place** — each planning pass writes a new timestamped file
|
|
38
|
+
|
|
39
|
+
## Timestamped Artifact Naming
|
|
40
|
+
|
|
41
|
+
All durable factory markdown artifacts use `YYMMDDHH-<slug>.md` where `YYMMDDHH=$(date +%y%m%d%H)` (8 digits, hour granularity).
|
|
42
|
+
|
|
43
|
+
Examples:
|
|
44
|
+
- `plans/26062203-foundations-hardening.md`
|
|
45
|
+
- `plans/26062203-foundations-hardening-verification.md`
|
|
46
|
+
- `plans/26062203-foundations-hardening-requirements.md`
|
|
47
|
+
- `plans/26062203-foundations-brownfield-map.md`
|
|
48
|
+
- `research/26062203-auth-token-research.md`
|
|
49
|
+
|
|
50
|
+
Use the **same** `YYMMDDHH` prefix for a plan and its verification map written in the same pass.
|
|
51
|
+
|
|
52
|
+
## Active Artifact Resolution
|
|
53
|
+
|
|
54
|
+
When reading (not writing), resolve the latest matching artifact:
|
|
55
|
+
|
|
56
|
+
1. Prefer the path recorded in the current session/run if one was emitted.
|
|
57
|
+
2. Else pick the lexicographically greatest `YYMMDDHH` among files matching the semantic suffix:
|
|
58
|
+
- requirements: `*-requirements.md`
|
|
59
|
+
- plan: `*-{phase}.md` (exclude `-verification` and `-requirements`)
|
|
60
|
+
- verification: `*-{phase}-verification.md`
|
|
61
|
+
- brownfield: `*-brownfield-map.md`
|
|
62
|
+
3. If no timestamped file exists, fall back to legacy unprefixed names only for migration reads — never write new unprefixed files.
|
|
32
63
|
|
|
33
64
|
## Plan Anatomy
|
|
34
65
|
|
|
@@ -42,9 +73,10 @@ Each slice should answer:
|
|
|
42
73
|
|
|
43
74
|
## Workflow
|
|
44
75
|
|
|
45
|
-
1. Read current intent artifacts:
|
|
46
|
-
-
|
|
47
|
-
-
|
|
76
|
+
1. Read current intent artifacts (latest by rules above):
|
|
77
|
+
- `~/.enact/factory/projects/<key>/plans/*-requirements.md`
|
|
78
|
+
- `~/.enact/factory/projects/<key>/plans/*-brownfield-map.md`
|
|
79
|
+
- any `hyperplan/<sessionId>/` debate bundle from `$hyperplan` when present
|
|
48
80
|
2. Derive the must-haves from the goal backward:
|
|
49
81
|
- what must be true when this is done?
|
|
50
82
|
- what artifacts and connections are required for those truths?
|
|
@@ -52,7 +84,7 @@ Each slice should answer:
|
|
|
52
84
|
- interface or contracts first
|
|
53
85
|
- implementation second
|
|
54
86
|
- verification and wiring last
|
|
55
|
-
4. Write
|
|
87
|
+
4. Write **new** timestamped artifacts (do not edit prior plan files):
|
|
56
88
|
- active phase plan
|
|
57
89
|
- verification map
|
|
58
90
|
- loop contract stages (mechanical vs. judgment per slice)
|
|
@@ -66,6 +98,6 @@ Each slice should answer:
|
|
|
66
98
|
|
|
67
99
|
## Deliverables
|
|
68
100
|
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
101
|
+
- `~/.enact/factory/projects/<key>/plans/<YYMMDDHH>-<phase>.md`
|
|
102
|
+
- `~/.enact/factory/projects/<key>/plans/<YYMMDDHH>-<phase>-verification.md`
|
|
103
|
+
- write **new** `~/.enact/factory/projects/<key>/plans/<YYMMDDHH>-<topic>-brownfield-map.md` when the brownfield map changes (append-only; never edit a prior brownfield file in place)
|
|
@@ -5,6 +5,11 @@ description: "LSP-verified symbol deletion with entry-point guards and candidate
|
|
|
5
5
|
|
|
6
6
|
# Remove Deadcode
|
|
7
7
|
|
|
8
|
+
> **Storage is GLOBAL — never write to a repo-local `.enact` dir.** Resolve the project's global dir:
|
|
9
|
+
> 1. `ROOT="$(git rev-parse --show-toplevel)"`
|
|
10
|
+
> 2. In `~/.enact/workspaces.json` → `workspaces`, find the entry whose `.root` == `$ROOT`; its object key is `<name>-<id>` (e.g. `enact-evolve-a38d1e`).
|
|
11
|
+
> 3. Loop artifacts go under `~/.enact/factory/projects/<key>/…`.
|
|
12
|
+
|
|
8
13
|
## Purpose
|
|
9
14
|
|
|
10
15
|
Use `$remove-deadcode` to remove provably unused code symbols without damaging runtime entry points.
|
|
@@ -12,7 +17,7 @@ Use `$remove-deadcode` to remove provably unused code symbols without damaging r
|
|
|
12
17
|
## Preconditions
|
|
13
18
|
|
|
14
19
|
- collect candidate symbols before any deletion
|
|
15
|
-
- load optional entry-point guard list from
|
|
20
|
+
- load optional entry-point guard list from `~/.enact/factory/projects/<key>/remove-deadcode/entry-points.txt`
|
|
16
21
|
|
|
17
22
|
## Required Safety Contract
|
|
18
23
|
|
|
@@ -5,6 +5,15 @@ description: "Evidence-first research mode for current patterns, implementation
|
|
|
5
5
|
|
|
6
6
|
# Research
|
|
7
7
|
|
|
8
|
+
> **Storage is GLOBAL — never write to a repo-local `.enact` dir.** Resolve the project's global dir:
|
|
9
|
+
> 1. `ROOT="$(git rev-parse --show-toplevel)"`
|
|
10
|
+
> 2. In `~/.enact/workspaces.json` → `workspaces`, find the entry whose `.root` == `$ROOT`; its object key is `<name>-<id>` (e.g. `enact-evolve-a38d1e`).
|
|
11
|
+
> 3. Factory planning artifacts go under `~/.enact/factory/projects/<key>/…`.
|
|
12
|
+
|
|
13
|
+
## Active Artifact Resolution
|
|
14
|
+
|
|
15
|
+
When reading prior research, pick the lexicographically greatest `YYMMDDHH` among files in `research/<YYMMDDHH>-*.md`. Never write unprefixed research filenames.
|
|
16
|
+
|
|
8
17
|
## Purpose
|
|
9
18
|
|
|
10
19
|
Use `$research` when the correct implementation depends on facts you do not yet have, either from the repo or from current external sources.
|
|
@@ -24,7 +33,7 @@ Use `$research` when the correct implementation depends on facts you do not yet
|
|
|
24
33
|
- external truth
|
|
25
34
|
- assumptions
|
|
26
35
|
3. Gather only the evidence needed to decide.
|
|
27
|
-
4. Write the result into
|
|
36
|
+
4. Write the result into `~/.enact/factory/projects/<key>/research/<YYMMDDHH>-<kebab-title>.md` (e.g. `research/26062101-auth-token-research.md`). Resolve `<key>` from `~/.enact/workspaces.json` as described in the Storage banner above; get the timestamp prefix via `date +%y%m%d%H`.
|
|
28
37
|
5. Update any linked loop contract or task state if the research is part of an active execution lane.
|
|
29
38
|
|
|
30
39
|
## Parallel Sweep
|
|
@@ -43,8 +52,9 @@ Anti-stop rule: do not stop at the first result. Continue each lane until at lea
|
|
|
43
52
|
- If research output is being used to support closure on a live loop, rely
|
|
44
53
|
on the real loop proof surfaces rather than treating research notes as
|
|
45
54
|
equivalent to stage evidence:
|
|
46
|
-
- `loop_grade`
|
|
47
|
-
|
|
55
|
+
- `loop_grade({ stageId })` — engine runs the mechanical stage `command`; caller-supplied
|
|
56
|
+
`status`/`evidence` are rejected
|
|
57
|
+
- `loop_grader_dispatch` + driver-relayed `loop_grader_verdict` (minted `continuationId`) for judgment stages
|
|
48
58
|
- `loop_contract_parity` (for contract-parity checks)
|
|
49
59
|
|
|
50
60
|
## Deliverables
|
|
@@ -70,4 +80,4 @@ Anti-stop rule: do not stop at the first result. Continue each lane until at lea
|
|
|
70
80
|
|
|
71
81
|
## Activation
|
|
72
82
|
|
|
73
|
-
Invoke with `$research` or `$enact-loop:research`. This skill is a stateless evidence pass — no durable workflow state is started automatically. If enact-loop MCP tools are available,
|
|
83
|
+
Invoke with `$research` or `$enact-loop:research`. This skill is a stateless evidence pass — no durable workflow state is started automatically. If enact-loop MCP tools are available, use them for stage recording that flows from research output — mechanical via `loop_grade({ stageId })`, judgment via dispatched grader + relayed verdict — not by citing research markdown as pass evidence.
|
|
@@ -5,6 +5,11 @@ description: "Findings-first pre-landing review against code, plan completion, v
|
|
|
5
5
|
|
|
6
6
|
# Review
|
|
7
7
|
|
|
8
|
+
> **Storage is GLOBAL — never write to a repo-local `.enact` dir.** Resolve the project's global dir:
|
|
9
|
+
> 1. `ROOT="$(git rev-parse --show-toplevel)"`
|
|
10
|
+
> 2. In `~/.enact/workspaces.json` → `workspaces`, find the entry whose `.root` == `$ROOT`; its object key is `<name>-<id>` (e.g. `enact-evolve-a38d1e`).
|
|
11
|
+
> 3. Factory artifacts go under `~/.enact/factory/projects/<key>/…`; loop runtime under `~/.enact/loop/projects/<key>/…`.
|
|
12
|
+
|
|
8
13
|
## Purpose
|
|
9
14
|
|
|
10
15
|
Use `$review` to answer one question: is this actually ready to land? Review is not a summary pass.
|
|
@@ -17,16 +22,29 @@ It is a bug, regression, coverage, and state-integrity pass.
|
|
|
17
22
|
- check the code, the tests, the plan, and the loop artifacts
|
|
18
23
|
- if the current context authored the change, prefer a separate reviewer role for approval
|
|
19
24
|
|
|
25
|
+
## Active Artifact Resolution
|
|
26
|
+
|
|
27
|
+
Resolve the plan and verification map to review:
|
|
28
|
+
|
|
29
|
+
1. Prefer paths recorded in the active loop/run session when available.
|
|
30
|
+
2. Else under `~/.enact/factory/projects/<key>/plans/`, pick the lexicographically greatest `YYMMDDHH` among:
|
|
31
|
+
- plan files matching `*-{phase}.md` (exclude `-verification` and `-requirements`)
|
|
32
|
+
- verification files matching `*-{phase}-verification.md` with the **same** `YYMMDDHH` prefix as the plan when possible
|
|
33
|
+
3. Fall back to legacy unprefixed plan names only for reads during migration — never treat them as the write contract.
|
|
34
|
+
|
|
35
|
+
For loop closure, read the current summary via `enact-loop summary show` or `summary-current.json` under `~/.enact/loop/projects/<key>/state/`.
|
|
36
|
+
|
|
20
37
|
## Review Order
|
|
21
38
|
|
|
22
39
|
1. Read the changed code.
|
|
23
|
-
2. Read the active plan and verification map.
|
|
40
|
+
2. Read the active plan and verification map (resolved per rules above).
|
|
24
41
|
3. Check what was supposed to happen vs what actually landed.
|
|
25
42
|
4. Verify:
|
|
26
43
|
- tests and typechecks
|
|
27
44
|
- docs drift
|
|
28
|
-
-
|
|
45
|
+
- `~/.enact/factory/projects/<key>/` state drift
|
|
29
46
|
- judgment stages have valid independent grader verdicts
|
|
47
|
+
- closure summary exists and fingerprint is current when the loop is closure-ready
|
|
30
48
|
5. Produce a verdict:
|
|
31
49
|
- approved
|
|
32
50
|
- changes requested
|
|
@@ -39,6 +57,7 @@ It is a bug, regression, coverage, and state-integrity pass.
|
|
|
39
57
|
- stale docs or setup instructions
|
|
40
58
|
- task marked done but still pending review evidence
|
|
41
59
|
- judgment stages with self-reported verdicts (flag as grader-independence-missing)
|
|
60
|
+
- closure-ready loop without a current timestamped summary artifact
|
|
42
61
|
|
|
43
62
|
## Output Standard
|
|
44
63
|
|
|
@@ -5,7 +5,10 @@ description: "Multi-agent security research with hunter/PoC split and optional c
|
|
|
5
5
|
|
|
6
6
|
# Security Research
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
> **Storage is GLOBAL — never write to a repo-local `.enact` dir.** Resolve the project's global dir:
|
|
9
|
+
> 1. `ROOT="$(git rev-parse --show-toplevel)"`
|
|
10
|
+
> 2. In `~/.enact/workspaces.json` → `workspaces`, find the entry whose `.root` == `$ROOT`; its object key is `<name>-<id>`.
|
|
11
|
+
> 3. Security findings go under `~/.enact/factory/projects/<key>/security/…`.
|
|
9
12
|
|
|
10
13
|
Use `$security-research` to run a focused vulnerability hunt, produce ranked findings, and optionally create Azure DevOps Bug work items for critical issues.
|
|
11
14
|
|
|
@@ -28,7 +31,7 @@ Use `$security-research` to run a focused vulnerability hunt, produce ranked fin
|
|
|
28
31
|
1. Launch hunters to identify and classify potential vulnerabilities.
|
|
29
32
|
2. Launch PoC engineers on top-ranked findings to validate exploitability.
|
|
30
33
|
3. Merge outputs into a single findings report.
|
|
31
|
-
4. Write report to
|
|
34
|
+
4. Write report to `~/.enact/factory/projects/<key>/security/<sessionId>/<YYMMDDHH>-findings.md` (e.g. `security/abc123/26062101-findings.md`). Resolve `<key>` from `~/.enact/workspaces.json`; get the timestamp prefix via `date +%y%m%d%H`.
|
|
32
35
|
5. Rank findings in the report by CVSS v4 severity.
|
|
33
36
|
6. For each finding with CVSS v4 `>= 9.0`, if `autoCreateBugs=true`, call `factory_workitem_sync_once` to create a `Bug` work item.
|
|
34
37
|
7. If `autoCreateBugs=false`, skip all bug auto-creation calls.
|
|
@@ -5,6 +5,11 @@ description: "Red-green-refactor mode for behavior with clear inputs, outputs, a
|
|
|
5
5
|
|
|
6
6
|
# TDD
|
|
7
7
|
|
|
8
|
+
> **Storage is GLOBAL — never write to a repo-local `.enact` dir.** Resolve the project's global dir:
|
|
9
|
+
> 1. `ROOT="$(git rev-parse --show-toplevel)"`
|
|
10
|
+
> 2. In `~/.enact/workspaces.json` → `workspaces`, find the entry whose `.root` == `$ROOT`; its object key is `<name>-<id>`.
|
|
11
|
+
> 3. Factory planning artifacts go under `~/.enact/factory/projects/<key>/…`.
|
|
12
|
+
|
|
8
13
|
## Purpose
|
|
9
14
|
|
|
10
15
|
Use `$tdd` when behavior can be specified before implementation. TDD is for design pressure and
|
|
@@ -46,7 +51,8 @@ No production code without a failing test first.
|
|
|
46
51
|
- one behavior per cycle
|
|
47
52
|
- do not batch multiple features into one red-green pass
|
|
48
53
|
- prefer regression tests for changed behavior
|
|
49
|
-
- record the verify command in the plan
|
|
54
|
+
- record the verify command in the current timestamped plan artifact (for example
|
|
55
|
+
`~/.enact/factory/projects/<key>/plans/<YYMMDDHH>-<phase>.md`) or in linked task notes
|
|
50
56
|
|
|
51
57
|
## Output Standard
|
|
52
58
|
|
|
@@ -8,6 +8,11 @@ description: >
|
|
|
8
8
|
|
|
9
9
|
# testing-strategy
|
|
10
10
|
|
|
11
|
+
> **Storage is GLOBAL — never write to a repo-local `.enact` dir.** Resolve the project's global dir:
|
|
12
|
+
> 1. `ROOT="$(git rev-parse --show-toplevel)"`
|
|
13
|
+
> 2. In `~/.enact/workspaces.json` → `workspaces`, find the entry whose `.root` == `$ROOT`; its object key is `<name>-<id>`.
|
|
14
|
+
> 3. Factory planning artifacts go under `~/.enact/factory/projects/<key>/…`. Local `_evidence/` remains a repo-local proof surface for Mode 1 only.
|
|
15
|
+
|
|
11
16
|
## Purpose
|
|
12
17
|
|
|
13
18
|
Enforce a consistent, lightweight approach across the three testing modes used
|
|
@@ -5,6 +5,11 @@ description: "Execution-path mapping for entry points, data flow, side effects,
|
|
|
5
5
|
|
|
6
6
|
# Trace
|
|
7
7
|
|
|
8
|
+
> **Storage is GLOBAL — never write to a repo-local `.enact` dir.** Resolve the project's global dir:
|
|
9
|
+
> 1. `ROOT="$(git rev-parse --show-toplevel)"`
|
|
10
|
+
> 2. In `~/.enact/workspaces.json` → `workspaces`, find the entry whose `.root` == `$ROOT`; its object key is `<name>-<id>`.
|
|
11
|
+
> 3. Factory planning artifacts go under `~/.enact/factory/projects/<key>/…`.
|
|
12
|
+
|
|
8
13
|
## Purpose
|
|
9
14
|
|
|
10
15
|
Use `$trace` before a risky edit or review when you need to know what code path actually runs, what
|
|
@@ -6,6 +6,11 @@ lane: true
|
|
|
6
6
|
|
|
7
7
|
# UltraQA
|
|
8
8
|
|
|
9
|
+
> **Storage is GLOBAL — never write to a repo-local `.enact` dir.** Resolve the project's global dir:
|
|
10
|
+
> 1. `ROOT="$(git rev-parse --show-toplevel)"`
|
|
11
|
+
> 2. In `~/.enact/workspaces.json` → `workspaces`, find the entry whose `.root` == `$ROOT`; its object key is `<name>-<id>` (e.g. `enact-evolve-a38d1e`).
|
|
12
|
+
> 3. Factory artifacts go under `~/.enact/factory/projects/<key>/…`; loop runtime state lives under `~/.enact/loop/projects/<key>/…`.
|
|
13
|
+
|
|
9
14
|
## Purpose
|
|
10
15
|
Combines `$loop` (durable contract-runner with closure gates) with an explicit set of QA gates. Each gate must pass before the loop advances. The cycle is: implement a fix, run all gates, advance only when green, repeat until every gate is clean in a single run.
|
|
11
16
|
|
|
@@ -16,7 +21,7 @@ Combines `$loop` (durable contract-runner with closure gates) with an explicit s
|
|
|
16
21
|
|
|
17
22
|
## Execution Policy
|
|
18
23
|
|
|
19
|
-
- start from the repo and
|
|
24
|
+
- start from the repo and `~/.enact/factory/projects/<key>/` truth, not chat memory
|
|
20
25
|
- drive the QA loop through loop MCP tools; CLI commands are the fallback
|
|
21
26
|
- keep loop state current as you go
|
|
22
27
|
- do not stop until all gates pass in a single clean run
|
|
@@ -24,25 +29,25 @@ Combines `$loop` (durable contract-runner with closure gates) with an explicit s
|
|
|
24
29
|
## Workflow
|
|
25
30
|
1. Start a loop contract scoped to the QA goal:
|
|
26
31
|
- MCP: `loop_start` with `goal` and QA gate stages as the contract
|
|
27
|
-
- CLI: `enact-loop
|
|
32
|
+
- CLI fallback: use the `enact-loop` runtime only for `status` / `summary write`; contract start remains MCP-first
|
|
28
33
|
2. Check current loop status before each iteration:
|
|
29
34
|
- MCP: `loop_status`
|
|
30
|
-
- CLI: `enact-loop
|
|
35
|
+
- CLI fallback: `enact-loop status --json`
|
|
31
36
|
3. Run each QA gate in sequence. All must pass before advancing:
|
|
32
37
|
- Unit and integration tests (run the project's test command)
|
|
33
38
|
- Lint and type checks (run the project's lint command)
|
|
34
39
|
- Doctor / readiness check (run the project's doctor command if present)
|
|
35
40
|
- Real-execution smoke test (invoke the primary feature with real inputs, not mocks)
|
|
36
|
-
4. Record each gate
|
|
37
|
-
- MCP: `loop_grade
|
|
38
|
-
- All gate results must include command evidence, not just a pass/fail assertion.
|
|
41
|
+
4. Record each mechanical gate via the engine:
|
|
42
|
+
- MCP: `loop_grade({ stageId, timeoutMs? })` — engine runs the stage command in loop root; rejects caller `status`/`evidence`
|
|
39
43
|
5. After all mechanical gates pass, advance to verifying:
|
|
40
44
|
- MCP: `loop_advance` with `toPhase=verifying`
|
|
41
|
-
6. If a judgment review is required
|
|
42
|
-
- MCP: `loop_grader_dispatch
|
|
43
|
-
7. When all required stages are passed, complete the loop:
|
|
45
|
+
6. If a judgment review is required, dispatch a grader and relay the verdict:
|
|
46
|
+
- MCP: `loop_grader_dispatch({ stageId })` → driver relays via `loop_grader_verdict` (`captureSource: "relayed"`)
|
|
47
|
+
7. When all required stages are passed, write the closure summary then complete the loop:
|
|
48
|
+
- CLI: `enact-loop summary write` (stamps fingerprint into `~/.enact/loop/projects/<key>/state/<YYMMDDHH>-loop-summary.md` and updates `summary-current.json`)
|
|
44
49
|
- MCP: `loop_complete` with `summary`
|
|
45
|
-
- CLI: `
|
|
50
|
+
- CLI fallback: use MCP for completion; `summary write` is the required CLI closure step
|
|
46
51
|
|
|
47
52
|
## Proof Path
|
|
48
53
|
|
|
@@ -51,15 +56,15 @@ Combines `$loop` (durable contract-runner with closure gates) with an explicit s
|
|
|
51
56
|
- Do not substitute inferred status for command-backed evidence.
|
|
52
57
|
|
|
53
58
|
## State Contract
|
|
54
|
-
- Reads:
|
|
55
|
-
- Writes: loop state via MCP tools (`loop_grade`, `loop_advance`, `loop_complete`)
|
|
59
|
+
- Reads: `enact-loop status --json` (current loop state), `enact-loop summary show` / `summary-current.json` (current closure summary), test and lint output
|
|
60
|
+
- Writes: loop state via MCP tools (`loop_grade`, `loop_advance`, `loop_complete`) and `enact-loop summary write` for the append-only closure summary artifact
|
|
56
61
|
|
|
57
62
|
## MCP Tools
|
|
58
63
|
|
|
59
64
|
- `loop_start` — start a loop contract scoped to the QA goal
|
|
60
65
|
- `loop_status` — read current loop state
|
|
61
66
|
- `loop_advance` — transition to the next phase
|
|
62
|
-
- `loop_grade` —
|
|
67
|
+
- `loop_grade` — run a mechanical stage command in loop root (engine-derived pass/fail)
|
|
63
68
|
- `loop_grader_dispatch` — dispatch an independent grader for a judgment gate
|
|
64
69
|
- `loop_grader_verdict` — record an independent grader's GO/NO-GO
|
|
65
70
|
- `loop_block` — mark blocked with a reason
|
|
@@ -69,11 +74,12 @@ Combines `$loop` (durable contract-runner with closure gates) with an explicit s
|
|
|
69
74
|
|
|
70
75
|
## Activation
|
|
71
76
|
|
|
72
|
-
Invoke with `$ultraqa` or `$enact-loop:ultraqa`. The SessionStart hook auto-resumes any active loop
|
|
77
|
+
Invoke with `$ultraqa` or `$enact-loop:ultraqa`. The SessionStart hook auto-resumes any active loop; use `enact-loop status --json` to inspect the current state. The Stop boulder blocks exit until all required stages are passed and the loop phase is terminal.
|
|
73
78
|
|
|
74
79
|
## Final Check
|
|
75
80
|
- Every gate (tests, lint, doctor, smoke) passed in a single iteration with command evidence
|
|
76
|
-
- `loop_grade`
|
|
81
|
+
- `loop_grade` passed all mechanical stages (engine-run, exit 0) before `loop_complete`
|
|
77
82
|
- Judgment stages have valid independent grader verdicts from `loop_grader_verdict`
|
|
78
83
|
- No gate was skipped or bypassed
|
|
84
|
+
- `enact-loop summary write` produced the current timestamped closure summary before `loop_complete`
|
|
79
85
|
- `loop_complete` was called; no loop left in `running` or `verifying` state
|
|
@@ -5,6 +5,11 @@ description: "Lightweight Azure DevOps work-item delivery lane: implement and ha
|
|
|
5
5
|
|
|
6
6
|
# Work With Workitem
|
|
7
7
|
|
|
8
|
+
> **Storage is GLOBAL — never write to a repo-local `.enact` dir.** Resolve the project's global dir:
|
|
9
|
+
> 1. `ROOT="$(git rev-parse --show-toplevel)"`
|
|
10
|
+
> 2. In `~/.enact/workspaces.json` → `workspaces`, find the entry whose `.root` == `$ROOT`; its object key is `<name>-<id>`.
|
|
11
|
+
> 3. Factory planning artifacts go under `~/.enact/factory/projects/<key>/…`; loop runtime state and closure summaries go under `~/.enact/loop/projects/<key>/…`.
|
|
12
|
+
|
|
8
13
|
## Purpose
|
|
9
14
|
|
|
10
15
|
Use `$work-with-workitem` for agent-driven delivery tied to a single Azure DevOps work item.
|
|
@@ -10,6 +10,11 @@ description: >-
|
|
|
10
10
|
|
|
11
11
|
# workitem-triage
|
|
12
12
|
|
|
13
|
+
> **Storage is GLOBAL — never write to a repo-local `.enact` dir.** Resolve the project's global dir:
|
|
14
|
+
> 1. `ROOT="$(git rev-parse --show-toplevel)"`
|
|
15
|
+
> 2. In `~/.enact/workspaces.json` → `workspaces`, find the entry whose `.root` == `$ROOT`; its object key is `<name>-<id>`.
|
|
16
|
+
> 3. Factory planning artifacts and queue-state handoff notes go under `~/.enact/factory/projects/<key>/…` when a downstream skill persists them.
|
|
17
|
+
|
|
13
18
|
## Purpose
|
|
14
19
|
Provide a read-only triage surface for Factory WorkItems. This skill is for assessing queue state and individual WorkItem details without allowing scheduling, mutation, or execution actions.
|
|
15
20
|
|
|
@@ -18,16 +18,17 @@
|
|
|
18
18
|
"targets": [
|
|
19
19
|
"claude",
|
|
20
20
|
"codex",
|
|
21
|
-
"cursor"
|
|
21
|
+
"cursor",
|
|
22
|
+
"enact"
|
|
22
23
|
],
|
|
23
24
|
"skills": "./skills/",
|
|
24
25
|
"hooks": "./hooks/hooks.json",
|
|
25
|
-
"validate": "
|
|
26
|
+
"validate": "node scripts/validate.mjs",
|
|
26
27
|
"mcpServers": "./.mcp.json",
|
|
27
28
|
"interface": {
|
|
28
29
|
"displayName": "Enact Loop",
|
|
29
30
|
"shortDescription": "Contract-runner loop with independent judgment grading.",
|
|
30
|
-
"longDescription": "Runs any declared contract (ordered stages: mechanical and judgment) to closure. The Stop boulder refuses to exit until every required stage passes. Judgment stages are graded by independent agents
|
|
31
|
+
"longDescription": "Runs any declared contract (ordered stages: mechanical and judgment) to closure. The Stop boulder refuses to exit until every required stage passes. Judgment stages are graded by independent agents on a different model — no self-grading. Mechanical stages are engine-run via loop_grade (exit code 0 = pass).",
|
|
31
32
|
"developerName": "enact-loop",
|
|
32
33
|
"category": "Developer Tools",
|
|
33
34
|
"capabilities": [
|
|
@@ -35,7 +36,7 @@
|
|
|
35
36
|
"independent judgment grading",
|
|
36
37
|
"stop boulder enforcement",
|
|
37
38
|
"session auto-resume",
|
|
38
|
-
"mechanical
|
|
39
|
+
"engine-run mechanical grading",
|
|
39
40
|
"loop lifecycle MCP tools"
|
|
40
41
|
]
|
|
41
42
|
},
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
|
|
5
|
+
const root = process.cwd();
|
|
6
|
+
const failures = [];
|
|
7
|
+
|
|
8
|
+
function fail(message) {
|
|
9
|
+
failures.push(message);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function readJson(relativePath) {
|
|
13
|
+
const path = join(root, relativePath);
|
|
14
|
+
if (!existsSync(path)) {
|
|
15
|
+
fail(`${relativePath} is missing`);
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
21
|
+
} catch (err) {
|
|
22
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
23
|
+
fail(`${relativePath} is not valid JSON: ${message}`);
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function assertEqual(actual, expected, label) {
|
|
29
|
+
if (actual !== expected) {
|
|
30
|
+
fail(`${label}: expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function assertArrayIncludes(values, expected, label) {
|
|
35
|
+
if (!Array.isArray(values) || !values.includes(expected)) {
|
|
36
|
+
fail(`${label}: expected array to include ${JSON.stringify(expected)}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function findCommandHook(groups, expectedCommand) {
|
|
41
|
+
if (!Array.isArray(groups)) return null;
|
|
42
|
+
for (const group of groups) {
|
|
43
|
+
if (!Array.isArray(group?.hooks)) continue;
|
|
44
|
+
for (const hook of group.hooks) {
|
|
45
|
+
if (hook?.type === "command" && hook?.command === expectedCommand) {
|
|
46
|
+
return { group, hook };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const manifest = readJson(".agents/plugin.json");
|
|
54
|
+
if (manifest) {
|
|
55
|
+
assertEqual(manifest.name, "enact-loop", "manifest.name");
|
|
56
|
+
assertEqual(manifest.skills, "./skills/", "manifest.skills");
|
|
57
|
+
assertEqual(manifest.hooks, "./hooks/hooks.json", "manifest.hooks");
|
|
58
|
+
assertEqual(manifest.mcpServers, "./.mcp.json", "manifest.mcpServers");
|
|
59
|
+
assertEqual(manifest.validate, "node scripts/validate.mjs", "manifest.validate");
|
|
60
|
+
|
|
61
|
+
for (const target of ["claude", "codex", "cursor", "enact"]) {
|
|
62
|
+
assertArrayIncludes(manifest.targets, target, "manifest.targets");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const mcp = readJson(".mcp.json");
|
|
67
|
+
if (mcp) {
|
|
68
|
+
const server = mcp.mcpServers?.["enact-loop"];
|
|
69
|
+
if (!server) {
|
|
70
|
+
fail('.mcp.json must declare mcpServers["enact-loop"]');
|
|
71
|
+
} else {
|
|
72
|
+
assertEqual(server.command, "enact-loop", 'mcpServers["enact-loop"].command');
|
|
73
|
+
if (!Array.isArray(server.args)) {
|
|
74
|
+
fail('mcpServers["enact-loop"].args must be an array');
|
|
75
|
+
} else {
|
|
76
|
+
assertEqual(server.args[0], "mcp", 'mcpServers["enact-loop"].args[0]');
|
|
77
|
+
assertEqual(server.args[1], ".", 'mcpServers["enact-loop"].args[1]');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const hooks = readJson("hooks/hooks.json");
|
|
83
|
+
if (hooks) {
|
|
84
|
+
const sessionStart = findCommandHook(hooks.hooks?.SessionStart, "enact-loop hook session-start");
|
|
85
|
+
if (!sessionStart) {
|
|
86
|
+
fail('hooks.SessionStart must run "enact-loop hook session-start"');
|
|
87
|
+
} else {
|
|
88
|
+
assertEqual(sessionStart.group.matcher, "startup|resume|clear", "hooks.SessionStart.matcher");
|
|
89
|
+
assertEqual(sessionStart.hook.statusMessage, "Resuming active loop", "hooks.SessionStart.statusMessage");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const stop = findCommandHook(hooks.hooks?.Stop, "enact-loop hook stop");
|
|
93
|
+
if (!stop) {
|
|
94
|
+
fail('hooks.Stop must run "enact-loop hook stop"');
|
|
95
|
+
} else {
|
|
96
|
+
assertEqual(stop.hook.timeout, 30, "hooks.Stop.timeout");
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const skillPath = "skills/enact-loop/SKILL.md";
|
|
101
|
+
if (!existsSync(join(root, skillPath))) {
|
|
102
|
+
fail(`${skillPath} is missing`);
|
|
103
|
+
} else {
|
|
104
|
+
const skill = readFileSync(join(root, skillPath), "utf8");
|
|
105
|
+
if (!/^---\s*\n[\s\S]*?\n---\s*\n/.test(skill)) {
|
|
106
|
+
fail(`${skillPath} must contain YAML frontmatter`);
|
|
107
|
+
}
|
|
108
|
+
if (!/^name:\s*enact-loop\s*$/m.test(skill)) {
|
|
109
|
+
fail(`${skillPath} frontmatter must declare name: enact-loop`);
|
|
110
|
+
}
|
|
111
|
+
if (!/loop_grader_dispatch/.test(skill) || !/loop_grader_verdict/.test(skill)) {
|
|
112
|
+
fail(`${skillPath} must document independent judgment grading tools`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (failures.length > 0) {
|
|
117
|
+
for (const failure of failures) {
|
|
118
|
+
console.error(`[enact-loop validate] ${failure}`);
|
|
119
|
+
}
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
console.log("[enact-loop validate] ok");
|