@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.
Files changed (152) hide show
  1. package/README.md +11 -12
  2. package/dist/create/claude.d.ts.map +1 -1
  3. package/dist/create/claude.js +6 -2
  4. package/dist/create/claude.js.map +1 -1
  5. package/dist/create/cursor.d.ts.map +1 -1
  6. package/dist/create/cursor.js +6 -2
  7. package/dist/create/cursor.js.map +1 -1
  8. package/dist/create/enact.js +1 -1
  9. package/dist/create/enact.js.map +1 -1
  10. package/dist/create/index.d.ts +4 -3
  11. package/dist/create/index.d.ts.map +1 -1
  12. package/dist/create/index.js +9 -2
  13. package/dist/create/index.js.map +1 -1
  14. package/dist/index.d.ts +9 -6
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +5 -4
  17. package/dist/index.js.map +1 -1
  18. package/dist/install.d.ts +5 -0
  19. package/dist/install.d.ts.map +1 -1
  20. package/dist/install.js +91 -11
  21. package/dist/install.js.map +1 -1
  22. package/dist/internal/agents.d.ts +25 -1
  23. package/dist/internal/agents.d.ts.map +1 -1
  24. package/dist/internal/agents.js +81 -4
  25. package/dist/internal/agents.js.map +1 -1
  26. package/dist/internal/claude.d.ts +49 -0
  27. package/dist/internal/claude.d.ts.map +1 -1
  28. package/dist/internal/claude.js +166 -1
  29. package/dist/internal/claude.js.map +1 -1
  30. package/dist/internal/platform.d.ts +11 -1
  31. package/dist/internal/platform.d.ts.map +1 -1
  32. package/dist/internal/platform.js +58 -1
  33. package/dist/internal/platform.js.map +1 -1
  34. package/dist/internal/types.d.ts +2 -1
  35. package/dist/internal/types.d.ts.map +1 -1
  36. package/dist/principles.d.ts +28 -0
  37. package/dist/principles.d.ts.map +1 -0
  38. package/dist/principles.js +159 -0
  39. package/dist/principles.js.map +1 -0
  40. package/extensions/dev-state/.agents/plugin.json +2 -1
  41. package/extensions/enact-context/.agents/plugin.json +2 -1
  42. package/extensions/enact-context/hooks/hooks.json +0 -10
  43. package/extensions/enact-context/skills/enact-context/SKILL.md +14 -12
  44. package/extensions/enact-context/skills/enact-context/scripts/install.sh +7 -7
  45. package/extensions/enact-core/.agents/plugin.json +2 -1
  46. package/extensions/enact-core/OPERATING-PRINCIPLES.md +7 -0
  47. package/extensions/enact-core/hooks/hooks.json +12 -0
  48. package/extensions/enact-evolve/.agents/plugin.json +47 -0
  49. package/extensions/enact-evolve/agents/evolve-session-analyst.toml +37 -0
  50. package/extensions/enact-evolve/skills/session-analysis/SKILL.md +98 -0
  51. package/extensions/enact-evolve/skills/session-analysis/scripts/run-evolve-analysis.sh +343 -0
  52. package/extensions/enact-factory/.agents/plugin.json +2 -1
  53. package/extensions/enact-factory/agents/architect.toml +9 -5
  54. package/extensions/enact-factory/agents/code-reviewer.toml +9 -5
  55. package/extensions/enact-factory/agents/critic.toml +9 -5
  56. package/extensions/enact-factory/agents/executor.toml +4 -1
  57. package/extensions/enact-factory/agents/explore.toml +4 -1
  58. package/extensions/enact-factory/agents/planner.toml +4 -1
  59. package/extensions/enact-factory/agents/verifier.toml +9 -5
  60. package/extensions/enact-factory/skills/advisor/SKILL.md +82 -0
  61. package/extensions/enact-factory/skills/ai-slop-cleaner/SKILL.md +6 -1
  62. package/extensions/enact-factory/skills/autonomous-runner/SKILL.md +347 -0
  63. package/extensions/enact-factory/skills/azdo-ci-strategy/SKILL.md +62 -15
  64. package/extensions/enact-factory/skills/committee/SKILL.md +80 -0
  65. package/extensions/enact-factory/skills/deep-interview/SKILL.md +9 -13
  66. package/extensions/enact-factory/skills/drive-loop/SKILL.md +161 -31
  67. package/extensions/enact-factory/skills/drive-loop/references/contract-schema.md +26 -6
  68. package/extensions/enact-factory/skills/handoff/SKILL.md +72 -0
  69. package/extensions/enact-factory/skills/hyperplan/SKILL.md +11 -3
  70. package/extensions/enact-factory/skills/looplan/SKILL.md +34 -17
  71. package/extensions/enact-factory/skills/plan/SKILL.md +40 -8
  72. package/extensions/enact-factory/skills/remove-deadcode/SKILL.md +6 -1
  73. package/extensions/enact-factory/skills/research/SKILL.md +14 -4
  74. package/extensions/enact-factory/skills/review/SKILL.md +21 -2
  75. package/extensions/enact-factory/skills/security-research/SKILL.md +5 -2
  76. package/extensions/enact-factory/skills/tdd/SKILL.md +7 -1
  77. package/extensions/enact-factory/skills/testing-strategy/SKILL.md +5 -0
  78. package/extensions/enact-factory/skills/trace/SKILL.md +5 -0
  79. package/extensions/enact-factory/skills/ultraqa/SKILL.md +21 -15
  80. package/extensions/enact-factory/skills/work-with-workitem/SKILL.md +5 -0
  81. package/extensions/enact-factory/skills/workitem-triage/SKILL.md +5 -0
  82. package/extensions/enact-loop/.agents/plugin.json +5 -4
  83. package/extensions/enact-loop/scripts/validate.mjs +123 -0
  84. package/extensions/enact-loop/skills/enact-loop/SKILL.md +189 -30
  85. package/extensions/enact-wiki/.agents/plugin.json +2 -1
  86. package/extensions/net-revenue-management/.agents/plugin.json +2 -1
  87. package/extensions/plugin-dev/.agents/plugin.json +2 -1
  88. package/extensions/plugin-dev/skills/start/SKILL.md +3 -3
  89. package/package.json +1 -1
  90. package/scripts/check-hooks.mjs +5 -5
  91. package/scripts/check-principles.mjs +19 -4
  92. package/scripts/enact-extensions.mjs +237 -90
  93. package/scripts/lib/hooks.mjs +61 -217
  94. package/scripts/lib/migrate-artifacts.mjs +144 -0
  95. package/scripts/lib/principles.mjs +109 -0
  96. package/scripts/lib/provision-mcp.mjs +1 -1
  97. package/scripts/lib/run-install.mjs +72 -2
  98. package/scripts/lib/run-prune.mjs +23 -2
  99. package/scripts/lib/run-sync.mjs +4 -1
  100. package/scripts/postinstall.mjs +6 -6
  101. package/scripts/setup-enact-context.sh +20 -15
  102. package/spec/codex.json +5 -0
  103. package/spec/enact.json +3 -3
  104. package/spec/enact.md +1 -4
  105. package/spec/index.json +1 -1
  106. package/extensions/enact-operator/.agents/plugin.json +0 -56
  107. package/extensions/enact-operator/.app.json +0 -3
  108. package/extensions/enact-operator/.mcp.json +0 -10
  109. package/extensions/enact-operator/_taxonomy.md +0 -86
  110. package/extensions/enact-operator/agents/README.md +0 -5
  111. package/extensions/enact-operator/agents/architect.toml +0 -25
  112. package/extensions/enact-operator/agents/code-reviewer.toml +0 -24
  113. package/extensions/enact-operator/agents/critic.toml +0 -30
  114. package/extensions/enact-operator/agents/executor.toml +0 -24
  115. package/extensions/enact-operator/agents/explore.toml +0 -23
  116. package/extensions/enact-operator/agents/planner.toml +0 -24
  117. package/extensions/enact-operator/agents/verifier.toml +0 -24
  118. package/extensions/enact-operator/docs/skill-variants.md +0 -44
  119. package/extensions/enact-operator/hooks/hooks.json +0 -91
  120. package/extensions/enact-operator/skills/ai-slop-cleaner/SKILL.md +0 -50
  121. package/extensions/enact-operator/skills/analyze/SKILL.md +0 -91
  122. package/extensions/enact-operator/skills/ask/SKILL.md +0 -47
  123. package/extensions/enact-operator/skills/autopilot/SKILL.md +0 -170
  124. package/extensions/enact-operator/skills/autoresearch-goal/SKILL.md +0 -79
  125. package/extensions/enact-operator/skills/cancel/SKILL.md +0 -99
  126. package/extensions/enact-operator/skills/configure-notifications/SKILL.md +0 -77
  127. package/extensions/enact-operator/skills/deep-interview/SKILL.md +0 -80
  128. package/extensions/enact-operator/skills/doctor/SKILL.md +0 -48
  129. package/extensions/enact-operator/skills/hud/SKILL.md +0 -49
  130. package/extensions/enact-operator/skills/hyperplan/SKILL.md +0 -47
  131. package/extensions/enact-operator/skills/plan/SKILL.md +0 -78
  132. package/extensions/enact-operator/skills/ralph/SKILL.md +0 -201
  133. package/extensions/enact-operator/skills/ralph/gemini.md +0 -18
  134. package/extensions/enact-operator/skills/ralplan/SKILL.md +0 -151
  135. package/extensions/enact-operator/skills/remove-deadcode/SKILL.md +0 -45
  136. package/extensions/enact-operator/skills/research/SKILL.md +0 -74
  137. package/extensions/enact-operator/skills/review/SKILL.md +0 -58
  138. package/extensions/enact-operator/skills/security-research/SKILL.md +0 -54
  139. package/extensions/enact-operator/skills/setup/SKILL.md +0 -91
  140. package/extensions/enact-operator/skills/setup/scripts/install.sh +0 -50
  141. package/extensions/enact-operator/skills/skill/SKILL.md +0 -82
  142. package/extensions/enact-operator/skills/tdd/SKILL.md +0 -59
  143. package/extensions/enact-operator/skills/team/SKILL.md +0 -199
  144. package/extensions/enact-operator/skills/trace/SKILL.md +0 -41
  145. package/extensions/enact-operator/skills/ultragoal/SKILL.md +0 -99
  146. package/extensions/enact-operator/skills/ultraqa/SKILL.md +0 -113
  147. package/extensions/enact-operator/skills/ultrawork/SKILL.md +0 -145
  148. package/extensions/enact-operator/skills/ultrawork/planner.md +0 -28
  149. package/extensions/enact-operator/skills/wiki/SKILL.md +0 -41
  150. package/extensions/enact-operator/skills/work-with-workitem/SKILL.md +0 -51
  151. /package/extensions/{enact-operator → enact-evolve}/assets/icon.png +0 -0
  152. /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 `.enact/loop/plans/<phase>.md` following `$plan` conventions:
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 `.enact/loop/plans/<phase>-verification.md`.
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: run the command, then `loop_grade`.
58
- - Judgment stages: `loop_grader_dispatch`, await `loop_grader_verdict`.
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. If review passes, complete the loop:
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
- - `.enact/loop/plans/*` (plan and verification map written in Phase 1)
78
- - `.enact/loop/state/loop.json` (loop state)
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
- - `.enact/loop/plans/<phase>.md`
82
- - `.enact/loop/plans/<phase>-verification.md`
83
- - Loop state via MCP tools
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` — record a mechanical stage result with evidence
91
- - `loop_grader_dispatch` — dispatch an independent grader for a judgment stage
92
- - `loop_grader_verdict` — record an independent grader's GO/NO-GO
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 `.enact/loop/plans/<phase>.md` before loop was started
100
- - All stages have evidence recorded, not just a passed status
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 .enact/loop artifacts."
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
- - `.enact/loop/plans/*-requirements.md`
47
- - `.enact/loop/plans/brownfield-map.md`
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 or refine:
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
- - `.enact/loop/plans/<phase>.md`
70
- - `.enact/loop/plans/<phase>-verification.md`
71
- - updated brownfield map or research summary when needed
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 `.enact/loop/remove-deadcode/entry-points.txt`
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 `.enact/loop/research/summary.md`.
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` (for mechanical stages with command evidence)
47
- - `loop_grader_dispatch` + `loop_grader_verdict` (for judgment stages)
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, prefer them for any stage recording that flows from the research output.
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
- - `.enact/loop/` state drift
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
- ## Purpose
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 `.enact/factory/security/<sessionId>/findings.md`.
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 or task notes
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 `.enact/loop/` truth, not chat memory
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 loop start --goal "<what must be verified>"`
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 loop status`
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 result:
37
- - MCP: `loop_grade` with `stageId`, `status=passed|failed`, and `evidence="<command + output>"`
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 before completing, dispatch a grader:
42
- - MCP: `loop_grader_dispatch` with `stageId`; await `loop_grader_verdict`
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: `enact-loop loop complete`
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: `.enact/loop/state/loop.json` (loop state), test and lint output
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` — record a mechanical gate result with command evidence
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 from `.enact/loop/state/loop.json`. The Stop boulder blocks exit until all required stages are passed and the loop phase is terminal.
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` recorded as `passed` for all mechanical stages before `loop_complete`
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": "enact-loop doctor",
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 running on a different vendor/model — no self-grading. Mechanical stages self-report via command evidence. Designed as the slim successor to enact-operator.",
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 stage self-report",
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");