hadara 0.3.4-rc.0 → 0.4.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/README.md +29 -29
- package/dist/cli/dashboard.js +16 -4
- package/dist/cli/docs.js +50 -0
- package/dist/cli/doctor.js +74 -3
- package/dist/cli/evidence-json.js +3 -0
- package/dist/cli/evidence.js +72 -0
- package/dist/cli/help.js +4 -3
- package/dist/cli/init.js +608 -122
- package/dist/cli/legacy-boundary.js +77 -0
- package/dist/cli/main.js +28 -0
- package/dist/cli/package-smoke.js +1 -0
- package/dist/cli/release-artifact.js +10 -1
- package/dist/cli/release-publish.js +9 -0
- package/dist/cli/task.js +142 -24
- package/dist/cli/validation.js +81 -0
- package/dist/context/context-pack.js +113 -19
- package/dist/context/session-start.js +61 -21
- package/dist/context/task-extractors.js +3 -2
- package/dist/core/schema.js +14 -0
- package/dist/core/timing.js +12 -0
- package/dist/dev/docker-check.js +3 -2
- package/dist/evidence/evidence.js +134 -11
- package/dist/evidence/semantics.js +3 -1
- package/dist/handoff/handoff-stale-problems.js +6 -1
- package/dist/handoff/handoff-suggestion.js +7 -1
- package/dist/handoff/handoff.js +1 -0
- package/dist/harness/validate.js +434 -72
- package/dist/schemas/close-source.schema.json +33 -0
- package/dist/schemas/docs-inbox.schema.json +50 -0
- package/dist/schemas/docs-read-map.schema.json +83 -0
- package/dist/schemas/docs-register.schema.json +70 -0
- package/dist/schemas/evidence-projection.schema.json +35 -0
- package/dist/schemas/schema-index.json +51 -2
- package/dist/schemas/task-audit-close.schema.json +7 -0
- package/dist/schemas/task-close.schema.json +4 -0
- package/dist/schemas/task-finalize.schema.json +40 -1
- package/dist/schemas/task-status.schema.json +117 -0
- package/dist/schemas/task-workbench.schema.json +97 -2
- package/dist/schemas/validation-run.schema.json +103 -0
- package/dist/services/capability-registry.js +216 -51
- package/dist/services/ci-gate.js +5 -2
- package/dist/services/clean-checkout-smoke.js +4 -2
- package/dist/services/dashboard-bootstrap.js +19 -4
- package/dist/services/dashboard-cache.js +2 -0
- package/dist/services/dashboard-task-detail.js +43 -13
- package/dist/services/dashboard-timeline.js +2 -2
- package/dist/services/docs-registry.js +485 -30
- package/dist/services/evidence-lint.js +9 -3
- package/dist/services/lifecycle-guide.js +11 -12
- package/dist/services/operational-debt.js +8 -14
- package/dist/services/operations-status-service.js +7 -1
- package/dist/services/package-recycle.js +101 -45
- package/dist/services/package-smoke.js +7 -2
- package/dist/services/proof-status.js +2 -0
- package/dist/services/protocol-consistency.js +13 -6
- package/dist/services/protocol-migration.js +2 -1
- package/dist/services/release-artifact.js +3 -2
- package/dist/services/release-closeout.js +2 -1
- package/dist/services/release-diagnostics.js +5 -4
- package/dist/services/release-dry-run.js +3 -2
- package/dist/services/state-projection.js +31 -16
- package/dist/services/task-read-model.js +7 -7
- package/dist/services/task-workbench.js +598 -29
- package/dist/services/validation-run.js +333 -0
- package/dist/services/workbench-next-actions.js +31 -20
- package/dist/services/write-preflight.js +2 -20
- package/dist/task/acceptance.js +27 -5
- package/dist/task/authoring-guidance.js +76 -0
- package/dist/task/lifecycle-next-actions.js +0 -1
- package/dist/task/task-capsule.js +24 -18
- package/dist/task/task-close-repair-plan.js +3 -2
- package/dist/task/task-close.js +319 -39
- package/dist/task/task-complete-flow.js +4 -3
- package/dist/task/task-create.js +1 -0
- package/dist/task/task-finalize.js +161 -28
- package/dist/task/task-finish.js +36 -8
- package/dist/task/task-lifecycle.js +8 -3
- package/dist/task/task-templates.js +5 -24
- package/dist/task/task-upgrade-scaffold.js +11 -60
- package/dist/tui/constants.js +1 -7
- package/dist/tui/read-model.js +6 -4
- package/dist/tui/snapshot.js +14 -2
- package/package.json +1 -1
|
@@ -10,6 +10,7 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
10
10
|
const context_graph_builder_1 = require("./context-graph-builder");
|
|
11
11
|
const context_slice_boundary_1 = require("./context-slice-boundary");
|
|
12
12
|
const extractor_contract_1 = require("./extractor-contract");
|
|
13
|
+
const docs_registry_1 = require("../services/docs-registry");
|
|
13
14
|
exports.CONTEXT_PACK_SCHEMA_ID = 'hadara.contextPack.v1';
|
|
14
15
|
exports.CONTEXT_PACK_COMMAND = 'context.pack';
|
|
15
16
|
exports.CONTEXT_PACK_DEFAULT_BUDGET = {
|
|
@@ -62,31 +63,43 @@ function buildContextPackReport(input) {
|
|
|
62
63
|
});
|
|
63
64
|
}
|
|
64
65
|
const connectedIds = taskId ? connectedNodeIds(graphReport.edges, (0, extractor_contract_1.createTaskNodeId)(taskId)) : new Set();
|
|
66
|
+
const docsReadMap = resolveDocsReadMap(input, taskId);
|
|
67
|
+
const readMapExcludedPaths = new Set((docsReadMap?.doNotReadByDefault ?? []).map((entry) => entry.path));
|
|
65
68
|
const rankedNodes = rankContextPackNodes(graphReport.nodes, graphReport.edges, connectedIds, taskNode);
|
|
66
|
-
const readFirstRanked = rankedNodes
|
|
67
|
-
|
|
68
|
-
.
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
const readFirstRanked = rankedNodes
|
|
70
|
+
.filter((ranked) => isReadFirstAllowed(ranked.node))
|
|
71
|
+
.filter((ranked) => !isExcludedByReadMap(ranked.node, readMapExcludedPaths));
|
|
72
|
+
const graphReadFirst = readFirstRanked.map((ranked) => itemFromRankedNode(ranked, true, input.projectRoot));
|
|
73
|
+
const readFirstCandidates = mergeContextPackItems([
|
|
74
|
+
...graphReadFirst.filter((item) => item.id === `task:${taskId}`),
|
|
75
|
+
...readMapItems(docsReadMap?.readFirst ?? [], input.projectRoot, true),
|
|
76
|
+
...graphReadFirst.filter((item) => item.id !== `task:${taskId}`)
|
|
77
|
+
]);
|
|
78
|
+
const readFirst = readFirstCandidates.slice(0, budget.maxReadFirstItems);
|
|
79
|
+
if (readFirstCandidates.length > readFirst.length) {
|
|
71
80
|
issues.push({
|
|
72
81
|
severity: 'warning',
|
|
73
82
|
code: 'CONTEXT_PACK_BUDGET_TRUNCATED',
|
|
74
|
-
message: `Context pack readFirst items were truncated from ${
|
|
83
|
+
message: `Context pack readFirst items were truncated from ${readFirstCandidates.length} to ${readFirst.length}.`
|
|
75
84
|
});
|
|
76
85
|
}
|
|
77
86
|
const selectedIds = new Set(readFirst.map((item) => item.id));
|
|
87
|
+
const selectedPaths = new Set(readFirst.map((item) => item.path).filter((value) => Boolean(value)));
|
|
78
88
|
const maxReadIfNeeded = Math.max(0, (budget.maxItems ?? 30) - readFirst.length);
|
|
79
89
|
const readIfNeededRanked = rankedNodes
|
|
80
|
-
.filter((ranked) => !selectedIds.has(ranked.node.id))
|
|
90
|
+
.filter((ranked) => !selectedIds.has(ranked.node.id) && (!ranked.node.path || !selectedPaths.has(ranked.node.path)))
|
|
91
|
+
.filter((ranked) => !isExcludedByReadMap(ranked.node, readMapExcludedPaths))
|
|
81
92
|
.filter((ranked) => !isDoNotReadByDefault(ranked.node));
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
.map((ranked) => itemFromRankedNode(ranked, false, input.projectRoot))
|
|
85
|
-
|
|
93
|
+
const readIfNeededCandidates = mergeContextPackItems([
|
|
94
|
+
...readMapItems(docsReadMap?.readIfNeeded ?? [], input.projectRoot, false),
|
|
95
|
+
...readIfNeededRanked.map((ranked) => itemFromRankedNode(ranked, false, input.projectRoot))
|
|
96
|
+
]).filter((item) => !selectedIds.has(item.id) && (!item.path || !selectedPaths.has(item.path)));
|
|
97
|
+
const readIfNeeded = readIfNeededCandidates.slice(0, maxReadIfNeeded);
|
|
98
|
+
if (readIfNeededCandidates.length > readIfNeeded.length) {
|
|
86
99
|
issues.push({
|
|
87
100
|
severity: 'warning',
|
|
88
101
|
code: 'CONTEXT_PACK_BUDGET_TRUNCATED',
|
|
89
|
-
message: `Context pack readIfNeeded items were truncated from ${
|
|
102
|
+
message: `Context pack readIfNeeded items were truncated from ${readIfNeededCandidates.length} to ${readIfNeeded.length}.`
|
|
90
103
|
});
|
|
91
104
|
}
|
|
92
105
|
const doNotReadByDefault = graphReport.nodes
|
|
@@ -137,16 +150,86 @@ function buildContextPackReport(input) {
|
|
|
137
150
|
graphAvailable: true,
|
|
138
151
|
codeIndexAvailable: codeIndexAvailable(graphReport),
|
|
139
152
|
stateProjectionAvailable: true,
|
|
140
|
-
docsRegistryAvailable: graphReport.stateProjection.sources.some((source) => source.kind === 'docs-registry'),
|
|
153
|
+
docsRegistryAvailable: Boolean(docsReadMap?.source.registryPresent) || graphReport.stateProjection.sources.some((source) => source.kind === 'docs-registry'),
|
|
141
154
|
commandRegistryAvailable: graphReport.nodes.some((node) => node.type === 'Command'),
|
|
142
155
|
degraded: graphReport.summary.degraded || issues.some((issue) => issue.severity !== 'info'),
|
|
143
156
|
graphSourceHash: graphReport.sourceHash,
|
|
144
|
-
sourcesRead: graphReport.summary.sourcesRead
|
|
157
|
+
sourcesRead: graphReport.summary.sourcesRead,
|
|
158
|
+
docsReadMapAvailable: Boolean(docsReadMap),
|
|
159
|
+
docsReadMapReadFirstCount: docsReadMap?.readFirst.length ?? 0,
|
|
160
|
+
docsReadMapDoNotReadByDefaultCount: docsReadMap?.doNotReadByDefault.length ?? 0
|
|
145
161
|
},
|
|
146
162
|
cache,
|
|
147
163
|
issues
|
|
148
164
|
};
|
|
149
165
|
}
|
|
166
|
+
function resolveDocsReadMap(input, taskId) {
|
|
167
|
+
if (input.docsReadMap)
|
|
168
|
+
return input.docsReadMap;
|
|
169
|
+
if (input.graphReport || !taskId)
|
|
170
|
+
return undefined;
|
|
171
|
+
if (!node_fs_1.default.existsSync(node_path_1.default.join(input.projectRoot, '.hadara', 'docs-registry.json')))
|
|
172
|
+
return undefined;
|
|
173
|
+
return (0, docs_registry_1.createDocsReadMapReport)(input.projectRoot, taskId);
|
|
174
|
+
}
|
|
175
|
+
function readMapItems(entries, projectRoot, required) {
|
|
176
|
+
return [...entries].sort(compareReadMapEntriesForContextPack).map((entry) => {
|
|
177
|
+
const sourceHash = sourceHashForPath(projectRoot, entry.path);
|
|
178
|
+
return {
|
|
179
|
+
id: `doc:${entry.path}`,
|
|
180
|
+
type: 'Document',
|
|
181
|
+
path: entry.path,
|
|
182
|
+
title: entry.title,
|
|
183
|
+
reason: `Docs read-map ${entry.readTier}: ${entry.reason}`,
|
|
184
|
+
confidence: entry.readTier === 'active-task' || entry.readTier === 'active-spec' ? 'explicit' : 'derived',
|
|
185
|
+
...(sourceHash ? { sourceHash } : {}),
|
|
186
|
+
estimatedTokens: estimateTokensForPath(entry.path, entry.title),
|
|
187
|
+
required,
|
|
188
|
+
sourceAccess: sourceAccessForPath(entry.path)
|
|
189
|
+
};
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
function compareReadMapEntriesForContextPack(a, b) {
|
|
193
|
+
return readMapTierPriority(a.readTier) - readMapTierPriority(b.readTier) || a.path.localeCompare(b.path);
|
|
194
|
+
}
|
|
195
|
+
function readMapTierPriority(tier) {
|
|
196
|
+
if (tier === 'active-task')
|
|
197
|
+
return 0;
|
|
198
|
+
if (tier === 'active-spec')
|
|
199
|
+
return 1;
|
|
200
|
+
if (tier === 'current-state')
|
|
201
|
+
return 2;
|
|
202
|
+
if (tier === 'workflow-reference')
|
|
203
|
+
return 3;
|
|
204
|
+
if (tier === 'conditional-reference')
|
|
205
|
+
return 4;
|
|
206
|
+
if (tier === 'implemented-reference')
|
|
207
|
+
return 5;
|
|
208
|
+
if (tier === 'drift-review')
|
|
209
|
+
return 6;
|
|
210
|
+
if (tier === 'historical')
|
|
211
|
+
return 7;
|
|
212
|
+
return 8;
|
|
213
|
+
}
|
|
214
|
+
function mergeContextPackItems(items) {
|
|
215
|
+
const seenIds = new Set();
|
|
216
|
+
const seenPaths = new Set();
|
|
217
|
+
const merged = [];
|
|
218
|
+
for (const item of items) {
|
|
219
|
+
if (seenIds.has(item.id))
|
|
220
|
+
continue;
|
|
221
|
+
if (item.path && seenPaths.has(item.path))
|
|
222
|
+
continue;
|
|
223
|
+
seenIds.add(item.id);
|
|
224
|
+
if (item.path)
|
|
225
|
+
seenPaths.add(item.path);
|
|
226
|
+
merged.push(item);
|
|
227
|
+
}
|
|
228
|
+
return merged;
|
|
229
|
+
}
|
|
230
|
+
function isExcludedByReadMap(node, excludedPaths) {
|
|
231
|
+
return Boolean(node.path && excludedPaths.has(node.path));
|
|
232
|
+
}
|
|
150
233
|
function normalizeContextBudget(input = {}) {
|
|
151
234
|
const maxReadFirstItems = positiveInteger(input.maxReadFirstItems) ?? exports.CONTEXT_PACK_DEFAULT_BUDGET.maxReadFirstItems;
|
|
152
235
|
return {
|
|
@@ -284,19 +367,24 @@ function itemFromRankedNode(ranked, required, projectRoot) {
|
|
|
284
367
|
function sourceHashForItem(projectRoot, node) {
|
|
285
368
|
if (!node.path || !(0, context_slice_boundary_1.isContextSliceProjectRelativePath)(node.path))
|
|
286
369
|
return node.source.hash;
|
|
287
|
-
|
|
370
|
+
return sourceHashForPath(projectRoot, node.path) ?? node.source.hash;
|
|
371
|
+
}
|
|
372
|
+
function sourceHashForPath(projectRoot, relativePath) {
|
|
373
|
+
if (!(0, context_slice_boundary_1.isContextSliceProjectRelativePath)(relativePath))
|
|
374
|
+
return undefined;
|
|
375
|
+
const normalized = (0, context_slice_boundary_1.normalizeContextSliceInputPath)(relativePath);
|
|
288
376
|
const root = node_path_1.default.resolve(projectRoot);
|
|
289
377
|
const absolutePath = node_path_1.default.resolve(root, normalized);
|
|
290
378
|
if (absolutePath !== root && !absolutePath.startsWith(`${root}${node_path_1.default.sep}`))
|
|
291
|
-
return
|
|
379
|
+
return undefined;
|
|
292
380
|
try {
|
|
293
381
|
const stat = node_fs_1.default.statSync(absolutePath);
|
|
294
382
|
if (!stat.isFile())
|
|
295
|
-
return
|
|
383
|
+
return undefined;
|
|
296
384
|
return (0, extractor_contract_1.hashContextGraphText)(node_fs_1.default.readFileSync(absolutePath, 'utf8'));
|
|
297
385
|
}
|
|
298
386
|
catch {
|
|
299
|
-
return
|
|
387
|
+
return undefined;
|
|
300
388
|
}
|
|
301
389
|
}
|
|
302
390
|
function sourceAccessForNode(node) {
|
|
@@ -306,7 +394,10 @@ function sourceAccessForNode(node) {
|
|
|
306
394
|
reason: 'This context item has no project file path for raw context slicing.'
|
|
307
395
|
};
|
|
308
396
|
}
|
|
309
|
-
|
|
397
|
+
return sourceAccessForPath(node.path);
|
|
398
|
+
}
|
|
399
|
+
function sourceAccessForPath(relativePath) {
|
|
400
|
+
if ((0, context_slice_boundary_1.isContextSliceProjectRelativePath)(relativePath)) {
|
|
310
401
|
return {
|
|
311
402
|
rawSlice: 'sliceable',
|
|
312
403
|
reason: 'This item path is inside the raw context-slice read boundary.'
|
|
@@ -322,6 +413,9 @@ function estimateTokens(node) {
|
|
|
322
413
|
const pathCost = node.path ? Math.ceil(node.path.length / 4) : 0;
|
|
323
414
|
return Math.max(24, labelCost + pathCost + 16);
|
|
324
415
|
}
|
|
416
|
+
function estimateTokensForPath(relativePath, title) {
|
|
417
|
+
return Math.max(24, Math.ceil(title.length / 4) + Math.ceil(relativePath.length / 4) + 16);
|
|
418
|
+
}
|
|
325
419
|
function validationSuggestionsForTask(taskId, graphReport) {
|
|
326
420
|
const suggestions = new Map();
|
|
327
421
|
if (taskId) {
|
|
@@ -7,6 +7,8 @@ const context_graph_builder_1 = require("./context-graph-builder");
|
|
|
7
7
|
const context_cache_store_1 = require("./context-cache-store");
|
|
8
8
|
const source_manifest_1 = require("./source-manifest");
|
|
9
9
|
const code_graph_extractor_1 = require("./code-graph-extractor");
|
|
10
|
+
const validate_1 = require("../harness/validate");
|
|
11
|
+
const docs_registry_1 = require("../services/docs-registry");
|
|
10
12
|
exports.SESSION_START_SCHEMA_ID = 'hadara.sessionStart.v1';
|
|
11
13
|
exports.SESSION_START_COMMAND = 'session.start';
|
|
12
14
|
function buildSessionStartReport(input) {
|
|
@@ -41,6 +43,7 @@ function buildSessionStartReport(input) {
|
|
|
41
43
|
lifecycle,
|
|
42
44
|
allowLiveContextPack: Boolean(input.allowLiveContextPack)
|
|
43
45
|
});
|
|
46
|
+
const docsReadMap = taskId ? createSessionStartDocsReadMap(input.projectRoot, taskId, input.budget?.maxReadFirstItems ?? 7) : undefined;
|
|
44
47
|
return {
|
|
45
48
|
schemaVersion: exports.SESSION_START_SCHEMA_ID,
|
|
46
49
|
command: exports.SESSION_START_COMMAND,
|
|
@@ -56,6 +59,7 @@ function buildSessionStartReport(input) {
|
|
|
56
59
|
contextPack,
|
|
57
60
|
lifecycle,
|
|
58
61
|
guidance,
|
|
62
|
+
...(docsReadMap ? { docsReadMap } : {}),
|
|
59
63
|
knownProblems: contextPack.knownProblems,
|
|
60
64
|
sourceSummary: contextPack.sourceSummary,
|
|
61
65
|
cache: contextPack.cache,
|
|
@@ -70,6 +74,43 @@ function buildSessionStartReport(input) {
|
|
|
70
74
|
issues
|
|
71
75
|
};
|
|
72
76
|
}
|
|
77
|
+
function createSessionStartDocsReadMap(projectRoot, taskId, maxReadFirst) {
|
|
78
|
+
const readMap = (0, docs_registry_1.createDocsReadMapReport)(projectRoot, taskId);
|
|
79
|
+
const sourceValidation = (0, validate_1.validateTaskCapsule)(projectRoot, taskId, { level: 'done' });
|
|
80
|
+
const sourceDocumentDrift = sourceValidation.issues
|
|
81
|
+
.filter((issue) => issue.code === 'TASK_SOURCE_DOCUMENT_CHANGED' || issue.code === 'TASK_SOURCE_DOCUMENT_MISSING_HASH')
|
|
82
|
+
.map((issue) => ({
|
|
83
|
+
code: issue.code,
|
|
84
|
+
message: issue.message,
|
|
85
|
+
...(issue.path ? { path: issue.path } : {}),
|
|
86
|
+
...(issue.heading ? { heading: issue.heading } : {})
|
|
87
|
+
}));
|
|
88
|
+
return {
|
|
89
|
+
taskId: readMap.taskId,
|
|
90
|
+
command: `node dist/cli/main.js docs read-map --task ${taskId} --json`,
|
|
91
|
+
source: readMap.source,
|
|
92
|
+
task: readMap.task,
|
|
93
|
+
readFirstCount: readMap.readFirst.length,
|
|
94
|
+
readIfNeededCount: readMap.readIfNeeded.length,
|
|
95
|
+
doNotReadByDefaultCount: readMap.doNotReadByDefault.length,
|
|
96
|
+
driftWarningCount: readMap.driftWarnings.length,
|
|
97
|
+
sourceDocumentDriftCount: sourceDocumentDrift.length,
|
|
98
|
+
readFirst: readMap.readFirst.slice(0, maxReadFirst).map((entry) => ({
|
|
99
|
+
path: entry.path,
|
|
100
|
+
readTier: entry.readTier,
|
|
101
|
+
authority: entry.authority,
|
|
102
|
+
reason: entry.reason
|
|
103
|
+
})),
|
|
104
|
+
driftWarnings: readMap.driftWarnings.slice(0, 10),
|
|
105
|
+
sourceDocumentDrift,
|
|
106
|
+
issues: readMap.issues.map((issue) => ({
|
|
107
|
+
severity: issue.severity,
|
|
108
|
+
code: issue.code,
|
|
109
|
+
message: issue.message,
|
|
110
|
+
...(issue.path ? { path: issue.path } : {})
|
|
111
|
+
}))
|
|
112
|
+
};
|
|
113
|
+
}
|
|
73
114
|
function buildWarmCachedContextPackReport(input) {
|
|
74
115
|
const cachedManifest = (0, context_cache_store_1.readContextSourceManifestCache)(input.projectRoot);
|
|
75
116
|
if (cachedManifest.status !== 'valid' || !cachedManifest.manifest)
|
|
@@ -134,11 +175,10 @@ function buildWarmCachedContextPackReport(input) {
|
|
|
134
175
|
function lifecycleForSessionStart(taskId, contextPack) {
|
|
135
176
|
const primaryNextCommands = taskId
|
|
136
177
|
? [
|
|
137
|
-
`node dist/cli/main.js task lifecycle --task ${taskId} --json`,
|
|
138
178
|
`node dist/cli/main.js task status --task ${taskId} --json`,
|
|
139
179
|
`node dist/cli/main.js context pack --task ${taskId} --json`
|
|
140
180
|
]
|
|
141
|
-
: ['node dist/cli/main.js task
|
|
181
|
+
: ['node dist/cli/main.js task status --json'];
|
|
142
182
|
for (const suggestion of contextPack.validateWith) {
|
|
143
183
|
if (suggestion.requiredForClose && !primaryNextCommands.includes(suggestion.command)) {
|
|
144
184
|
primaryNextCommands.push(suggestion.command);
|
|
@@ -179,42 +219,36 @@ function guidanceForSessionStart(input) {
|
|
|
179
219
|
let primaryAction;
|
|
180
220
|
if (!taskId) {
|
|
181
221
|
primaryAction = {
|
|
182
|
-
id: 'task-
|
|
222
|
+
id: 'task-status',
|
|
183
223
|
label: 'Select the next task',
|
|
184
|
-
command: 'node dist/cli/main.js task
|
|
185
|
-
args: ['task', '
|
|
224
|
+
command: 'node dist/cli/main.js task status --json',
|
|
225
|
+
args: ['task', 'status', '--json'],
|
|
186
226
|
reason: 'No task id is available, so the next useful step is to select a concrete task before reading task-scoped context.',
|
|
187
227
|
writeBoundary: 'read-only',
|
|
188
228
|
recommendedActorRole: 'agent-worker'
|
|
189
229
|
};
|
|
190
230
|
commands.push({
|
|
191
|
-
id: 'task-
|
|
192
|
-
command: 'node dist/cli/main.js task
|
|
193
|
-
args: ['task', '
|
|
231
|
+
id: 'task-status',
|
|
232
|
+
command: 'node dist/cli/main.js task status --json',
|
|
233
|
+
args: ['task', 'status', '--json'],
|
|
194
234
|
reason: 'Choose the next task before requesting task-scoped context.'
|
|
195
235
|
});
|
|
196
236
|
}
|
|
197
237
|
else {
|
|
198
238
|
primaryAction = {
|
|
199
|
-
id: 'task-
|
|
200
|
-
label: 'Inspect task
|
|
201
|
-
command: `node dist/cli/main.js task
|
|
202
|
-
args: ['task', '
|
|
203
|
-
reason: 'A task id is available, so the fastest safe first step is to inspect
|
|
239
|
+
id: 'task-status',
|
|
240
|
+
label: 'Inspect task loop phase',
|
|
241
|
+
command: `node dist/cli/main.js task status --task ${taskId} --json`,
|
|
242
|
+
args: ['task', 'status', '--task', taskId, '--json'],
|
|
243
|
+
reason: 'A task id is available, so the fastest safe first step is to inspect loop phase, blockers, and the primary next action before editing files.',
|
|
204
244
|
writeBoundary: 'read-only',
|
|
205
245
|
recommendedActorRole: 'agent-worker'
|
|
206
246
|
};
|
|
207
|
-
commands.push({
|
|
208
|
-
id: 'task-lifecycle',
|
|
209
|
-
command: `node dist/cli/main.js task lifecycle --task ${taskId} --json`,
|
|
210
|
-
args: ['task', 'lifecycle', '--task', taskId, '--json'],
|
|
211
|
-
reason: 'Inspect the task phase and the one primary lifecycle next action before editing.'
|
|
212
|
-
});
|
|
213
247
|
commands.push({
|
|
214
248
|
id: 'task-status',
|
|
215
249
|
command: `node dist/cli/main.js task status --task ${taskId} --json`,
|
|
216
250
|
args: ['task', 'status', '--task', taskId, '--json'],
|
|
217
|
-
reason: 'Inspect task readiness, evidence, and
|
|
251
|
+
reason: 'Inspect task readiness, evidence, loop phase, and the primary next action.'
|
|
218
252
|
});
|
|
219
253
|
commands.push({
|
|
220
254
|
id: 'context-pack',
|
|
@@ -222,6 +256,12 @@ function guidanceForSessionStart(input) {
|
|
|
222
256
|
args: ['context', 'pack', '--task', taskId, '--json'],
|
|
223
257
|
reason: 'Inspect the bounded task read plan without slicing raw source text.'
|
|
224
258
|
});
|
|
259
|
+
commands.push({
|
|
260
|
+
id: 'docs-read-map',
|
|
261
|
+
command: `node dist/cli/main.js docs read-map --task ${taskId} --json`,
|
|
262
|
+
args: ['docs', 'read-map', '--task', taskId, '--json'],
|
|
263
|
+
reason: 'Inspect registry-backed task reading guidance and drift warnings before broad manual reads.'
|
|
264
|
+
});
|
|
225
265
|
}
|
|
226
266
|
commands.push({
|
|
227
267
|
id: 'cache-warm',
|
|
@@ -278,7 +318,7 @@ function buildBoundedContextPackReport(input) {
|
|
|
278
318
|
severity: 'warning',
|
|
279
319
|
code: 'CONTEXT_PACK_TASK_NOT_FOUND',
|
|
280
320
|
message: 'No task id was supplied. Bounded session start returned task-selection guidance without running live project discovery.',
|
|
281
|
-
fixHint: 'Run hadara task
|
|
321
|
+
fixHint: 'Run hadara task status --json, then rerun hadara session start --task <task-id> --json.'
|
|
282
322
|
}];
|
|
283
323
|
const readFirst = input.taskId
|
|
284
324
|
? [{
|
|
@@ -138,8 +138,9 @@ function readTaskStatus(content) {
|
|
|
138
138
|
const sectionStatus = (0, markdown_table_1.readMarkdownSection)(content, '## Status').trim().split(/\r?\n/)[0]?.trim();
|
|
139
139
|
if (sectionStatus)
|
|
140
140
|
return sectionStatus;
|
|
141
|
-
const
|
|
142
|
-
|
|
141
|
+
const identityRows = (0, markdown_table_1.parseMarkdownRowsUnderHeading)(content, '## Identity');
|
|
142
|
+
const metadataRows = (0, markdown_table_1.parseMarkdownRowsUnderHeading)(content, '## Metadata');
|
|
143
|
+
return (0, markdown_table_1.findMarkdownRowByCell)(identityRows, 0, 'Status')?.[1] ?? (0, markdown_table_1.findMarkdownRowByCell)(metadataRows, 0, 'Status')?.[1] ?? null;
|
|
143
144
|
}
|
|
144
145
|
function readTaskHandoffStatus(content) {
|
|
145
146
|
const rows = (0, markdown_table_1.parseMarkdownRowsUnderHeading)(content, '## Current State');
|
package/dist/core/schema.js
CHANGED
|
@@ -12,6 +12,7 @@ const actor_context_schema_json_1 = __importDefault(require("../schemas/actor-co
|
|
|
12
12
|
const active_run_projection_schema_json_1 = __importDefault(require("../schemas/active-run-projection.schema.json"));
|
|
13
13
|
const active_run_resume_schema_json_1 = __importDefault(require("../schemas/active-run-resume.schema.json"));
|
|
14
14
|
const clean_checkout_smoke_schema_json_1 = __importDefault(require("../schemas/clean-checkout-smoke.schema.json"));
|
|
15
|
+
const close_source_schema_json_1 = __importDefault(require("../schemas/close-source.schema.json"));
|
|
15
16
|
const code_index_schema_json_1 = __importDefault(require("../schemas/code-index.schema.json"));
|
|
16
17
|
const context_cache_record_schema_json_1 = __importDefault(require("../schemas/context-cache-record.schema.json"));
|
|
17
18
|
const context_cache_status_schema_json_1 = __importDefault(require("../schemas/context-cache-status.schema.json"));
|
|
@@ -29,13 +30,17 @@ const dev_docker_check_schema_json_1 = __importDefault(require("../schemas/dev-d
|
|
|
29
30
|
const docs_archive_plan_schema_json_1 = __importDefault(require("../schemas/docs-archive-plan.schema.json"));
|
|
30
31
|
const docs_doctor_schema_json_1 = __importDefault(require("../schemas/docs-doctor.schema.json"));
|
|
31
32
|
const docs_explain_schema_json_1 = __importDefault(require("../schemas/docs-explain.schema.json"));
|
|
33
|
+
const docs_inbox_schema_json_1 = __importDefault(require("../schemas/docs-inbox.schema.json"));
|
|
32
34
|
const docs_list_schema_json_1 = __importDefault(require("../schemas/docs-list.schema.json"));
|
|
33
35
|
const docs_mark_schema_json_1 = __importDefault(require("../schemas/docs-mark.schema.json"));
|
|
34
36
|
const docs_patch_plan_schema_json_1 = __importDefault(require("../schemas/docs-patch-plan.schema.json"));
|
|
37
|
+
const docs_read_map_schema_json_1 = __importDefault(require("../schemas/docs-read-map.schema.json"));
|
|
38
|
+
const docs_register_schema_json_1 = __importDefault(require("../schemas/docs-register.schema.json"));
|
|
35
39
|
const docs_required_reading_schema_json_1 = __importDefault(require("../schemas/docs-required-reading.schema.json"));
|
|
36
40
|
const evidence_lint_schema_json_1 = __importDefault(require("../schemas/evidence-lint.schema.json"));
|
|
37
41
|
const evidence_list_schema_json_1 = __importDefault(require("../schemas/evidence-list.schema.json"));
|
|
38
42
|
const evidence_migration_preview_schema_json_1 = __importDefault(require("../schemas/evidence-migration-preview.schema.json"));
|
|
43
|
+
const evidence_projection_schema_json_1 = __importDefault(require("../schemas/evidence-projection.schema.json"));
|
|
39
44
|
const evidence_summary_schema_json_1 = __importDefault(require("../schemas/evidence-summary.schema.json"));
|
|
40
45
|
const event_schema_json_1 = __importDefault(require("../schemas/event.schema.json"));
|
|
41
46
|
const feature_smoke_schema_json_1 = __importDefault(require("../schemas/feature-smoke.schema.json"));
|
|
@@ -74,9 +79,11 @@ const task_finish_schema_json_1 = __importDefault(require("../schemas/task-finis
|
|
|
74
79
|
const task_lifecycle_schema_json_1 = __importDefault(require("../schemas/task-lifecycle.schema.json"));
|
|
75
80
|
const task_next_schema_json_1 = __importDefault(require("../schemas/task-next.schema.json"));
|
|
76
81
|
const task_ready_schema_json_1 = __importDefault(require("../schemas/task-ready.schema.json"));
|
|
82
|
+
const task_status_schema_json_1 = __importDefault(require("../schemas/task-status.schema.json"));
|
|
77
83
|
const task_upgrade_scaffold_schema_json_1 = __importDefault(require("../schemas/task-upgrade-scaffold.schema.json"));
|
|
78
84
|
const task_workbench_schema_json_1 = __importDefault(require("../schemas/task-workbench.schema.json"));
|
|
79
85
|
const tools_list_schema_json_1 = __importDefault(require("../schemas/tools-list.schema.json"));
|
|
86
|
+
const validation_run_schema_json_1 = __importDefault(require("../schemas/validation-run.schema.json"));
|
|
80
87
|
const write_preflight_schema_json_1 = __importDefault(require("../schemas/write-preflight.schema.json"));
|
|
81
88
|
class SchemaValidationError extends Error {
|
|
82
89
|
schemaId;
|
|
@@ -96,6 +103,7 @@ const registeredSchemas = {
|
|
|
96
103
|
'hadara.active_run.projection.v1': active_run_projection_schema_json_1.default,
|
|
97
104
|
'hadara.active_run.resume.v1': active_run_resume_schema_json_1.default,
|
|
98
105
|
'hadara.cleanCheckoutSmoke.v1': clean_checkout_smoke_schema_json_1.default,
|
|
106
|
+
'hadara.closeSource.v1': close_source_schema_json_1.default,
|
|
99
107
|
'hadara.codeIndex.v1': code_index_schema_json_1.default,
|
|
100
108
|
'hadara.context.cacheRecord.v1': context_cache_record_schema_json_1.default,
|
|
101
109
|
'hadara.context.cacheStatus.v1': context_cache_status_schema_json_1.default,
|
|
@@ -113,13 +121,17 @@ const registeredSchemas = {
|
|
|
113
121
|
'hadara.docs.archivePlan.v1': docs_archive_plan_schema_json_1.default,
|
|
114
122
|
'hadara.docs.doctor.v1': docs_doctor_schema_json_1.default,
|
|
115
123
|
'hadara.docs.explain.v1': docs_explain_schema_json_1.default,
|
|
124
|
+
'hadara.docs.inbox.v1': docs_inbox_schema_json_1.default,
|
|
116
125
|
'hadara.docs.list.v1': docs_list_schema_json_1.default,
|
|
117
126
|
'hadara.docs.mark.v1': docs_mark_schema_json_1.default,
|
|
118
127
|
'hadara.docs.patchPlan.v1': docs_patch_plan_schema_json_1.default,
|
|
128
|
+
'hadara.docs.readMap.v1': docs_read_map_schema_json_1.default,
|
|
129
|
+
'hadara.docs.register.v1': docs_register_schema_json_1.default,
|
|
119
130
|
'hadara.docs.requiredReading.v1': docs_required_reading_schema_json_1.default,
|
|
120
131
|
'hadara.evidence.lint.v1': evidence_lint_schema_json_1.default,
|
|
121
132
|
'hadara.evidence.list.v1': evidence_list_schema_json_1.default,
|
|
122
133
|
'hadara.evidence.migration_preview.v1': evidence_migration_preview_schema_json_1.default,
|
|
134
|
+
'hadara.evidence.projection.v1': evidence_projection_schema_json_1.default,
|
|
123
135
|
'hadara.evidence.summary.v1': evidence_summary_schema_json_1.default,
|
|
124
136
|
'hadara.event.v1': event_schema_json_1.default,
|
|
125
137
|
'hadara.featureSmoke.v1': feature_smoke_schema_json_1.default,
|
|
@@ -158,9 +170,11 @@ const registeredSchemas = {
|
|
|
158
170
|
'hadara.task.lifecycle.v1': task_lifecycle_schema_json_1.default,
|
|
159
171
|
'hadara.task.next.v1': task_next_schema_json_1.default,
|
|
160
172
|
'hadara.task.ready.v1': task_ready_schema_json_1.default,
|
|
173
|
+
'hadara.task.status.v1': task_status_schema_json_1.default,
|
|
161
174
|
'hadara.task.upgrade_scaffold.v1': task_upgrade_scaffold_schema_json_1.default,
|
|
162
175
|
'hadara.task.workbench.v1': task_workbench_schema_json_1.default,
|
|
163
176
|
'hadara.tools.list.v1': tools_list_schema_json_1.default,
|
|
177
|
+
'hadara.validation.run.v1': validation_run_schema_json_1.default,
|
|
164
178
|
'hadara.write.preflight.v1': write_preflight_schema_json_1.default
|
|
165
179
|
};
|
|
166
180
|
function loadSchema(schemaId) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.startMonotonicTimer = startMonotonicTimer;
|
|
4
|
+
const node_perf_hooks_1 = require("node:perf_hooks");
|
|
5
|
+
function startMonotonicTimer(now = () => node_perf_hooks_1.performance.now()) {
|
|
6
|
+
const started = now();
|
|
7
|
+
return {
|
|
8
|
+
elapsedMs() {
|
|
9
|
+
return Math.max(0, Math.round(now() - started));
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
}
|
package/dist/dev/docker-check.js
CHANGED
|
@@ -9,6 +9,7 @@ const node_child_process_1 = require("node:child_process");
|
|
|
9
9
|
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
10
10
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
11
11
|
const node_path_1 = __importDefault(require("node:path"));
|
|
12
|
+
const timing_1 = require("../core/timing");
|
|
12
13
|
const lifecycle_next_actions_1 = require("../task/lifecycle-next-actions");
|
|
13
14
|
function createDevDockerCheckReport(projectRoot, options = {}, runner = defaultRunner) {
|
|
14
15
|
const focusedTests = normalizeFocusedTests(options.focusedTests ?? []);
|
|
@@ -47,9 +48,9 @@ function createDevDockerCheckReport(projectRoot, options = {}, runner = defaultR
|
|
|
47
48
|
steps.push({ id: step.id, status: 'skipped', summary: step.runWhen ? 'Skipped because an earlier step failed.' : step.summary });
|
|
48
49
|
continue;
|
|
49
50
|
}
|
|
50
|
-
const
|
|
51
|
+
const timer = (0, timing_1.startMonotonicTimer)();
|
|
51
52
|
const result = runner.run('docker', dockerExecArgs(container, step.script), env);
|
|
52
|
-
const elapsedMs =
|
|
53
|
+
const elapsedMs = timer.elapsedMs();
|
|
53
54
|
if (result.ok) {
|
|
54
55
|
steps.push({ id: step.id, status: 'passed', elapsedMs, summary: step.summary });
|
|
55
56
|
if (step.mark)
|