@planu/cli 4.1.1 → 4.1.3
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/CHANGELOG.md +21 -0
- package/dist/config/license-plans.json +65 -361
- package/dist/engine/core-bridge.js +35 -4
- package/dist/engine/hooks/file-watcher.d.ts +6 -0
- package/dist/engine/hooks/file-watcher.js +69 -16
- package/dist/tools/git/hook-ops.js +23 -9
- package/dist/tools/tool-registry/group-infra.js +22 -0
- package/package.json +7 -7
- package/dist/engine/escalator/index.d.ts +0 -5
- package/dist/engine/escalator/index.js +0 -5
- package/dist/engine/freeze/retro-audit.d.ts +0 -6
- package/dist/engine/freeze/retro-audit.js +0 -24
- package/dist/engine/heal/backup.d.ts +0 -9
- package/dist/engine/heal/backup.js +0 -21
- package/dist/engine/idioma-validator/index.d.ts +0 -17
- package/dist/engine/idioma-validator/index.js +0 -89
- package/dist/engine/saga/index.d.ts +0 -4
- package/dist/engine/saga/index.js +0 -4
- package/dist/engine/spec-state-machine/index.d.ts +0 -3
- package/dist/engine/spec-state-machine/index.js +0 -2
- package/dist/engine/spec-summary-html/dashboard-renderer.d.ts +0 -6
- package/dist/engine/spec-summary-html/dashboard-renderer.js +0 -333
- package/dist/engine/triagier/index.d.ts +0 -5
- package/dist/engine/triagier/index.js +0 -5
- package/dist/engine/universal-rules/index.d.ts +0 -5
- package/dist/engine/universal-rules/index.js +0 -6
- package/dist/testing/cassette/index.d.ts +0 -23
- package/dist/testing/cassette/index.js +0 -26
- package/dist/tools/domain-bundle-handler.d.ts +0 -37
- package/dist/tools/domain-bundle-handler.js +0 -71
- package/dist/tools/figma/rules-file.d.ts +0 -5
- package/dist/tools/figma/rules-file.js +0 -45
- package/dist/tools/heal-planu-root.d.ts +0 -8
- package/dist/tools/heal-planu-root.js +0 -144
- package/dist/tools/opencode-host-adapter.d.ts +0 -3
- package/dist/tools/opencode-host-adapter.js +0 -33
- package/dist/tools/plan-team-distribution.d.ts +0 -3
- package/dist/tools/plan-team-distribution.js +0 -71
- package/dist/tools/reconcile-status-json.d.ts +0 -4
- package/dist/tools/reconcile-status-json.js +0 -209
- package/dist/tools/register-all-tools.d.ts +0 -8
- package/dist/tools/register-all-tools.js +0 -239
- package/dist/tools/tool-registry/group-analysis-monitoring.d.ts +0 -3
- package/dist/tools/tool-registry/group-analysis-monitoring.js +0 -942
- package/dist/tools/tool-registry/group-integrations.d.ts +0 -3
- package/dist/tools/tool-registry/group-integrations.js +0 -1046
- package/dist/tools/tool-registry/group-misc.d.ts +0 -3
- package/dist/tools/tool-registry/group-misc.js +0 -1367
- package/dist/tools/tool-registry/group-platform.d.ts +0 -3
- package/dist/tools/tool-registry/group-platform.js +0 -1681
- package/dist/tools/tool-registry/group-session-knowledge.d.ts +0 -3
- package/dist/tools/tool-registry/group-session-knowledge.js +0 -1416
- package/dist/tools/tool-registry/group-spec-ops.d.ts +0 -3
- package/dist/tools/tool-registry/group-spec-ops.js +0 -917
- package/dist/tools/workspace-overview.d.ts +0 -4
- package/dist/tools/workspace-overview.js +0 -316
- package/dist/transports/middleware/index.d.ts +0 -9
- package/dist/transports/middleware/index.js +0 -7
- package/dist/transports/middleware/with-sandbox.d.ts +0 -21
- package/dist/transports/middleware/with-sandbox.js +0 -68
- package/dist/types/heal.d.ts +0 -18
- package/dist/types/heal.js +0 -3
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { ToolResult } from '../types/index.js';
|
|
2
|
-
import type { ProjectOverviewInput } from '../types/workspace-overview.js';
|
|
3
|
-
export declare function handleProjectOverview(params: ProjectOverviewInput): Promise<ToolResult>;
|
|
4
|
-
//# sourceMappingURL=workspace-overview.d.ts.map
|
|
@@ -1,316 +0,0 @@
|
|
|
1
|
-
// tools/workspace-overview.ts — SPEC-753: project_overview tool
|
|
2
|
-
//
|
|
3
|
-
// Single-call state query: counts, pending, drift, version, cleanup, stale-implementing.
|
|
4
|
-
// Replaces the multi-tool dance (planu_status + list_specs + filesystem reads).
|
|
5
|
-
import { join } from 'node:path';
|
|
6
|
-
import { checkBundledVersionGap } from '../engine/version-detector/bundled-version-checker.js';
|
|
7
|
-
import { checkAndFixBundledVersion } from '../engine/mcp-config/mcp-config-writer.js';
|
|
8
|
-
import { readFile } from 'node:fs/promises';
|
|
9
|
-
import { resolveProjectPath } from '../storage/path-resolver.js';
|
|
10
|
-
import { hashProjectPath } from '../storage/base-store.js';
|
|
11
|
-
import { validateStatusJson } from '../storage/status-store/self-healing.js';
|
|
12
|
-
import { syncVersionField } from '../storage/status-store/version-sync.js';
|
|
13
|
-
import { findStaleImplementing } from '../engine/staleness/stale-implementing.js';
|
|
14
|
-
import { readForceAnalytics } from '../storage/force-analytics-store.js';
|
|
15
|
-
import { PLANU_VERSION } from '../config/version.js';
|
|
16
|
-
// ---------------------------------------------------------------------------
|
|
17
|
-
// Helpers
|
|
18
|
-
// ---------------------------------------------------------------------------
|
|
19
|
-
async function getForceUsage(projectId, totalSpecs) {
|
|
20
|
-
try {
|
|
21
|
-
const analytics = await readForceAnalytics(projectId);
|
|
22
|
-
const ratio = totalSpecs > 0 ? analytics.stats.forcedSpecs / totalSpecs : 0;
|
|
23
|
-
// Simple trend heuristic: compare current ratio to historical ratio stored in stats
|
|
24
|
-
const historicalRatio = analytics.stats.ratio;
|
|
25
|
-
let trend = 'stable';
|
|
26
|
-
if (ratio < historicalRatio - 0.05) {
|
|
27
|
-
trend = 'improving';
|
|
28
|
-
}
|
|
29
|
-
else if (ratio > historicalRatio + 0.05) {
|
|
30
|
-
trend = 'worsening';
|
|
31
|
-
}
|
|
32
|
-
return {
|
|
33
|
-
forcedSpecs: analytics.stats.forcedSpecs,
|
|
34
|
-
totalSpecs,
|
|
35
|
-
ratio: Math.round(ratio * 100) / 100,
|
|
36
|
-
trend,
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
catch {
|
|
40
|
-
return {
|
|
41
|
-
forcedSpecs: 0,
|
|
42
|
-
totalSpecs,
|
|
43
|
-
ratio: 0,
|
|
44
|
-
trend: 'stable',
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
async function getSpecCountsByStatus(projectPath, projectId) {
|
|
49
|
-
const emptyStatus = {
|
|
50
|
-
draft: 0,
|
|
51
|
-
approved: 0,
|
|
52
|
-
implementing: 0,
|
|
53
|
-
review: 0,
|
|
54
|
-
validating: 0,
|
|
55
|
-
done: 0,
|
|
56
|
-
discarded: 0,
|
|
57
|
-
};
|
|
58
|
-
try {
|
|
59
|
-
const { specStore } = await import('../storage/index.js');
|
|
60
|
-
const specs = await specStore.listSpecs(projectId);
|
|
61
|
-
const byStatus = { ...emptyStatus };
|
|
62
|
-
for (const spec of specs) {
|
|
63
|
-
const s = spec.status;
|
|
64
|
-
if (s in byStatus) {
|
|
65
|
-
byStatus[s]++;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
const total = specs.length;
|
|
69
|
-
const pendingTotal = total - byStatus.done - byStatus.discarded;
|
|
70
|
-
return { byStatus, total, pendingTotal };
|
|
71
|
-
}
|
|
72
|
-
catch {
|
|
73
|
-
// Fall back to reading status.json directly
|
|
74
|
-
}
|
|
75
|
-
// Fallback: read status.json
|
|
76
|
-
const statusPath = join(projectPath, 'planu', 'status.json');
|
|
77
|
-
try {
|
|
78
|
-
const raw = await readFile(statusPath, 'utf-8');
|
|
79
|
-
const parsed = JSON.parse(raw);
|
|
80
|
-
if (typeof parsed === 'object' && parsed !== null && 'byStatus' in parsed) {
|
|
81
|
-
const bs = parsed.byStatus;
|
|
82
|
-
if (typeof bs === 'object' && bs !== null) {
|
|
83
|
-
const bsRec = bs;
|
|
84
|
-
const byStatus = {
|
|
85
|
-
draft: bsRec.draft ?? 0,
|
|
86
|
-
approved: bsRec.approved ?? 0,
|
|
87
|
-
implementing: bsRec.implementing ?? 0,
|
|
88
|
-
review: bsRec.review ?? 0,
|
|
89
|
-
validating: bsRec.validating ?? 0,
|
|
90
|
-
done: bsRec.done ?? 0,
|
|
91
|
-
discarded: bsRec.discarded ?? 0,
|
|
92
|
-
};
|
|
93
|
-
const total = Object.values(bsRec).reduce((sum, v) => sum + v, 0);
|
|
94
|
-
const pendingTotal = total - byStatus.done - byStatus.discarded;
|
|
95
|
-
return { byStatus, total, pendingTotal };
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
catch {
|
|
100
|
-
// ignore
|
|
101
|
-
}
|
|
102
|
-
return { byStatus: emptyStatus, total: 0, pendingTotal: 0 };
|
|
103
|
-
}
|
|
104
|
-
async function getTopPending(projectId, topN) {
|
|
105
|
-
try {
|
|
106
|
-
const { specStore } = await import('../storage/index.js');
|
|
107
|
-
const specs = await specStore.listSpecs(projectId);
|
|
108
|
-
const pending = specs.filter((s) => s.status !== 'done' && s.status !== 'discarded');
|
|
109
|
-
// Sort by status priority: implementing > review > validating > approved > draft
|
|
110
|
-
const statusOrder = {
|
|
111
|
-
implementing: 0,
|
|
112
|
-
review: 1,
|
|
113
|
-
validating: 2,
|
|
114
|
-
approved: 3,
|
|
115
|
-
draft: 4,
|
|
116
|
-
};
|
|
117
|
-
pending.sort((a, b) => {
|
|
118
|
-
const ao = statusOrder[a.status] ?? 99;
|
|
119
|
-
const bo = statusOrder[b.status] ?? 99;
|
|
120
|
-
return ao - bo;
|
|
121
|
-
});
|
|
122
|
-
return pending.slice(0, topN).map((s) => ({
|
|
123
|
-
specId: s.id,
|
|
124
|
-
status: s.status,
|
|
125
|
-
title: s.title,
|
|
126
|
-
daysInStatus: 0, // best-effort; transition-log not queried here for performance
|
|
127
|
-
hasProgress: false,
|
|
128
|
-
}));
|
|
129
|
-
}
|
|
130
|
-
catch {
|
|
131
|
-
return [];
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
async function getLastRelease(projectPath) {
|
|
135
|
-
// Try reading from CHANGELOG.md or session-context.md
|
|
136
|
-
try {
|
|
137
|
-
const changelogPath = join(projectPath, 'CHANGELOG.md');
|
|
138
|
-
const raw = await readFile(changelogPath, 'utf-8');
|
|
139
|
-
const versionMatch = /^## \[([^\]]+)\].*?(\d{4}-\d{2}-\d{2})?/m.exec(raw);
|
|
140
|
-
if (versionMatch?.[1]) {
|
|
141
|
-
return {
|
|
142
|
-
version: versionMatch[1],
|
|
143
|
-
publishedAt: versionMatch[2] ?? null,
|
|
144
|
-
tagSha: null,
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
catch {
|
|
149
|
-
// ignore
|
|
150
|
-
}
|
|
151
|
-
try {
|
|
152
|
-
const pkgPath = join(projectPath, 'package.json');
|
|
153
|
-
const raw = await readFile(pkgPath, 'utf-8');
|
|
154
|
-
const pkg = JSON.parse(raw);
|
|
155
|
-
if (typeof pkg === 'object' && pkg !== null && 'version' in pkg) {
|
|
156
|
-
const v = pkg.version;
|
|
157
|
-
if (typeof v === 'string') {
|
|
158
|
-
return { version: v, publishedAt: null, tagSha: null };
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
catch {
|
|
163
|
-
// ignore
|
|
164
|
-
}
|
|
165
|
-
return null;
|
|
166
|
-
}
|
|
167
|
-
async function checkStatusJsonHealth(projectPath) {
|
|
168
|
-
const statusPath = join(projectPath, 'planu', 'status.json');
|
|
169
|
-
const validation = await validateStatusJson(statusPath);
|
|
170
|
-
let versionInSync = true;
|
|
171
|
-
if (validation.ok) {
|
|
172
|
-
const syncResult = await syncVersionField(statusPath);
|
|
173
|
-
versionInSync = !syncResult.synced; // synced=true means it WAS out of sync
|
|
174
|
-
}
|
|
175
|
-
return { healthy: validation.ok, versionInSync };
|
|
176
|
-
}
|
|
177
|
-
// ---------------------------------------------------------------------------
|
|
178
|
-
// Hint generation
|
|
179
|
-
// ---------------------------------------------------------------------------
|
|
180
|
-
function generateHints(result) {
|
|
181
|
-
const hints = [];
|
|
182
|
-
if (!result.drift.statusJsonHealthy) {
|
|
183
|
-
hints.push('status.json is corrupt — run `reconcile_status_json` to repair it from frontmatters');
|
|
184
|
-
}
|
|
185
|
-
if (!result.drift.versionInSync) {
|
|
186
|
-
hints.push(`status.json version is out of sync with runtime — it will be updated automatically`);
|
|
187
|
-
}
|
|
188
|
-
for (const spec of result.staleImplementing) {
|
|
189
|
-
const days = spec.daysInStatus >= 0 ? `${spec.daysInStatus} days` : 'an unknown number of days';
|
|
190
|
-
hints.push(`Consider transitioning ${spec.specId} to done — in implementing for ${days}${spec.hasProgress ? ' (has progress.md)' : ' with no progress.md'}`);
|
|
191
|
-
}
|
|
192
|
-
if (result.status.byStatus.draft > 10) {
|
|
193
|
-
hints.push(`${result.status.byStatus.draft} specs in draft — consider approving or discarding stale ones`);
|
|
194
|
-
}
|
|
195
|
-
return hints;
|
|
196
|
-
}
|
|
197
|
-
// ---------------------------------------------------------------------------
|
|
198
|
-
// Main handler
|
|
199
|
-
// ---------------------------------------------------------------------------
|
|
200
|
-
export async function handleProjectOverview(params) {
|
|
201
|
-
const { includeStaleImplementing = true, staleDays = 7, topN = 10 } = params;
|
|
202
|
-
// Resolve projectPath
|
|
203
|
-
const { projectPath } = await resolveProjectPath(params.projectPath);
|
|
204
|
-
const projectId = hashProjectPath(projectPath);
|
|
205
|
-
// Gather all data in parallel
|
|
206
|
-
const [statusCounts, health, topPending, lastRelease, staleRaw] = await Promise.all([
|
|
207
|
-
getSpecCountsByStatus(projectPath, projectId),
|
|
208
|
-
checkStatusJsonHealth(projectPath),
|
|
209
|
-
getTopPending(projectId, topN),
|
|
210
|
-
getLastRelease(projectPath),
|
|
211
|
-
includeStaleImplementing
|
|
212
|
-
? findStaleImplementing({ projectPath, daysThreshold: staleDays })
|
|
213
|
-
: Promise.resolve([]),
|
|
214
|
-
]);
|
|
215
|
-
// Drift score (best-effort — don't fail the whole call)
|
|
216
|
-
let planuDriftScore = 0;
|
|
217
|
-
try {
|
|
218
|
-
const { computePlanuDriftScore } = await import('../engine/dashboard/drift-score.js');
|
|
219
|
-
const driftResult = await computePlanuDriftScore(projectPath);
|
|
220
|
-
planuDriftScore = driftResult.score;
|
|
221
|
-
}
|
|
222
|
-
catch {
|
|
223
|
-
// ignore
|
|
224
|
-
}
|
|
225
|
-
const drift = {
|
|
226
|
-
statusJsonHealthy: health.healthy,
|
|
227
|
-
versionInSync: health.versionInSync,
|
|
228
|
-
pendingDriftReviews: 0, // SPEC-748 integration — placeholder
|
|
229
|
-
planuDriftScore,
|
|
230
|
-
};
|
|
231
|
-
const forceUsage = await getForceUsage(projectId, statusCounts.total);
|
|
232
|
-
const partialResult = {
|
|
233
|
-
projectId,
|
|
234
|
-
projectPath,
|
|
235
|
-
runtime: {
|
|
236
|
-
planuVersion: PLANU_VERSION,
|
|
237
|
-
node: process.version,
|
|
238
|
-
},
|
|
239
|
-
status: statusCounts,
|
|
240
|
-
topPending,
|
|
241
|
-
lastRelease,
|
|
242
|
-
drift,
|
|
243
|
-
pendingCleanup: null, // SPEC-751 integration — placeholder
|
|
244
|
-
staleImplementing: staleRaw,
|
|
245
|
-
forceUsage,
|
|
246
|
-
};
|
|
247
|
-
const hints = generateHints(partialResult);
|
|
248
|
-
const result = { ...partialResult, hints };
|
|
249
|
-
// Format as structured text for the LLM
|
|
250
|
-
const lines = [
|
|
251
|
-
`# Workspace Overview — ${projectPath.split('/').pop() ?? projectPath}`,
|
|
252
|
-
``,
|
|
253
|
-
`**Runtime:** Planu v${PLANU_VERSION} · Node ${process.version}`,
|
|
254
|
-
`**Project:** \`${projectId}\` at \`${projectPath}\``,
|
|
255
|
-
``,
|
|
256
|
-
`## Spec Status`,
|
|
257
|
-
`| Status | Count |`,
|
|
258
|
-
`|--------|-------|`,
|
|
259
|
-
...Object.entries(result.status.byStatus).map(([s, n]) => `| ${s} | ${String(n)} |`),
|
|
260
|
-
`| **Total** | **${String(result.status.total)}** |`,
|
|
261
|
-
`| **Pending** | **${String(result.status.pendingTotal)}** |`,
|
|
262
|
-
``,
|
|
263
|
-
];
|
|
264
|
-
if (result.topPending.length > 0) {
|
|
265
|
-
lines.push(`## Top ${String(topN)} Pending Specs`);
|
|
266
|
-
lines.push(`| Spec | Status | Title |`);
|
|
267
|
-
lines.push(`|------|--------|-------|`);
|
|
268
|
-
for (const s of result.topPending) {
|
|
269
|
-
lines.push(`| ${s.specId} | ${s.status} | ${s.title} |`);
|
|
270
|
-
}
|
|
271
|
-
lines.push('');
|
|
272
|
-
}
|
|
273
|
-
if (result.staleImplementing.length > 0) {
|
|
274
|
-
lines.push(`## Stale Implementing (>${String(staleDays)}d)`);
|
|
275
|
-
for (const s of result.staleImplementing) {
|
|
276
|
-
const days = s.daysInStatus >= 0 ? `${s.daysInStatus}d` : '?d';
|
|
277
|
-
lines.push(`- **${s.specId}** — ${days} · progress: ${s.hasProgress ? 'yes' : 'no'}`);
|
|
278
|
-
}
|
|
279
|
-
lines.push('');
|
|
280
|
-
}
|
|
281
|
-
lines.push(`## Drift & Health`);
|
|
282
|
-
lines.push(`- status.json: ${result.drift.statusJsonHealthy ? 'healthy' : '⚠️ CORRUPT'}`);
|
|
283
|
-
lines.push(`- version sync: ${result.drift.versionInSync ? 'in sync' : '⚠️ out of sync'}`);
|
|
284
|
-
lines.push(`- drift score: ${String(result.drift.planuDriftScore)}`);
|
|
285
|
-
lines.push('');
|
|
286
|
-
lines.push(`## Force Usage`);
|
|
287
|
-
lines.push(`- ${result.forceUsage.forcedSpecs}/${result.forceUsage.totalSpecs} specs bypassed gates (${Math.round(result.forceUsage.ratio * 100)}%) — trend: ${result.forceUsage.trend}`);
|
|
288
|
-
lines.push('');
|
|
289
|
-
if (result.lastRelease) {
|
|
290
|
-
lines.push(`## Last Release: v${result.lastRelease.version}${result.lastRelease.publishedAt ? ` (${result.lastRelease.publishedAt})` : ''}`);
|
|
291
|
-
lines.push('');
|
|
292
|
-
}
|
|
293
|
-
if (hints.length > 0) {
|
|
294
|
-
lines.push(`## Hints`);
|
|
295
|
-
for (const h of hints) {
|
|
296
|
-
lines.push(`- ${h}`);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
// SPEC-756: lazy version check — fire-and-forget, non-blocking
|
|
300
|
-
checkBundledVersionGap(2000)
|
|
301
|
-
.then((gap) => {
|
|
302
|
-
if (gap.gap) {
|
|
303
|
-
checkAndFixBundledVersion(projectPath, gap.current, gap.latest).catch(() => {
|
|
304
|
-
/* best-effort — never block project_overview */
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
})
|
|
308
|
-
.catch(() => {
|
|
309
|
-
/* best-effort */
|
|
310
|
-
});
|
|
311
|
-
return {
|
|
312
|
-
content: [{ type: 'text', text: lines.join('\n') }],
|
|
313
|
-
structuredContent: result,
|
|
314
|
-
};
|
|
315
|
-
}
|
|
316
|
-
//# sourceMappingURL=workspace-overview.js.map
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export { composeMiddleware } from './compose.js';
|
|
2
|
-
export { withBudget, resetSessionCounters, getSessionCallCount } from './with-budget.js';
|
|
3
|
-
export { withTelemetry, isTelemetryEnabled } from './with-telemetry.js';
|
|
4
|
-
export { withSandbox, requireSandbox, isSandboxRequired, SANDBOX_REQUIRED, } from './with-sandbox.js';
|
|
5
|
-
export { TOOL_OVERRIDES, shouldSkip } from './overrides.js';
|
|
6
|
-
export type { ToolHandler, ToolContext, Middleware } from './types.js';
|
|
7
|
-
export type { ToolOverride } from './overrides.js';
|
|
8
|
-
export type { TelemetryEntry } from './with-telemetry.js';
|
|
9
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
// transports/middleware/index.ts — Barrel export for middleware chain (SPEC-740)
|
|
2
|
-
export { composeMiddleware } from './compose.js';
|
|
3
|
-
export { withBudget, resetSessionCounters, getSessionCallCount } from './with-budget.js';
|
|
4
|
-
export { withTelemetry, isTelemetryEnabled } from './with-telemetry.js';
|
|
5
|
-
export { withSandbox, requireSandbox, isSandboxRequired, SANDBOX_REQUIRED, } from './with-sandbox.js';
|
|
6
|
-
export { TOOL_OVERRIDES, shouldSkip } from './overrides.js';
|
|
7
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { Middleware } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
* Flag value indicating a tool requires sandbox isolation.
|
|
4
|
-
*/
|
|
5
|
-
export declare const SANDBOX_REQUIRED: "required";
|
|
6
|
-
/**
|
|
7
|
-
* withSandbox middleware: delegates to SPEC-742 sandbox runner when tool requires it.
|
|
8
|
-
* No-op pass-through for tools that don't require sandbox.
|
|
9
|
-
* Logs a warning when sandbox is required but no runner is available (transition period).
|
|
10
|
-
*/
|
|
11
|
-
export declare const withSandbox: Middleware;
|
|
12
|
-
/**
|
|
13
|
-
* Register a tool as requiring sandbox isolation.
|
|
14
|
-
* Used by tool registration code (e.g. execute-sdd-flow).
|
|
15
|
-
*/
|
|
16
|
-
export declare function requireSandbox(toolName: string): void;
|
|
17
|
-
/**
|
|
18
|
-
* Check if a tool requires sandbox (for testing).
|
|
19
|
-
*/
|
|
20
|
-
export declare function isSandboxRequired(toolName: string): boolean;
|
|
21
|
-
//# sourceMappingURL=with-sandbox.d.ts.map
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
// transports/middleware/with-sandbox.ts — Sandbox adapter (SPEC-740)
|
|
2
|
-
// Acts as a thin wiring layer to SPEC-742 sandbox runner.
|
|
3
|
-
// When SPEC-742 is not yet wired, falls back to no-op pass-through.
|
|
4
|
-
/**
|
|
5
|
-
* Flag value indicating a tool requires sandbox isolation.
|
|
6
|
-
*/
|
|
7
|
-
export const SANDBOX_REQUIRED = 'required';
|
|
8
|
-
/**
|
|
9
|
-
* Registry of tools that require sandbox isolation.
|
|
10
|
-
* Keyed by tool name. When SPEC-742 lands, this is checked by the middleware.
|
|
11
|
-
*/
|
|
12
|
-
const SANDBOX_REQUIRED_TOOLS = new Set(['execute_sdd_flow']);
|
|
13
|
-
/**
|
|
14
|
-
* Tries to import the SPEC-742 sandbox runner.
|
|
15
|
-
* Returns null if not yet implemented (graceful degradation).
|
|
16
|
-
*/
|
|
17
|
-
async function tryGetSandboxRunner() {
|
|
18
|
-
try {
|
|
19
|
-
// Dynamic import to avoid hard dependency before SPEC-742 lands.
|
|
20
|
-
// The path is intentionally via variable so tsc does not resolve it statically.
|
|
21
|
-
const sandboxPath = '../../engine/sandbox/index.js';
|
|
22
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
23
|
-
const mod = await import(/* @vite-ignore */ sandboxPath);
|
|
24
|
-
const fn = mod.runInSandbox;
|
|
25
|
-
return typeof fn === 'function' ? fn : null;
|
|
26
|
-
}
|
|
27
|
-
catch {
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* withSandbox middleware: delegates to SPEC-742 sandbox runner when tool requires it.
|
|
33
|
-
* No-op pass-through for tools that don't require sandbox.
|
|
34
|
-
* Logs a warning when sandbox is required but no runner is available (transition period).
|
|
35
|
-
*/
|
|
36
|
-
export const withSandbox = (handler) => {
|
|
37
|
-
return async (input, ctx) => {
|
|
38
|
-
if (!SANDBOX_REQUIRED_TOOLS.has(ctx.toolName)) {
|
|
39
|
-
// No sandbox required — pass through
|
|
40
|
-
return handler(input, ctx);
|
|
41
|
-
}
|
|
42
|
-
// Sandbox required — try to get runner from SPEC-742
|
|
43
|
-
const runner = await tryGetSandboxRunner();
|
|
44
|
-
if (runner === null) {
|
|
45
|
-
// SPEC-742 not yet wired — log warning and pass through (transition period)
|
|
46
|
-
console.warn(`[Planu] Sandbox runner not available for ${ctx.toolName}. ` +
|
|
47
|
-
'Running without sandbox isolation. Install SPEC-742 to enable.');
|
|
48
|
-
return handler(input, ctx);
|
|
49
|
-
}
|
|
50
|
-
// Delegate to SPEC-742 runner — the handler is still called but command
|
|
51
|
-
// execution inside it will go through the sandbox runner
|
|
52
|
-
return handler(input, ctx);
|
|
53
|
-
};
|
|
54
|
-
};
|
|
55
|
-
/**
|
|
56
|
-
* Register a tool as requiring sandbox isolation.
|
|
57
|
-
* Used by tool registration code (e.g. execute-sdd-flow).
|
|
58
|
-
*/
|
|
59
|
-
export function requireSandbox(toolName) {
|
|
60
|
-
SANDBOX_REQUIRED_TOOLS.add(toolName);
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Check if a tool requires sandbox (for testing).
|
|
64
|
-
*/
|
|
65
|
-
export function isSandboxRequired(toolName) {
|
|
66
|
-
return SANDBOX_REQUIRED_TOOLS.has(toolName);
|
|
67
|
-
}
|
|
68
|
-
//# sourceMappingURL=with-sandbox.js.map
|
package/dist/types/heal.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export type HealTier = 1 | 2 | 3;
|
|
2
|
-
export interface HealFileResult {
|
|
3
|
-
path: string;
|
|
4
|
-
tier: HealTier;
|
|
5
|
-
action: 'auto-fixed' | 'proposal-emitted' | 'skipped';
|
|
6
|
-
backup?: string;
|
|
7
|
-
proposalPath?: string;
|
|
8
|
-
reason?: string;
|
|
9
|
-
}
|
|
10
|
-
export interface HealRunResult {
|
|
11
|
-
scanned: number;
|
|
12
|
-
results: HealFileResult[];
|
|
13
|
-
skipped: {
|
|
14
|
-
path: string;
|
|
15
|
-
reason: string;
|
|
16
|
-
}[];
|
|
17
|
-
}
|
|
18
|
-
//# sourceMappingURL=heal.d.ts.map
|
package/dist/types/heal.js
DELETED