@jenga-ai/agent 1.0.1 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/README.md +10 -7
  2. package/agents/developer.md +82 -2
  3. package/agents/scrum-master.md +215 -21
  4. package/agents/tester.md +90 -8
  5. package/hooks/on_session_end.sh +171 -20
  6. package/mcp/router/embedder.js +1 -1
  7. package/mcp/training_runner/index.js +239 -0
  8. package/mcp/training_runner/package-lock.json +1065 -0
  9. package/mcp/training_runner/package.json +15 -0
  10. package/package.json +14 -16
  11. package/scripts/check-permission-level.sh +107 -0
  12. package/scripts/check-publicignore-match.sh +122 -0
  13. package/scripts/check-worktree-liveness.sh +193 -0
  14. package/scripts/generate-rapport-manifest.sh +43 -0
  15. package/scripts/idea_manager.sh +47 -0
  16. package/scripts/install-worktree-commit-guard.sh +134 -0
  17. package/scripts/jenga-permission-level-switch.sh +109 -0
  18. package/scripts/smoke-harness.sh +139 -0
  19. package/scripts/validate-board.sh +62 -0
  20. package/scripts/with-lock.sh +158 -0
  21. package/scripts/worktree-remove-guard.sh +204 -0
  22. package/skills/clearify/SKILL.md +52 -0
  23. package/skills/close-story/SKILL.md +203 -0
  24. package/skills/close-story/scripts/check-story-closeable.sh +195 -0
  25. package/skills/close-story/scripts/compute-scope-divergence.sh +128 -0
  26. package/skills/close-story/scripts/extract-diff-stats.sh +48 -0
  27. package/skills/close-story/scripts/extract-task-diff-stats.sh +97 -0
  28. package/skills/close-story/scripts/update-task-frontmatter.sh +103 -0
  29. package/skills/commit/SKILL.md +30 -3
  30. package/skills/distribute/CONFIG_SCHEMA.md +148 -0
  31. package/skills/distribute/SKILL.md +173 -0
  32. package/skills/distribute/scripts/check-version.sh +74 -0
  33. package/skills/distribute/scripts/commit-version-bump.sh +108 -0
  34. package/skills/distribute/scripts/distribute-changes.sh +381 -0
  35. package/skills/do/SKILL.md +352 -1
  36. package/skills/do/assets/intent-vs-diff-prompt.md +69 -0
  37. package/skills/doc/assets/path-objectives.yaml +13 -0
  38. package/skills/doc-sync/SKILL.md +16 -0
  39. package/skills/doc-sync/assets/doc_targets.md +11 -0
  40. package/skills/idea/SKILL.md +56 -0
  41. package/skills/idea/assets/idea_handoff_template.md +26 -0
  42. package/skills/idea/assets/idea_template.md +3 -0
  43. package/skills/init/SKILL.md +101 -7
  44. package/skills/init/assets/directory_structure.txt +1 -0
  45. package/skills/init/assets/strategy_stub_template.md +38 -0
  46. package/skills/init/assets/workflow_template.json +1 -1
  47. package/skills/init/scripts/apply-project-visibility.sh +176 -0
  48. package/skills/init/scripts/detect-existing-codebase.sh +166 -0
  49. package/skills/init/scripts/init.sh +35 -1
  50. package/skills/jenga/SKILL.md +206 -14
  51. package/skills/jenga/scripts/board-scan.sh +238 -0
  52. package/skills/jenga/scripts/cascade-resolve.sh +297 -0
  53. package/skills/jenga/scripts/render-confirmation.sh +679 -0
  54. package/skills/jenga/scripts/render-picker.sh +439 -0
  55. package/skills/jenga/scripts/resolve-id.sh +367 -0
  56. package/skills/jenga-permission-level/SKILL.md +81 -0
  57. package/skills/proceed/SKILL.md +1 -1
  58. package/skills/publish/SKILL.md +8 -5
  59. package/skills/publish/assets/ci-contract.md +2 -2
  60. package/skills/publish/assets/ownership-matrix.md +1 -1
  61. package/skills/publish/scripts/finalize_changelog.sh +115 -0
  62. package/skills/publish/scripts/generate_release_notes.sh +475 -28
  63. package/skills/publish/scripts/npm_ci_pipeline.sh +44 -6
  64. package/skills/publish/scripts/publish_deploy.sh +38 -8
  65. package/skills/publish/scripts/run_gates.sh +2 -2
  66. package/skills/reconcile/SKILL.md +117 -5
  67. package/skills/reconcile/scripts/detect-unlinked-code.sh +741 -0
  68. package/skills/skillify/assets/init-new/assets/directory_structure.txt +5 -1
  69. package/skills/spinoff/SKILL.md +12 -7
  70. package/skills/todo/SKILL.md +2 -0
  71. package/skills/uncharted/SKILL.md +711 -0
  72. package/skills/uncharted/assets/SEGMENT_PROPOSAL_TEMPLATE.md +129 -0
  73. package/skills/uncharted/assets/UNDERSTANDING_DOC_TEMPLATE.md +160 -0
  74. package/skills/uncharted/scripts/apply-subsystem-cap.sh +573 -0
  75. package/skills/uncharted/scripts/detect-dependencies.sh +732 -0
  76. package/skills/uncharted/scripts/detect-tests.sh +553 -0
  77. package/skills/uncharted/scripts/discover-subsystems.sh +1029 -0
  78. package/skills/uncharted/scripts/enumerate-target.sh +470 -0
  79. package/skills/uncharted/scripts/import-source.sh +517 -0
  80. package/skills/uncharted/scripts/inspect-provenance.sh +573 -0
  81. package/skills/uncharted/scripts/resolve-segment-target.sh +640 -0
  82. package/skills/uncharted/scripts/run-engine.sh +655 -0
  83. package/skills/uncharted/scripts/validate-proposed-items.sh +125 -0
  84. package/skills/uncharted/scripts/write-backfilled-epics.sh +498 -0
  85. package/skills/wtf/SKILL.md +20 -0
  86. package/templates/CHANGELOG_TEMPLATE.md +13 -0
  87. package/templates/PROBLEM_RAPPORT_TEMPLATE.md +4 -1
  88. package/templates/SCRUM_BOARD_SCHEMA.md +206 -10
  89. package/templates/permission-levels/README.md +73 -0
  90. package/templates/permission-levels/level-1-locked.json +71 -0
  91. package/templates/permission-levels/level-2-guarded.json +64 -0
  92. package/templates/permission-levels/level-3-standard.json +62 -0
  93. package/templates/permission-levels/level-4-elevated.json +60 -0
  94. package/templates/permission-levels/level-5-unrestricted.json +58 -0
  95. package/skills/convert/SKILL.md +0 -124
  96. package/skills/convert/convert_cli.py +0 -235
  97. package/skills/convert/tests/sample.csv +0 -4
  98. package/skills/convert/tests/sample.json +0 -5
  99. package/skills/convert/tests/sample.jsonl +0 -3
  100. package/skills/convert/tests/sample.yaml +0 -18
  101. package/skills/convert/tests/sample_obj.csv +0 -2
  102. package/skills/convert/tests/sample_obj.json +0 -9
  103. package/skills/mirror-public/SKILL.md +0 -237
  104. package/skills/mirror-public/assets/config.json +0 -5
  105. package/skills/mirror-public/scripts/mirror.sh +0 -374
  106. package/skills/self-sync/SKILL.md +0 -73
  107. package/skills/self-sync/scripts/run.js +0 -136
  108. package/skills/train/SKILL.md +0 -116
  109. package/skills/train/assets/dashboard-templates/classifiers.html +0 -106
  110. package/skills/train/assets/dashboard-templates/nlp.html +0 -102
  111. package/skills/train/assets/dashboard-templates/transformers.html +0 -98
  112. package/skills/train/assets/results-parsers/__init__.py +0 -9
  113. package/skills/train/assets/results-parsers/classifiers.py +0 -84
  114. package/skills/train/assets/results-parsers/nlp.py +0 -88
  115. package/skills/train/assets/results-parsers/reporter.py +0 -154
  116. package/skills/train/assets/results-parsers/transformers.py +0 -120
  117. package/skills/train/train_cli.py +0 -786
