@amsterdamdatalabs/enact-extensions 0.1.12 → 0.1.25

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 (148) hide show
  1. package/README.md +11 -12
  2. package/dist/create/enact.js +1 -1
  3. package/dist/create/enact.js.map +1 -1
  4. package/dist/create/index.d.ts +4 -3
  5. package/dist/create/index.d.ts.map +1 -1
  6. package/dist/create/index.js +9 -2
  7. package/dist/create/index.js.map +1 -1
  8. package/dist/index.d.ts +8 -6
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +4 -3
  11. package/dist/index.js.map +1 -1
  12. package/dist/install.d.ts +5 -0
  13. package/dist/install.d.ts.map +1 -1
  14. package/dist/install.js +10 -3
  15. package/dist/install.js.map +1 -1
  16. package/dist/internal/agents.d.ts +6 -1
  17. package/dist/internal/agents.d.ts.map +1 -1
  18. package/dist/internal/agents.js +8 -4
  19. package/dist/internal/agents.js.map +1 -1
  20. package/dist/internal/claude.d.ts +24 -0
  21. package/dist/internal/claude.d.ts.map +1 -1
  22. package/dist/internal/claude.js +99 -0
  23. package/dist/internal/claude.js.map +1 -1
  24. package/dist/internal/platform.d.ts +3 -1
  25. package/dist/internal/platform.d.ts.map +1 -1
  26. package/dist/internal/platform.js +7 -1
  27. package/dist/internal/platform.js.map +1 -1
  28. package/dist/internal/types.d.ts +2 -1
  29. package/dist/internal/types.d.ts.map +1 -1
  30. package/dist/principles.d.ts +28 -0
  31. package/dist/principles.d.ts.map +1 -0
  32. package/dist/principles.js +159 -0
  33. package/dist/principles.js.map +1 -0
  34. package/extensions/dev-state/.agents/plugin.json +2 -1
  35. package/extensions/enact-context/.agents/plugin.json +2 -1
  36. package/extensions/enact-context/hooks/hooks.json +0 -10
  37. package/extensions/enact-context/skills/enact-context/SKILL.md +14 -12
  38. package/extensions/enact-context/skills/enact-context/scripts/install.sh +7 -7
  39. package/extensions/enact-core/.agents/plugin.json +2 -1
  40. package/extensions/enact-core/OPERATING-PRINCIPLES.md +7 -0
  41. package/extensions/enact-core/hooks/hooks.json +12 -0
  42. package/extensions/enact-evolve/.agents/plugin.json +47 -0
  43. package/extensions/enact-evolve/agents/evolve-session-analyst.toml +37 -0
  44. package/extensions/enact-evolve/skills/session-analysis/SKILL.md +98 -0
  45. package/extensions/enact-evolve/skills/session-analysis/scripts/run-evolve-analysis.sh +343 -0
  46. package/extensions/enact-factory/.agents/plugin.json +2 -2
  47. package/extensions/enact-factory/agents/architect.toml +9 -5
  48. package/extensions/enact-factory/agents/code-reviewer.toml +9 -5
  49. package/extensions/enact-factory/agents/critic.toml +9 -5
  50. package/extensions/enact-factory/agents/executor.toml +4 -1
  51. package/extensions/enact-factory/agents/explore.toml +4 -1
  52. package/extensions/enact-factory/agents/planner.toml +4 -1
  53. package/extensions/enact-factory/agents/verifier.toml +9 -5
  54. package/extensions/enact-factory/skills/advisor/SKILL.md +82 -0
  55. package/extensions/enact-factory/skills/ai-slop-cleaner/SKILL.md +6 -1
  56. package/extensions/enact-factory/skills/autonomous-runner/SKILL.md +347 -0
  57. package/extensions/enact-factory/skills/azdo-ci-strategy/SKILL.md +42 -15
  58. package/extensions/enact-factory/skills/committee/SKILL.md +80 -0
  59. package/extensions/enact-factory/skills/deep-interview/SKILL.md +9 -13
  60. package/extensions/enact-factory/skills/drive-loop/SKILL.md +161 -31
  61. package/extensions/enact-factory/skills/drive-loop/references/contract-schema.md +26 -6
  62. package/extensions/enact-factory/skills/handoff/SKILL.md +72 -0
  63. package/extensions/enact-factory/skills/hyperplan/SKILL.md +11 -3
  64. package/extensions/enact-factory/skills/looplan/SKILL.md +34 -17
  65. package/extensions/enact-factory/skills/plan/SKILL.md +40 -8
  66. package/extensions/enact-factory/skills/remove-deadcode/SKILL.md +6 -1
  67. package/extensions/enact-factory/skills/research/SKILL.md +14 -4
  68. package/extensions/enact-factory/skills/review/SKILL.md +21 -2
  69. package/extensions/enact-factory/skills/security-research/SKILL.md +5 -2
  70. package/extensions/enact-factory/skills/tdd/SKILL.md +7 -1
  71. package/extensions/enact-factory/skills/testing-strategy/SKILL.md +5 -0
  72. package/extensions/enact-factory/skills/trace/SKILL.md +5 -0
  73. package/extensions/enact-factory/skills/ultraqa/SKILL.md +21 -15
  74. package/extensions/enact-factory/skills/work-with-workitem/SKILL.md +5 -0
  75. package/extensions/enact-factory/skills/workitem-triage/SKILL.md +5 -0
  76. package/extensions/enact-loop/.agents/plugin.json +5 -4
  77. package/extensions/enact-loop/scripts/validate.mjs +123 -0
  78. package/extensions/enact-loop/skills/enact-loop/SKILL.md +189 -30
  79. package/extensions/enact-wiki/.agents/plugin.json +2 -1
  80. package/extensions/net-revenue-management/.agents/plugin.json +2 -1
  81. package/extensions/plugin-dev/.agents/plugin.json +2 -1
  82. package/extensions/plugin-dev/skills/start/SKILL.md +3 -3
  83. package/package.json +1 -1
  84. package/scripts/check-hooks.mjs +5 -5
  85. package/scripts/check-principles.mjs +19 -4
  86. package/scripts/enact-extensions.mjs +237 -90
  87. package/scripts/lib/hooks.mjs +61 -217
  88. package/scripts/lib/migrate-artifacts.mjs +144 -0
  89. package/scripts/lib/principles.mjs +109 -0
  90. package/scripts/lib/provision-mcp.mjs +1 -1
  91. package/scripts/lib/run-install.mjs +72 -2
  92. package/scripts/lib/run-prune.mjs +23 -2
  93. package/scripts/lib/run-sync.mjs +4 -1
  94. package/scripts/postinstall.mjs +6 -6
  95. package/scripts/setup-enact-context.sh +20 -15
  96. package/scripts/version-bump.sh +22 -1
  97. package/spec/codex.json +5 -0
  98. package/spec/enact.json +3 -3
  99. package/spec/enact.md +1 -4
  100. package/spec/index.json +1 -1
  101. package/extensions/enact-factory/hooks/hooks.json +0 -14
  102. package/extensions/enact-operator/.agents/plugin.json +0 -56
  103. package/extensions/enact-operator/.app.json +0 -3
  104. package/extensions/enact-operator/.mcp.json +0 -10
  105. package/extensions/enact-operator/_taxonomy.md +0 -86
  106. package/extensions/enact-operator/agents/README.md +0 -5
  107. package/extensions/enact-operator/agents/architect.toml +0 -25
  108. package/extensions/enact-operator/agents/code-reviewer.toml +0 -24
  109. package/extensions/enact-operator/agents/critic.toml +0 -30
  110. package/extensions/enact-operator/agents/executor.toml +0 -24
  111. package/extensions/enact-operator/agents/explore.toml +0 -23
  112. package/extensions/enact-operator/agents/planner.toml +0 -24
  113. package/extensions/enact-operator/agents/verifier.toml +0 -24
  114. package/extensions/enact-operator/docs/skill-variants.md +0 -44
  115. package/extensions/enact-operator/hooks/hooks.json +0 -91
  116. package/extensions/enact-operator/skills/ai-slop-cleaner/SKILL.md +0 -50
  117. package/extensions/enact-operator/skills/analyze/SKILL.md +0 -91
  118. package/extensions/enact-operator/skills/ask/SKILL.md +0 -47
  119. package/extensions/enact-operator/skills/autopilot/SKILL.md +0 -170
  120. package/extensions/enact-operator/skills/autoresearch-goal/SKILL.md +0 -79
  121. package/extensions/enact-operator/skills/cancel/SKILL.md +0 -99
  122. package/extensions/enact-operator/skills/configure-notifications/SKILL.md +0 -77
  123. package/extensions/enact-operator/skills/deep-interview/SKILL.md +0 -80
  124. package/extensions/enact-operator/skills/doctor/SKILL.md +0 -48
  125. package/extensions/enact-operator/skills/hud/SKILL.md +0 -49
  126. package/extensions/enact-operator/skills/hyperplan/SKILL.md +0 -47
  127. package/extensions/enact-operator/skills/plan/SKILL.md +0 -78
  128. package/extensions/enact-operator/skills/ralph/SKILL.md +0 -201
  129. package/extensions/enact-operator/skills/ralph/gemini.md +0 -18
  130. package/extensions/enact-operator/skills/ralplan/SKILL.md +0 -151
  131. package/extensions/enact-operator/skills/remove-deadcode/SKILL.md +0 -45
  132. package/extensions/enact-operator/skills/research/SKILL.md +0 -74
  133. package/extensions/enact-operator/skills/review/SKILL.md +0 -58
  134. package/extensions/enact-operator/skills/security-research/SKILL.md +0 -54
  135. package/extensions/enact-operator/skills/setup/SKILL.md +0 -91
  136. package/extensions/enact-operator/skills/setup/scripts/install.sh +0 -50
  137. package/extensions/enact-operator/skills/skill/SKILL.md +0 -82
  138. package/extensions/enact-operator/skills/tdd/SKILL.md +0 -59
  139. package/extensions/enact-operator/skills/team/SKILL.md +0 -199
  140. package/extensions/enact-operator/skills/trace/SKILL.md +0 -41
  141. package/extensions/enact-operator/skills/ultragoal/SKILL.md +0 -99
  142. package/extensions/enact-operator/skills/ultraqa/SKILL.md +0 -113
  143. package/extensions/enact-operator/skills/ultrawork/SKILL.md +0 -145
  144. package/extensions/enact-operator/skills/ultrawork/planner.md +0 -28
  145. package/extensions/enact-operator/skills/wiki/SKILL.md +0 -41
  146. package/extensions/enact-operator/skills/work-with-workitem/SKILL.md +0 -51
  147. /package/extensions/{enact-operator → enact-evolve}/assets/icon.png +0 -0
  148. /package/extensions/{enact-operator → enact-evolve}/assets/logo.png +0 -0
