@hone-ai/cli 1.21.0 → 1.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/hone-cli.js +38 -0
- package/lib/mcp-tools.js +50 -0
- package/lib/story-classifier.js +10 -0
- package/package.json +1 -1
package/hone-cli.js
CHANGED
|
@@ -5417,6 +5417,44 @@ program
|
|
|
5417
5417
|
});
|
|
5418
5418
|
|
|
5419
5419
|
// ── HC-041: Run Story (Orchestrator) ─────────────────────────────────────────
|
|
5420
|
+
program
|
|
5421
|
+
.command('workflows')
|
|
5422
|
+
.description("List your org's recent workflow runs (HC-E5-MCP)")
|
|
5423
|
+
.option('--status <status>', 'Filter: queued|running|paused|completed|failed|stalled|killed')
|
|
5424
|
+
.option('--limit <n>', 'Max runs to return (1-100, default 20)')
|
|
5425
|
+
.option('--format <fmt>', 'Output format: pretty | json', 'pretty')
|
|
5426
|
+
.action(async (opts) => {
|
|
5427
|
+
const config = getConfig();
|
|
5428
|
+
const client = api(config);
|
|
5429
|
+
try {
|
|
5430
|
+
const params = new URLSearchParams();
|
|
5431
|
+
if (opts.status) params.set('status', opts.status);
|
|
5432
|
+
if (opts.limit) params.set('limit', opts.limit);
|
|
5433
|
+
const qs = params.toString();
|
|
5434
|
+
const { data } = await client.get(`/orchestrate${qs ? `?${qs}` : ''}`);
|
|
5435
|
+
if (opts.format === 'json') { console.log(JSON.stringify(data, null, 2)); return; }
|
|
5436
|
+
if (!data.runs.length) { console.log('No workflow runs found.'); return; }
|
|
5437
|
+
const age = (ts) => {
|
|
5438
|
+
const m = Math.floor((Date.now() - new Date(ts).getTime()) / 60000);
|
|
5439
|
+
return m < 60 ? `${m}m` : m < 1440 ? `${Math.floor(m / 60)}h` : `${Math.floor(m / 1440)}d`;
|
|
5440
|
+
};
|
|
5441
|
+
console.log('RUN ID STORY STATUS STEP AGE');
|
|
5442
|
+
for (const r of data.runs) {
|
|
5443
|
+
console.log([
|
|
5444
|
+
String(r.id).slice(0, 8).padEnd(9),
|
|
5445
|
+
String(r.story_id || '-').slice(0, 21).padEnd(22),
|
|
5446
|
+
String(r.status).padEnd(10),
|
|
5447
|
+
String(r.current_step || '-').padEnd(10),
|
|
5448
|
+
age(r.created_at),
|
|
5449
|
+
].join(' ') + (r.error_message ? ` ⚠ ${String(r.error_message).slice(0, 40)}` : ''));
|
|
5450
|
+
}
|
|
5451
|
+
console.log(`\n${data.count} run(s). Inspect: hone show step <runId> <step> · Kill: hone run-story <runId> --kill`);
|
|
5452
|
+
} catch (e) {
|
|
5453
|
+
console.error(`Failed: ${e.response?.data?.error || e.message}`);
|
|
5454
|
+
process.exit(1);
|
|
5455
|
+
}
|
|
5456
|
+
});
|
|
5457
|
+
|
|
5420
5458
|
program
|
|
5421
5459
|
.command('run-story <storyId>')
|
|
5422
5460
|
.description('Run the SDLC pipeline for a story via the orchestrator')
|
package/lib/mcp-tools.js
CHANGED
|
@@ -97,6 +97,40 @@ async function runStory({ storyId, mode = 'batch', cwd } = {}) {
|
|
|
97
97
|
};
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
// hone_list_workflows — list the org's recent runs (readOnly). GET /orchestrate
|
|
101
|
+
// via `hone workflows` (HC-E5-MCP). Summary rows only — the server never sends
|
|
102
|
+
// config/bundled source on the list wire (memo D1).
|
|
103
|
+
async function listWorkflows({ status, limit, cwd } = {}) {
|
|
104
|
+
const args = ['workflows', '--format', 'json'];
|
|
105
|
+
if (status) args.push('--status', String(status));
|
|
106
|
+
if (limit) args.push('--limit', String(limit));
|
|
107
|
+
const r = await runHone(args, { cwd });
|
|
108
|
+
if (r.error) return { isError: true, detail: r.error };
|
|
109
|
+
const data = parseLastJson(r.stdout);
|
|
110
|
+
return {
|
|
111
|
+
isError: !data,
|
|
112
|
+
runs: data ? data.runs : null,
|
|
113
|
+
count: data ? data.count : 0,
|
|
114
|
+
exitCode: r.exitCode,
|
|
115
|
+
detail: data ? `${data.count} run(s)` : (r.stderr || 'could not parse workflows JSON').slice(0, 500),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// hone_kill_workflow — kill ONE run by explicit id (DESTRUCTIVE, irreversible).
|
|
120
|
+
// runId is schema-required: an agent must never guess a target for a kill —
|
|
121
|
+
// explicit id or nothing (memo D3 refutation). Server 409s non-killable states.
|
|
122
|
+
async function killWorkflow({ runId, cwd } = {}) {
|
|
123
|
+
if (!runId) return { isError: true, detail: 'runId is required' };
|
|
124
|
+
const r = await runHone(['run-story', String(runId), '--kill'], { cwd });
|
|
125
|
+
if (r.error) return { isError: true, detail: r.error };
|
|
126
|
+
return {
|
|
127
|
+
isError: !r.ok,
|
|
128
|
+
killed: r.ok,
|
|
129
|
+
exitCode: r.exitCode,
|
|
130
|
+
detail: (r.stdout || r.stderr || '').trim().slice(0, 500) || (r.ok ? 'killed' : 'kill failed'),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
100
134
|
// hone_status — read run status (readOnly). GET /orchestrate/:id.
|
|
101
135
|
async function status({ runId, cwd } = {}) {
|
|
102
136
|
if (!runId) return { isError: true, detail: 'runId is required' };
|
|
@@ -295,6 +329,20 @@ const TOOLS = [
|
|
|
295
329
|
inputSchema: { type: 'object', properties: { skillsOnly: { type: 'boolean', default: false }, agentsOnly: { type: 'boolean', default: false } } },
|
|
296
330
|
handler: sync,
|
|
297
331
|
},
|
|
332
|
+
{
|
|
333
|
+
name: 'hone_list_workflows',
|
|
334
|
+
description: "List your org's recent Hone workflow runs (id, story, status, step, age). Read-only; optional status filter and limit (1-100).",
|
|
335
|
+
readOnly: true,
|
|
336
|
+
inputSchema: { type: 'object', properties: { status: { type: 'string', enum: ['queued', 'running', 'paused', 'completed', 'failed', 'stalled', 'killed'] }, limit: { type: 'number' } } },
|
|
337
|
+
handler: listWorkflows,
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
name: 'hone_kill_workflow',
|
|
341
|
+
description: 'KILL a Hone workflow run by explicit run id. DESTRUCTIVE and irreversible: the run stops and cannot be resumed. Requires the exact runId — list first if unsure.',
|
|
342
|
+
readOnly: false,
|
|
343
|
+
inputSchema: { type: 'object', properties: { runId: { type: 'string' } }, required: ['runId'] },
|
|
344
|
+
handler: killWorkflow,
|
|
345
|
+
},
|
|
298
346
|
{
|
|
299
347
|
name: 'hone_doctor',
|
|
300
348
|
description: 'Self-check the Hone setup (read-only): is a token configured, and is the `hone` CLI installed + reachable? Run this first if other tools fail.',
|
|
@@ -305,6 +353,8 @@ const TOOLS = [
|
|
|
305
353
|
];
|
|
306
354
|
|
|
307
355
|
module.exports = {
|
|
356
|
+
listWorkflows,
|
|
357
|
+
killWorkflow,
|
|
308
358
|
runStory, status, verifyPatch, checkPatch, showStep, approve, emitPr, verifyPr, agentEval, derive, sync, doctor,
|
|
309
359
|
runHone, parseRunStarted, parseLastJson, honeBin, readHoneConfig, TOOLS,
|
|
310
360
|
};
|
package/lib/story-classifier.js
CHANGED
|
@@ -48,6 +48,11 @@ const ARCHITECT_AXES = Object.freeze({
|
|
|
48
48
|
EXTERNAL_COORDINATION: 'external-coordination',
|
|
49
49
|
CROSS_REPO_DEPENDENCY: 'cross-repo-dependency',
|
|
50
50
|
SECURITY_IMPLICATIONS: 'security-implications',
|
|
51
|
+
// HC-DH-001: the story gates/wraps/re-bills/re-routes a function shared by
|
|
52
|
+
// 2+ consumers (billing, auth, quota, dispatch, refusal). Origin: a billing
|
|
53
|
+
// story with single-module surface + one obvious design engaged NO axis —
|
|
54
|
+
// exactly where an independent architect caught a money leak.
|
|
55
|
+
SHARED_CHOKEPOINT: 'shared-chokepoint',
|
|
51
56
|
});
|
|
52
57
|
|
|
53
58
|
// Estimate ordering for threshold comparisons
|
|
@@ -97,6 +102,11 @@ function shouldEngageArchitect(input) {
|
|
|
97
102
|
if (input.has_security_implications === true) {
|
|
98
103
|
axes.push(ARCHITECT_AXES.SECURITY_IMPLICATIONS);
|
|
99
104
|
}
|
|
105
|
+
// Shared chokepoint → architect for whole-repo call-site + invariant review
|
|
106
|
+
// (HC-DH-001). Missing/false input = today's behavior — additive-only.
|
|
107
|
+
if (input.touches_shared_chokepoint === true) {
|
|
108
|
+
axes.push(ARCHITECT_AXES.SHARED_CHOKEPOINT);
|
|
109
|
+
}
|
|
100
110
|
return { engage: axes.length > 0, axes };
|
|
101
111
|
}
|
|
102
112
|
|