@@ -0,0 +1,239 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * training_runner — MCP server
4
+ *
5
+ * Exposes a single tool: run_training_job
6
+ * - Validates the job directory and config.yaml
7
+ * - Checks confirm_before_run flag
8
+ * - Executes bash start.sh, collecting stdout/stderr
9
+ * - Returns a structured result including exit_code, duration, and results.json contents
10
+ */
11
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
12
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
13
+ import { z } from "zod";
14
+ import { existsSync, readFileSync } from "fs";
15
+ import { join, resolve } from "path";
16
+ import { spawn } from "child_process";
17
+ import { load as yamlLoad } from "js-yaml";
18
+
19
+ const server = new McpServer({
20
+ name: "training_runner",
21
+ version: "1.0.0",
22
+ });
23
+
24
+ // ---------------------------------------------------------------------------
25
+ // Helpers
26
+ // ---------------------------------------------------------------------------
27
+
28
+ /**
29
+ * Load and parse config.yaml from the job directory.
30
+ * Returns { config, error } — error is a string if loading failed.
31
+ */
32
+ function loadConfig(jobDir) {
33
+ const configPath = join(jobDir, "input", "config.yaml");
34
+ if (!existsSync(configPath)) {
35
+ return { config: null, error: `config.yaml not found at: ${configPath}` };
36
+ }
37
+ try {
38
+ const raw = readFileSync(configPath, "utf8");
39
+ const config = yamlLoad(raw) || {};
40
+ return { config, error: null };
41
+ } catch (err) {
42
+ return { config: null, error: `Failed to parse config.yaml: ${err.message}` };
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Validate required config fields.
48
+ * Returns an array of missing field names (empty = all present).
49
+ */
50
+ function validateRequiredFields(config) {
51
+ const missing = [];
52
+ const model = config.model || {};
53
+
54
+ // Every job type requires at least one of model.type or model.name
55
+ if (!model.type && !model.name) {
56
+ missing.push("model.type (classifiers) or model.name (transformers/nlp)");
57
+ }
58
+
59
+ return missing;
60
+ }
61
+
62
+ /**
63
+ * Run `bash start.sh` in jobDir; collect output lines and exit code.
64
+ * Returns a Promise<{ lines: string[], exitCode: number }>.
65
+ */
66
+ function runStartSh(jobDir) {
67
+ return new Promise((resolve_) => {
68
+ const lines = [];
69
+ const proc = spawn("bash", ["start.sh"], {
70
+ cwd: jobDir,
71
+ env: process.env,
72
+ });
73
+
74
+ const collect = (data) => {
75
+ const text = data.toString();
76
+ text.split("\n").forEach((line) => {
77
+ if (line !== "") lines.push(line);
78
+ });
79
+ };
80
+
81
+ proc.stdout.on("data", collect);
82
+ proc.stderr.on("data", collect);
83
+
84
+ proc.on("close", (exitCode) => {
85
+ resolve_({ lines, exitCode: exitCode ?? -1 });
86
+ });
87
+
88
+ proc.on("error", (err) => {
89
+ lines.push(`[runner error] ${err.message}`);
90
+ resolve_({ lines, exitCode: -1 });
91
+ });
92
+ });
93
+ }
94
+
95
+ /**
96
+ * Read results.json from the job directory, if it exists.
97
+ * Returns the parsed object or null.
98
+ */
99
+ function readResultsJson(jobDir) {
100
+ const resultsPath = join(jobDir, "results.json");
101
+ if (!existsSync(resultsPath)) return null;
102
+ try {
103
+ const raw = readFileSync(resultsPath, "utf8");
104
+ return JSON.parse(raw);
105
+ } catch {
106
+ return null;
107
+ }
108
+ }
109
+
110
+ // ---------------------------------------------------------------------------
111
+ // Tool: run_training_job
112
+ // ---------------------------------------------------------------------------
113
+ server.tool(
114
+ "run_training_job",
115
+ "Validate and run an ML training job by executing bash start.sh in the job directory.",
116
+ {
117
+ job_dir: z
118
+ .string()
119
+ .describe("Absolute or relative path to the job directory (must contain input/config.yaml and start.sh)."),
120
+ confirm: z
121
+ .boolean()
122
+ .optional()
123
+ .default(false)
124
+ .describe(
125
+ "Set to true to confirm execution when confirm_before_run is enabled in config.yaml."
126
+ ),
127
+ },
128
+ async ({ job_dir, confirm }) => {
129
+ const jobDir = resolve(job_dir);
130
+
131
+ // --- T02: Directory validation ---
132
+ if (!existsSync(jobDir)) {
133
+ return {
134
+ content: [
135
+ {
136
+ type: "text",
137
+ text: `❌ Job directory not found: ${jobDir}`,
138
+ },
139
+ ],
140
+ };
141
+ }
142
+
143
+ // --- T02: config.yaml validation ---
144
+ const { config, error: configError } = loadConfig(jobDir);
145
+ if (configError) {
146
+ return {
147
+ content: [{ type: "text", text: `❌ ${configError}` }],
148
+ };
149
+ }
150
+
151
+ // --- T02: Required field validation ---
152
+ const missingFields = validateRequiredFields(config);
153
+ if (missingFields.length > 0) {
154
+ return {
155
+ content: [
156
+ {
157
+ type: "text",
158
+ text: `❌ config.yaml is missing required fields:\n${missingFields.map((f) => ` - ${f}`).join("\n")}`,
159
+ },
160
+ ],
161
+ };
162
+ }
163
+
164
+ // --- T02: start.sh must exist ---
165
+ const startSh = join(jobDir, "start.sh");
166
+ if (!existsSync(startSh)) {
167
+ return {
168
+ content: [{ type: "text", text: `❌ start.sh not found in ${jobDir}. Re-scaffold with /train new to generate it.` }],
169
+ };
170
+ }
171
+
172
+ // --- T04: confirm_before_run gate ---
173
+ const workflow = config.workflow || {};
174
+ if (workflow.confirm_before_run === true && !confirm) {
175
+ return {
176
+ content: [
177
+ {
178
+ type: "text",
179
+ text: [
180
+ `⚠️ This job has confirm_before_run: true in its config.yaml.`,
181
+ ``,
182
+ `Job directory: ${jobDir}`,
183
+ ``,
184
+ `To proceed, re-invoke this tool with confirm: true.`,
185
+ ].join("\n"),
186
+ },
187
+ ],
188
+ };
189
+ }
190
+
191
+ // --- T03: Execute bash start.sh ---
192
+ const startTime = Date.now();
193
+ const { lines, exitCode } = await runStartSh(jobDir);
194
+ const durationSeconds = ((Date.now() - startTime) / 1000).toFixed(2);
195
+
196
+ // --- T04 / E01_S04_T02: Read results.json if present ---
197
+ const results = readResultsJson(jobDir);
198
+
199
+ // Build response
200
+ const outputText = lines.join("\n");
201
+ const status = exitCode === 0 ? "✅ Completed" : `❌ Failed (exit code ${exitCode})`;
202
+
203
+ const summary = [
204
+ `${status}`,
205
+ `Job directory : ${jobDir}`,
206
+ `Duration : ${durationSeconds}s`,
207
+ `Exit code : ${exitCode}`,
208
+ ``,
209
+ `--- Output ---`,
210
+ outputText || "(no output)",
211
+ ];
212
+
213
+ if (results !== null) {
214
+ summary.push(``, `--- results.json ---`, JSON.stringify(results, null, 2));
215
+ }
216
+
217
+ // Structured result as JSON (appended as second content block)
218
+ const structuredResult = {
219
+ exit_code: exitCode,
220
+ job_dir: jobDir,
221
+ duration_seconds: parseFloat(durationSeconds),
222
+ output: lines,
223
+ results: results,
224
+ };
225
+
226
+ return {
227
+ content: [
228
+ { type: "text", text: summary.join("\n") },
229
+ { type: "text", text: JSON.stringify(structuredResult, null, 2) },
230
+ ],
231
+ };
232
+ }
233
+ );
234
+
235
+ // ---------------------------------------------------------------------------
236
+ // Start server
237
+ // ---------------------------------------------------------------------------
238
+ const transport = new StdioServerTransport();
239
+ await server.connect(transport);