@@ -1,5 +1,17 @@
1
1
  {
2
2
  "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "matcher": "startup|resume",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "enact-extensions hook session-start",
10
+ "statusMessage": "Checking plugin freshness"
11
+ }
12
+ ]
13
+ }
14
+ ],
3
15
  "UserPromptSubmit": [
4
16
  {
5
17
  "hooks": [
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "enact-evolve",
3
+ "version": "0.1.0",
4
+ "description": "Session evidence analysis plugin for enact-evolve ingestion, evaluation, and synthesis workflows.",
5
+ "author": {
6
+ "name": "Amsterdam Data Labs"
7
+ },
8
+ "homepage": "https://amsterdamdatalabs.com",
9
+ "repository": "https://dev.azure.com/amsterdamdatalabs/Enact/_git/enact-extensions",
10
+ "license": "UNLICENSED",
11
+ "keywords": [
12
+ "enact-evolve",
13
+ "session-analysis",
14
+ "transcripts",
15
+ "evidence",
16
+ "evaluation",
17
+ "synthesis"
18
+ ],
19
+ "targets": [
20
+ "claude",
21
+ "codex",
22
+ "cursor",
23
+ "enact"
24
+ ],
25
+ "skills": "./skills/",
26
+ "agents": "./agents/",
27
+ "interface": {
28
+ "displayName": "Enact Evolve",
29
+ "shortDescription": "CLI-backed session evidence ingestion, evaluation, and synthesis workflows.",
30
+ "longDescription": "Install this plugin to make enact-evolve the default path for Codex, Claude, and Factory session forensics: ingest transcripts, evaluate normalized evidence, and synthesize human-readable findings without running promotion.",
31
+ "developerName": "Amsterdam Data Labs",
32
+ "category": "Developer Tools",
33
+ "composerIcon": "./assets/icon.png",
34
+ "logo": "./assets/logo.png",
35
+ "capabilities": [
36
+ "session transcript ingestion",
37
+ "evidence evaluation",
38
+ "forensics synthesis",
39
+ "candidate improvement review",
40
+ "context usage analysis"
41
+ ]
42
+ },
43
+ "factory": {
44
+ "firstParty": true,
45
+ "operatorScope": "global"
46
+ }
47
+ }
@@ -0,0 +1,37 @@
1
+ name = "evolve-session-analyst"
2
+ desc = "Session forensics agent that must run enact-evolve ingest/evaluate before synthesis"
3
+ model = "gpt-5.5"
4
+ claude_model = "opus"
5
+ cursor_model = "default"
6
+ model_reasoning_effort = "medium"
7
+ sandbox_mode = "danger-full-access"
8
+ developer_instructions = """
9
+ Agent definition: enact-evolve session forensics analyst.
10
+
11
+ Use this agent when a user asks to analyze a Codex, Claude, or Factory session transcript, rollout JSONL, hook/tool behavior, context injection, token/context burn, or why an agent did not use the expected evolve workflow.
12
+
13
+ Core rules:
14
+ - Use enact-evolve artifacts as primary truth.
15
+ - Start with the session-analysis skill workflow and run the bundled run-evolve-analysis.sh helper unless the user explicitly provides already-generated evidence and eval artifacts.
16
+ - Run enact-evolve ingest and enact-evolve evaluate before synthesizing findings.
17
+ - Never run enact-evolve promote.
18
+ - Do not create downstream Dream, wiki, extension, package patch, or promotion handoff artifacts.
19
+ - Treat the current working directory as the project/workspace storage anchor, matching Enact plugin and MCP `mcp .` conventions.
20
+ - Use raw transcript JSONL only as a clearly labeled cross-check for details not yet normalized by enact-evolve, such as exact MCP server/tool pairs or hook execution gaps.
21
+ - If normalized evidence has an empty hook_summary or hook_timeline, report that as an evidence limitation instead of claiming hooks did not fire.
22
+ - Prefer absolute artifact paths in the final report.
23
+
24
+ Analysis process:
25
+ 1. Identify surface and session source.
26
+ 2. Produce or locate session-specific evidence output.
27
+ 3. Read session-evidence.jsonl, eval/metrics.jsonl, eval/candidate-improvements.jsonl, eval/trace-events.jsonl, and the transcript markdown.
28
+ 4. Cross-check raw transcript only for missing normalized fields requested by the user.
29
+ 5. Synthesize a concise report covering identity, pipeline proof, tool/MCP behavior, hook evidence, context injection, token/context usage, candidates, and actionable findings.
30
+
31
+ Output contract:
32
+ - evidence_artifacts
33
+ - normalized_findings
34
+ - raw_cross_checks
35
+ - synthesis
36
+ - follow_up_recommendations
37
+ """
@@ -0,0 +1,98 @@
1
+ ---
2
+ name: session-analysis
3
+ description: This skill should be used when the user asks to analyze, audit, evaluate, or synthesize Codex, Claude, or Factory session transcripts, rollout JSONL files, tool/MCP call behavior, hook evidence, context injection, token usage, or candidate improvements with enact-evolve. It must run enact-evolve ingest and evaluate before drawing conclusions and must not run promotion.
4
+ argument-hint: "--surface <codex|claude|factory> --session <path-or-id> [--watchdog <path>] [--out <dir>]"
5
+ ---
6
+
7
+ # Enact Evolve Session Analysis
8
+
9
+ Use this workflow for session forensics. The purpose is to force the product path first: `enact-evolve ingest` then `enact-evolve evaluate`, then synthesis from generated artifacts.
10
+
11
+ ## Non-Negotiables
12
+
13
+ - Use `enact-evolve` CLI artifacts as primary truth.
14
+ - Never run `enact-evolve promote`.
15
+ - Do not create Dream, wiki, extension, package patch, or promotion handoff artifacts.
16
+ - Do not rely on raw JSONL parsing until after ingest/evaluate has run.
17
+ - Label every raw transcript lookup as a cross-check, not primary evidence.
18
+ - If `hook_summary` or `hook_timeline` is empty, say the normalized evidence did not capture hook firings; do not infer that hooks did not fire.
19
+
20
+ ## Inputs
21
+
22
+ Accept the same arguments as the helper script:
23
+
24
+ ```bash
25
+ ${CLAUDE_PLUGIN_ROOT}/skills/session-analysis/scripts/run-evolve-analysis.sh \
26
+ --surface codex \
27
+ --session /path/to/session.jsonl
28
+ ```
29
+
30
+ Required:
31
+ - `--surface codex|claude|factory`
32
+ - `--session <path-or-id>`
33
+
34
+ Optional:
35
+ - `--watchdog <path>`
36
+ - `--out <dir>`
37
+
38
+ Default output:
39
+ `~/.enact/evolve/projects/<workspace-id>/analysis/<surface>-<safe-session-id>/`
40
+
41
+ The helper resolves `<workspace-id>` from the current working directory by calling `enact-evolve storage --json`, matching the cwd-bound `mcp .` pattern used by other Enact plugins. Pass `--out` only when an explicit non-default location is required.
42
+
43
+ ## Workflow
44
+
45
+ 1. Resolve the session source and surface.
46
+ - Use `codex` for files under `.codex/sessions` or rollout JSONL.
47
+ - Use `claude` for Claude transcript JSONL.
48
+ - Use `factory` only for supported factory scenarios.
49
+ - Treat the current working directory as the owning workspace for storage.
50
+
51
+ 2. Run the helper script.
52
+ - Prefer the bundled script over handwritten CLI command sequences.
53
+ - The script verifies `enact-evolve`, resolves project-scoped analysis storage from cwd, writes session-specific artifacts, and refuses to continue if promotion artifacts are produced.
54
+
55
+ 3. Read these generated artifacts:
56
+ - `session-evidence.jsonl`
57
+ - `metrics.jsonl`
58
+ - `candidate-improvements.jsonl`
59
+ - `trace-events.jsonl`
60
+ - `eval/session-evidence.jsonl`
61
+ - `eval/metrics.jsonl`
62
+ - `eval/candidate-improvements.jsonl`
63
+ - `eval/trace-events.jsonl`
64
+ - `<session-id>.md`
65
+ - `synthesis.md`
66
+
67
+ 4. Synthesize from normalized evidence first.
68
+ - Use `tool_summary`, `tool_timeline`, `hook_summary`, `hook_timeline`, `context_summary`, `system_prompts`, `quality_metrics`, and `candidate_improvements`.
69
+ - Prefer the transcript markdown for readable chronology and context.
70
+ - Use raw JSONL only for fields that are not yet represented in normalized evidence, such as exact MCP `server/tool` pairs.
71
+
72
+ 5. Report limitations.
73
+ - Empty hook summaries mean "not normalized/captured as hook events in evidence", not "did not happen."
74
+ - Missing prompt counts or context entries should be called out as evidence-shape limitations.
75
+ - If the helper fails because `enact-evolve` is missing, report the install/runtime issue before attempting manual analysis.
76
+
77
+ ## Required Synthesis Shape
78
+
79
+ Return or update `synthesis.md` with these sections:
80
+
81
+ - `Session Identity`: surface, session id, source path, evidence id, output paths.
82
+ - `Pipeline Proof`: exact ingest/evaluate commands and generated artifact list.
83
+ - `Tool And MCP Analysis`: normalized tool summary first; raw MCP cross-check only if needed.
84
+ - `Hook Evidence`: hook timeline/summary and any explicit evidence limitation.
85
+ - `Context Injection`: system/developer/context entries, token usage, duplicate context, largest context blocks.
86
+ - `Candidate Summary`: counts by target family, notable source signals, extension-skill/rule/tool-description implications.
87
+ - `Findings`: what happened, what went wrong, and what the assistant should have done.
88
+ - `Follow-Up Recommendations`: implementation or workflow changes, explicitly excluding promotion unless the user separately requests it.
89
+
90
+ ## Verification
91
+
92
+ After running the helper, verify:
93
+ - `session-evidence.jsonl` exists and has at least one record.
94
+ - `eval/metrics.jsonl` exists.
95
+ - `eval/candidate-improvements.jsonl` exists, even if empty.
96
+ - Transcript markdown exists.
97
+ - `synthesis.md` exists.
98
+ - No `promote/` directory exists under the output directory.
@@ -0,0 +1,343 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ usage() {
5
+ cat <<'USAGE'
6
+ Usage:
7
+ run-evolve-analysis.sh --surface codex|claude|factory --session <path-or-id> [--watchdog <path>] [--out <dir>]
8
+
9
+ Runs enact-evolve ingest, enact-evolve evaluate, and writes synthesis.md.
10
+ This workflow does not run promotion.
11
+ USAGE
12
+ }
13
+
14
+ surface=""
15
+ session=""
16
+ watchdog=""
17
+ out=""
18
+
19
+ while [[ $# -gt 0 ]]; do
20
+ case "$1" in
21
+ --surface)
22
+ surface="${2:-}"
23
+ shift 2
24
+ ;;
25
+ --session)
26
+ session="${2:-}"
27
+ shift 2
28
+ ;;
29
+ --watchdog)
30
+ watchdog="${2:-}"
31
+ shift 2
32
+ ;;
33
+ --out)
34
+ out="${2:-}"
35
+ shift 2
36
+ ;;
37
+ -h|--help)
38
+ usage
39
+ exit 0
40
+ ;;
41
+ *)
42
+ echo "Unknown argument: $1" >&2
43
+ usage >&2
44
+ exit 2
45
+ ;;
46
+ esac
47
+ done
48
+
49
+ if [[ -z "$surface" || -z "$session" ]]; then
50
+ usage >&2
51
+ exit 2
52
+ fi
53
+
54
+ case "$surface" in
55
+ codex|claude|factory)
56
+ ;;
57
+ *)
58
+ echo "Invalid --surface: $surface" >&2
59
+ usage >&2
60
+ exit 2
61
+ ;;
62
+ esac
63
+
64
+ if ! command -v enact-evolve >/dev/null 2>&1; then
65
+ echo "enact-evolve is required on PATH." >&2
66
+ exit 127
67
+ fi
68
+
69
+ safe_session_id() {
70
+ local value="$1"
71
+ value="${value%/}"
72
+ value="${value##*/}"
73
+ value="${value:-session}"
74
+ printf '%s' "$value" | sed -E 's/[^A-Za-z0-9._-]+/-/g; s/^-+//; s/-+$//'
75
+ }
76
+
77
+ safe_id="$(safe_session_id "$session")"
78
+ if [[ -z "$out" ]]; then
79
+ storage_json="$(enact-evolve storage --json)" || {
80
+ echo "Unable to resolve project-scoped enact-evolve storage from the current working directory. Run inside a project, or pass --out." >&2
81
+ exit 1
82
+ }
83
+ analysis_root="$(python3 -c 'import json, sys; print(json.load(sys.stdin).get("analysis_dir", ""))' <<< "$storage_json")"
84
+ if [[ -z "$analysis_root" ]]; then
85
+ echo "enact-evolve storage --json did not return analysis_dir." >&2
86
+ exit 1
87
+ fi
88
+ out="${analysis_root}/${surface}-${safe_id}"
89
+ if [[ -e "${out}/session-evidence.jsonl" ]]; then
90
+ out="${out}-$(date -u +%Y%m%dT%H%M%SZ)"
91
+ fi
92
+ fi
93
+
94
+ mkdir -p "$out"
95
+
96
+ if [[ "$surface" == "factory" ]]; then
97
+ ingest_cmd=(enact-evolve ingest --surface "$surface" --scenario "$session" --out "$out")
98
+ else
99
+ ingest_cmd=(enact-evolve ingest --surface "$surface" --session "$session" --out "$out")
100
+ fi
101
+
102
+ if [[ -n "$watchdog" ]]; then
103
+ ingest_cmd+=(--watchdog "$watchdog")
104
+ fi
105
+
106
+ evaluate_cmd=(enact-evolve evaluate --evidence "${out}/session-evidence.jsonl" --out "${out}/eval")
107
+
108
+ {
109
+ printf 'ingest: '
110
+ printf '%q ' "${ingest_cmd[@]}"
111
+ printf '\n'
112
+ printf 'evaluate: '
113
+ printf '%q ' "${evaluate_cmd[@]}"
114
+ printf '\n'
115
+ } > "${out}/pipeline-commands.txt"
116
+
117
+ "${ingest_cmd[@]}"
118
+ "${evaluate_cmd[@]}"
119
+
120
+ python3 - "$out" "$surface" "$session" <<'PY'
121
+ import collections
122
+ import json
123
+ import sys
124
+ from pathlib import Path
125
+
126
+ out = Path(sys.argv[1]).expanduser().resolve()
127
+ surface = sys.argv[2]
128
+ session_arg = sys.argv[3]
129
+
130
+ def read_jsonl(path):
131
+ path = Path(path)
132
+ if not path.exists():
133
+ return []
134
+ text = path.read_text(encoding="utf-8").strip()
135
+ if not text:
136
+ return []
137
+ if text.startswith("["):
138
+ data = json.loads(text)
139
+ return data if isinstance(data, list) else [data]
140
+ rows = []
141
+ for line in text.splitlines():
142
+ line = line.strip()
143
+ if line:
144
+ rows.append(json.loads(line))
145
+ return rows
146
+
147
+ def first_present(mapping, keys, default=None):
148
+ cur = mapping
149
+ for key in keys:
150
+ if not isinstance(cur, dict) or key not in cur:
151
+ return default
152
+ cur = cur[key]
153
+ return cur
154
+
155
+ def fmt_count_map(counter):
156
+ if not counter:
157
+ return "- None"
158
+ items = counter.items() if hasattr(counter, "items") else counter
159
+ return "\n".join(f"- `{key}`: {value}" for key, value in sorted(items))
160
+
161
+ def compact_json(value, limit=600):
162
+ if value in (None, "", [], {}):
163
+ return "None"
164
+ text = json.dumps(value, ensure_ascii=False, sort_keys=True)
165
+ if len(text) > limit:
166
+ return text[: limit - 3] + "..."
167
+ return text
168
+
169
+ def bullet_lines(items, limit=20, key=None):
170
+ if not items:
171
+ return "- None"
172
+ lines = []
173
+ for item in items[:limit]:
174
+ if key and isinstance(item, dict):
175
+ value = item.get(key)
176
+ count = item.get("count")
177
+ if count is not None:
178
+ lines.append(f"- `{value}`: {count}")
179
+ else:
180
+ lines.append(f"- `{value}`")
181
+ elif isinstance(item, dict):
182
+ lines.append(f"- `{compact_json(item, 360)}`")
183
+ else:
184
+ lines.append(f"- `{item}`")
185
+ if len(items) > limit:
186
+ lines.append(f"- ... {len(items) - limit} more")
187
+ return "\n".join(lines)
188
+
189
+ evidence_rows = read_jsonl(out / "session-evidence.jsonl")
190
+ metrics_rows = read_jsonl(out / "metrics.jsonl")
191
+ candidate_rows = read_jsonl(out / "candidate-improvements.jsonl")
192
+ trace_rows = read_jsonl(out / "trace-events.jsonl")
193
+ eval_metrics_rows = read_jsonl(out / "eval" / "metrics.jsonl")
194
+ eval_candidate_rows = read_jsonl(out / "eval" / "candidate-improvements.jsonl")
195
+
196
+ evidence = evidence_rows[-1] if evidence_rows else {}
197
+ quality_metrics = evidence.get("quality_metrics") or {}
198
+ context_usage = quality_metrics.get("context_usage") or {}
199
+ token_usage = quality_metrics.get("token_usage") or {}
200
+ context_summary = evidence.get("context_summary") or []
201
+ context_entries = evidence.get("context_entries") or []
202
+ tool_summary = evidence.get("tool_summary") or []
203
+ tool_timeline = evidence.get("tool_timeline") or []
204
+ hook_summary = evidence.get("hook_summary") or []
205
+ hook_timeline = evidence.get("hook_timeline") or []
206
+ system_prompts = evidence.get("system_prompts") or []
207
+ candidate_source = eval_candidate_rows or candidate_rows
208
+ candidate_counts = collections.Counter(
209
+ (row.get("target_family") or "unknown") for row in candidate_source if isinstance(row, dict)
210
+ )
211
+ source_signal_counts = collections.Counter()
212
+ for row in candidate_source:
213
+ if not isinstance(row, dict):
214
+ continue
215
+ for signal in row.get("source_signals") or []:
216
+ source_signal_counts[str(signal)] += 1
217
+
218
+ artifact_paths = []
219
+ for path in sorted(out.rglob("*")):
220
+ if path.is_file():
221
+ artifact_paths.append(path.relative_to(out).as_posix())
222
+
223
+ transcripts = [
224
+ path for path in sorted(out.glob("*.md"))
225
+ if path.name != "synthesis.md"
226
+ ]
227
+
228
+ commands = (out / "pipeline-commands.txt").read_text(encoding="utf-8").strip()
229
+ session_id = evidence.get("session_id") or Path(session_arg).name
230
+ evidence_id = evidence.get("evidence_id") or evidence.get("id") or "unknown"
231
+ source_refs = evidence.get("source_refs") or []
232
+ source_path = evidence.get("source_path") or evidence.get("source") or (source_refs[0] if source_refs else session_arg)
233
+
234
+ top_context_sources = context_usage.get("top_context_sources") or []
235
+ largest_context_blocks = context_usage.get("largest_context_blocks") or context_usage.get("largest_blocks") or []
236
+ duplicate_context_count = context_usage.get("duplicate_context_count")
237
+ if duplicate_context_count is None:
238
+ duplicate_context_count = context_usage.get("duplicate_count", "not normalized")
239
+
240
+ tool_family_counts = collections.Counter()
241
+ for item in tool_summary:
242
+ if isinstance(item, dict):
243
+ name = item.get("name") or item.get("tool") or item.get("kind") or item.get("key") or "unknown"
244
+ tool_family_counts[str(name)] += int(item.get("count") or 1)
245
+
246
+ markdown = f"""# Enact Evolve Session Analysis
247
+
248
+ ## Session Identity
249
+
250
+ - Surface: `{surface}`
251
+ - Session id: `{session_id}`
252
+ - Source path: `{source_path}`
253
+ - Evidence id: `{evidence_id}`
254
+ - Output directory: `{out}`
255
+ - Transcript markdown: `{transcripts[0] if transcripts else 'not generated'}`
256
+
257
+ ## Pipeline Proof
258
+
259
+ ```text
260
+ {commands}
261
+ ```
262
+
263
+ Generated artifacts:
264
+ {bullet_lines(artifact_paths, limit=80)}
265
+
266
+ ## Tool And MCP Analysis
267
+
268
+ Normalized tool summary:
269
+ {bullet_lines(tool_summary, limit=30)}
270
+
271
+ Tool timeline entries: `{len(tool_timeline)}`
272
+
273
+ Tool family counts:
274
+ {fmt_count_map(tool_family_counts)}
275
+
276
+ Raw MCP cross-check: not performed by this helper. Use the original JSONL only when normalized evidence lacks a requested exact server/tool pair, and label that lookup as a cross-check.
277
+
278
+ ## Hook Evidence
279
+
280
+ Normalized hook summary:
281
+ {bullet_lines(hook_summary, limit=30)}
282
+
283
+ Hook timeline entries: `{len(hook_timeline)}`
284
+
285
+ Evidence limitation: {"normalized evidence did not capture hook firings for this transcript; inspect raw JSONL only as a labeled cross-check for hook execution gaps." if not hook_summary and not hook_timeline else "hook evidence is present in normalized artifacts."}
286
+
287
+ ## Context Injection
288
+
289
+ - System prompt entries: `{len(system_prompts)}`
290
+ - Context entries: `{len(context_entries)}`
291
+ - Context usage: `{compact_json(context_usage, 1200)}`
292
+ - Context summary: `{compact_json(context_summary, 1200)}`
293
+ - Token usage: `{compact_json(token_usage, 1200)}`
294
+ - Duplicate context count: `{duplicate_context_count}`
295
+
296
+ Top context sources:
297
+ {bullet_lines(top_context_sources, limit=20)}
298
+
299
+ Largest context blocks:
300
+ {bullet_lines(largest_context_blocks, limit=20)}
301
+
302
+ ## Candidate Summary
303
+
304
+ Candidate rows: `{len(candidate_source)}`
305
+
306
+ Counts by target family:
307
+ {fmt_count_map(candidate_counts)}
308
+
309
+ Top source signals:
310
+ {fmt_count_map(source_signal_counts.most_common(20))}
311
+
312
+ Extension implications: review candidates targeting skill instructions, hook rules, tool descriptions, and agent routing. Keep promotion out of this plugin workflow unless a separate user request explicitly starts a downstream promotion process.
313
+
314
+ ## Findings
315
+
316
+ - The canonical workflow ran through `enact-evolve ingest` and `enact-evolve evaluate` before synthesis.
317
+ - Findings should be grounded in normalized evidence first; raw transcript inspection is only a cross-check for missing normalized fields.
318
+ - If hook evidence is empty above, the actionable issue is normalizer coverage, not proof that hooks did not execute.
319
+ - If the original assistant analyzed raw JSONL without this pipeline, the follow-up is to route session-forensics requests through this skill and helper first.
320
+
321
+ ## Follow-Up Recommendations
322
+
323
+ - Add or improve evolve normalization for exact MCP server/tool pairs if users routinely ask for that level of detail.
324
+ - Add hook event normalization coverage when transcripts contain hook execution records that do not appear in `hook_summary` or `hook_timeline`.
325
+ - Use candidate target families and source signals to decide whether follow-up work belongs in extension skills, hook rules, or tool descriptions.
326
+ - Keep this plugin CLI-only until `enact-evolve` exposes a real MCP command.
327
+ """
328
+
329
+ (out / "synthesis.md").write_text(markdown, encoding="utf-8")
330
+ PY
331
+
332
+ if [[ -d "${out}/promote" ]]; then
333
+ echo "Unexpected promotion artifacts found under ${out}/promote" >&2
334
+ exit 1
335
+ fi
336
+
337
+ cat <<EOF
338
+ analysis_out=${out}
339
+ session_evidence=${out}/session-evidence.jsonl
340
+ eval_metrics=${out}/eval/metrics.jsonl
341
+ eval_candidates=${out}/eval/candidate-improvements.jsonl
342
+ synthesis=${out}/synthesis.md
343
+ EOF
@@ -18,11 +18,11 @@
18
18
  "targets": [
19
19
  "claude",
20
20
  "codex",
21
- "cursor"
21
+ "cursor",
22
+ "enact"
22
23
  ],
23
24
  "skills": "./skills/",
24
25
  "agents": "./agents/",
25
- "hooks": "./hooks/hooks.json",
26
26
  "mcpServers": "./.mcp.json",
27
27
  "validate": "enact-factory doctor",
28
28
  "interface": {
@@ -1,14 +1,18 @@
1
1
  name = "architect"
2
2
  description = "Architectural review and GO/NO-GO verdict with evidence pointers — independent grader"
3
+ model = "gpt-5.5"
4
+ claude_model = "opus"
5
+ cursor_model = "default"
3
6
  model_reasoning_effort = "high"
4
7
  sandbox_mode = "danger-full-access"
5
8
  tools = "Read, Grep, Glob, Bash"
6
9
  developer_instructions = """
7
- You are the Enact Loop architect agent. You are an INDEPENDENT GRADER.
10
+ Agent definition: read-only architectural reviewer and independent grader for GO/NO-GO verdicts with evidence pointers.
8
11
 
9
- You run on a different model and vendor from the executor. You must reach your own GO/NO-GO verdict
10
- independently — do not defer to the executor's self-assessment. Your verdict is recorded by
11
- `loop_grader_verdict` and is required before the judgment stage can close.
12
+ You run on a different model and vendor from the executor. Reach your own GO/NO-GO verdict
13
+ independently — do not defer to the executor's self-assessment. Return a verdict envelope to the
14
+ driver (default) or call `loop_grader_verdict` directly with the dispatch-minted continuationId.
15
+ You have NO closure authority — do not call loop_complete, summary write, pause/resume, or retarget.
12
16
 
13
17
  Role:
14
18
  - Read-only architectural reviewer.
@@ -20,7 +24,7 @@ Rules:
20
24
  - Never speculate when you can read the source.
21
25
  - Cite exact file paths and line references for material claims.
22
26
  - Call out tradeoffs, not just the favored direction.
23
- - Record your verdict via loop_grader_verdict do not self-report on behalf of the executor.
27
+ - Return verdict envelope to driver (captureSource=relayed) or call loop_grader_verdict directly with continuationId from dispatch. No closure tools.
24
28
 
25
29
  Output contract:
26
30
  - verdict: GO or NO-GO
@@ -1,14 +1,18 @@
1
1
  name = "code-reviewer"
2
2
  description = "Binding code review pass — independent grader on a separate model"
3
+ model = "gpt-5.3-codex-spark"
4
+ claude_model = "haiku"
5
+ cursor_model = "default"
3
6
  model_reasoning_effort = "high"
4
7
  sandbox_mode = "danger-full-access"
5
8
  tools = "Read, Grep, Glob, Bash"
6
9
  developer_instructions = """
7
- You are the Enact Loop code-reviewer agent. You are an INDEPENDENT GRADER.
10
+ Agent definition: binding code review pass independent grader on a separate model.
8
11
 
9
- You run on a different model and vendor from the executor. You must reach your own verdict
10
- independently — do not defer to the executor's self-assessment. Your verdict is recorded by
11
- `loop_grader_verdict` and is required before the judgment stage can close.
12
+ You run on a different model and vendor from the executor. Reach your own verdict
13
+ independently — do not defer to the executor's self-assessment. Return a verdict envelope to the
14
+ driver (default) or call `loop_grader_verdict` directly with the dispatch-minted continuationId.
15
+ You have NO closure authority — do not call loop_complete, summary write, pause/resume, or retarget.
12
16
 
13
17
  Role:
14
18
  - Perform the binding review pass after an implementation batch.
@@ -20,7 +24,7 @@ Rules:
20
24
  - Every finding must cite a file reference and explain impact.
21
25
  - If no actionable issues remain, emit the token UNCONDITIONAL_APPROVE.
22
26
  - Otherwise, return a blocking verdict with the findings ordered by severity.
23
- - Record your verdict via loop_grader_verdict do not self-report on behalf of the executor.
27
+ - Return verdict envelope to driver (captureSource=relayed) or call loop_grader_verdict directly with continuationId from dispatch. No closure tools.
24
28
 
25
29
  Output contract:
26
30
  - verdict: UNCONDITIONAL_APPROVE or REQUEST_CHANGES
@@ -1,14 +1,18 @@
1
1
  name = "critic"
2
2
  description = "Adversarial debate participant for high-risk decision review — independent grader"
3
+ model = "gpt-5.3-codex-spark"
4
+ claude_model = "haiku"
5
+ cursor_model = "default"
3
6
  model_reasoning_effort = "high"
4
7
  sandbox_mode = "danger-full-access"
5
8
  tools = "Read, Grep, Glob, Bash"
6
9
  developer_instructions = """
7
- You are the Enact Loop critic agent. You are an INDEPENDENT GRADER.
10
+ Agent definition: adversarial debate participant for high-risk decision review independent grader.
8
11
 
9
- You run on a different model and vendor from the executor. You must reach your own GO/NO-GO verdict
10
- independently — do not defer to the executor's self-assessment. Your verdict is recorded by
11
- `loop_grader_verdict` and is required before the judgment stage can close.
12
+ You run on a different model and vendor from the executor. Reach your own GO/NO-GO verdict
13
+ independently — do not defer to the executor's self-assessment. Return a verdict envelope to the
14
+ driver (default) or call `loop_grader_verdict` directly with the dispatch-minted continuationId.
15
+ You have NO closure authority — do not call loop_complete, summary write, pause/resume, or retarget.
12
16
 
13
17
  Role:
14
18
  - Attack weak assumptions in plans, proposals, and risky implementation choices.
@@ -19,7 +23,7 @@ Rules:
19
23
  - Surface the strongest counterargument first.
20
24
  - Prefer concrete failure modes over vague concern language.
21
25
  - When a decision looks sound, say that plainly instead of inventing objections.
22
- - Record your GO/NO-GO verdict via loop_grader_verdict do not self-report on behalf of the executor.
26
+ - Return verdict envelope to driver (captureSource=relayed) or call loop_grader_verdict directly with continuationId from dispatch. No closure tools.
23
27
 
24
28
  Round protocol:
25
29
  1. Independent critique.
@@ -1,9 +1,12 @@
1
1
  name = "executor"
2
2
  description = "Focused implementation worker for small, reviewable diffs with verification"
3
+ model = "gpt-5.4"
4
+ claude_model = "sonnet"
5
+ cursor_model = "composer-2.5"
3
6
  model_reasoning_effort = "medium"
4
7
  sandbox_mode = "danger-full-access"
5
8
  developer_instructions = """
6
- You are the Enact Loop executor agent.
9
+ Agent definition: focused implementation worker for small, reviewable diffs with verification.
7
10
 
8
11
  Role:
9
12
  - Implement the requested change with the smallest viable diff.