@aionis/manifest 0.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.
- package/CHANGELOG.md +26 -0
- package/LICENSE +178 -0
- package/README.md +170 -0
- package/dist/ast/types.d.ts +34 -0
- package/dist/ast/types.js +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +122 -0
- package/dist/compile.d.ts +14 -0
- package/dist/compile.js +219 -0
- package/dist/contracts.d.ts +12610 -0
- package/dist/contracts.js +401 -0
- package/dist/diagnostics/types.d.ts +17 -0
- package/dist/diagnostics/types.js +1 -0
- package/dist/execute/localRuntime.d.ts +5 -0
- package/dist/execute/localRuntime.js +165 -0
- package/dist/execute/moduleRuntime.d.ts +25 -0
- package/dist/execute/moduleRuntime.js +352 -0
- package/dist/execute/types.d.ts +113 -0
- package/dist/execute/types.js +1 -0
- package/dist/execute-cli.d.ts +2 -0
- package/dist/execute-cli.js +112 -0
- package/dist/execute.d.ts +6 -0
- package/dist/execute.js +46 -0
- package/dist/graph/buildExecutionGraph.d.ts +8 -0
- package/dist/graph/buildExecutionGraph.js +69 -0
- package/dist/graph/types.d.ts +24 -0
- package/dist/graph/types.js +1 -0
- package/dist/handoff-store-cli.d.ts +2 -0
- package/dist/handoff-store-cli.js +139 -0
- package/dist/handoff-store.d.ts +103 -0
- package/dist/handoff-store.js +78 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +21 -0
- package/dist/ir/types.d.ts +92 -0
- package/dist/ir/types.js +1 -0
- package/dist/parser/parseAst.d.ts +3 -0
- package/dist/parser/parseAst.js +207 -0
- package/dist/parser/payload.d.ts +6 -0
- package/dist/parser/payload.js +211 -0
- package/dist/plan/buildExecutionPlan.d.ts +9 -0
- package/dist/plan/buildExecutionPlan.js +98 -0
- package/dist/plan/types.d.ts +44 -0
- package/dist/plan/types.js +1 -0
- package/dist/publish-cli.d.ts +2 -0
- package/dist/publish-cli.js +249 -0
- package/dist/publish.d.ts +148 -0
- package/dist/publish.js +190 -0
- package/dist/recover-cli.d.ts +2 -0
- package/dist/recover-cli.js +258 -0
- package/dist/recover.d.ts +489 -0
- package/dist/recover.js +290 -0
- package/dist/refs/resolveRefs.d.ts +13 -0
- package/dist/refs/resolveRefs.js +104 -0
- package/dist/registry/loadModuleRegistry.d.ts +28 -0
- package/dist/registry/loadModuleRegistry.js +97 -0
- package/dist/registry/types.d.ts +20 -0
- package/dist/registry/types.js +2 -0
- package/dist/resume-cli.d.ts +2 -0
- package/dist/resume-cli.js +379 -0
- package/dist/resume.d.ts +2076 -0
- package/dist/resume.js +452 -0
- package/dist/run-cli.d.ts +2 -0
- package/dist/run-cli.js +119 -0
- package/dist/run.d.ts +9 -0
- package/dist/run.js +43 -0
- package/dist/runtime-handoff-cli.d.ts +2 -0
- package/dist/runtime-handoff-cli.js +179 -0
- package/dist/runtime-handoff.d.ts +914 -0
- package/dist/runtime-handoff.js +383 -0
- package/dist/scanner/scanSource.d.ts +9 -0
- package/dist/scanner/scanSource.js +43 -0
- package/dist/schema/validateIrSchemas.d.ts +3 -0
- package/dist/schema/validateIrSchemas.js +64 -0
- package/dist/validate-module-cli.d.ts +2 -0
- package/dist/validate-module-cli.js +93 -0
- package/dist/validate-registry-cli.d.ts +2 -0
- package/dist/validate-registry-cli.js +82 -0
- package/dist/validate.d.ts +52 -0
- package/dist/validate.js +91 -0
- package/fixtures/duplicate-doc.aionis.md +19 -0
- package/fixtures/fenced-example.aionis.md +27 -0
- package/fixtures/malformed-payload.aionis.md +9 -0
- package/fixtures/npm-installed-module-registry.json +17 -0
- package/fixtures/standalone-module-registry.json +13 -0
- package/fixtures/standalone-runner-plan.json +51 -0
- package/fixtures/standalone-runner.aionis.md +29 -0
- package/fixtures/unresolved-ref.aionis.md +14 -0
- package/fixtures/valid-minimal.aionis.md +24 -0
- package/fixtures/valid-workflow.aionis.md +29 -0
- package/official-modules/copy-summary/CHANGELOG.md +6 -0
- package/official-modules/copy-summary/README.md +43 -0
- package/official-modules/copy-summary/index.mjs +41 -0
- package/official-modules/copy-summary/package.json +31 -0
- package/official-modules/json-transform/CHANGELOG.md +6 -0
- package/official-modules/json-transform/README.md +51 -0
- package/official-modules/json-transform/index.mjs +53 -0
- package/official-modules/json-transform/package.json +31 -0
- package/official-modules/research-claims/CHANGELOG.md +6 -0
- package/official-modules/research-claims/README.md +47 -0
- package/official-modules/research-claims/index.mjs +44 -0
- package/official-modules/research-claims/package.json +31 -0
- package/package.json +74 -0
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { AIONIS_MANIFEST_COMPILE_RESULT_VERSION, AionisManifestCompileEnvelopeSchema, } from "./contracts.js";
|
|
3
|
+
import { buildExecutionPlanV1 } from "./plan/buildExecutionPlan.js";
|
|
4
|
+
export const AIONIS_MANIFEST_RUNTIME_HANDOFF_VERSION = "aionis_manifest_runtime_handoff_v1";
|
|
5
|
+
const RuntimeExecutionStageSchema = z.enum(["triage", "patch", "review", "resume"]);
|
|
6
|
+
const RuntimeExecutionRoleSchema = z.enum(["orchestrator", "triage", "patch", "review", "resume"]);
|
|
7
|
+
const RuntimeStringListSchema = z.array(z.string().min(1));
|
|
8
|
+
export const RuntimeReviewerContractSchema = z.object({
|
|
9
|
+
standard: z.string().trim().min(1),
|
|
10
|
+
required_outputs: RuntimeStringListSchema,
|
|
11
|
+
acceptance_checks: RuntimeStringListSchema,
|
|
12
|
+
rollback_required: z.boolean(),
|
|
13
|
+
});
|
|
14
|
+
export const RuntimeResumeAnchorSchema = z.object({
|
|
15
|
+
anchor: z.string().trim().min(1),
|
|
16
|
+
file_path: z.string().trim().min(1).nullable(),
|
|
17
|
+
symbol: z.string().trim().min(1).nullable(),
|
|
18
|
+
repo_root: z.string().trim().min(1).nullable(),
|
|
19
|
+
});
|
|
20
|
+
export const RuntimeExecutionStateSchema = z.object({
|
|
21
|
+
state_id: z.string().trim().min(1),
|
|
22
|
+
scope: z.string().trim().min(1),
|
|
23
|
+
task_brief: z.string().trim().min(1),
|
|
24
|
+
current_stage: RuntimeExecutionStageSchema,
|
|
25
|
+
active_role: RuntimeExecutionRoleSchema,
|
|
26
|
+
owned_files: z.array(z.string()),
|
|
27
|
+
modified_files: z.array(z.string()),
|
|
28
|
+
pending_validations: z.array(z.string()),
|
|
29
|
+
completed_validations: z.array(z.string()),
|
|
30
|
+
last_accepted_hypothesis: z.string().trim().min(1).nullable(),
|
|
31
|
+
rejected_paths: z.array(z.string()),
|
|
32
|
+
unresolved_blockers: z.array(z.string()),
|
|
33
|
+
rollback_notes: z.array(z.string()),
|
|
34
|
+
reviewer_contract: RuntimeReviewerContractSchema.nullable(),
|
|
35
|
+
resume_anchor: RuntimeResumeAnchorSchema.nullable(),
|
|
36
|
+
updated_at: z.string().min(1),
|
|
37
|
+
version: z.literal(1),
|
|
38
|
+
});
|
|
39
|
+
export const RuntimeExecutionPacketSchema = z.object({
|
|
40
|
+
version: z.literal(1),
|
|
41
|
+
state_id: z.string().trim().min(1),
|
|
42
|
+
current_stage: RuntimeExecutionStageSchema,
|
|
43
|
+
active_role: RuntimeExecutionRoleSchema,
|
|
44
|
+
task_brief: z.string().trim().min(1),
|
|
45
|
+
target_files: z.array(z.string()),
|
|
46
|
+
next_action: z.string().trim().min(1).nullable(),
|
|
47
|
+
hard_constraints: z.array(z.string()),
|
|
48
|
+
accepted_facts: z.array(z.string()),
|
|
49
|
+
rejected_paths: z.array(z.string()),
|
|
50
|
+
pending_validations: z.array(z.string()),
|
|
51
|
+
unresolved_blockers: z.array(z.string()),
|
|
52
|
+
rollback_notes: z.array(z.string()),
|
|
53
|
+
review_contract: RuntimeReviewerContractSchema.nullable(),
|
|
54
|
+
resume_anchor: RuntimeResumeAnchorSchema.nullable(),
|
|
55
|
+
artifact_refs: z.array(z.string()),
|
|
56
|
+
evidence_refs: z.array(z.string()),
|
|
57
|
+
});
|
|
58
|
+
export const RuntimeExecutionReadyHandoffSchema = z.object({
|
|
59
|
+
anchor: z.string().trim().min(1),
|
|
60
|
+
handoff_kind: z.literal("task_handoff"),
|
|
61
|
+
summary: z.string().trim().min(1).nullable(),
|
|
62
|
+
handoff_text: z.string().trim().min(1),
|
|
63
|
+
acceptance_checks: z.array(z.string()),
|
|
64
|
+
target_files: z.array(z.string()),
|
|
65
|
+
next_action: z.string().trim().min(1).nullable(),
|
|
66
|
+
});
|
|
67
|
+
export const RuntimeGraphSummarySchema = z.object({
|
|
68
|
+
graph_id: z.string().trim().min(1).nullable(),
|
|
69
|
+
execution_count: z.number().int().nonnegative(),
|
|
70
|
+
graph_node_count: z.number().int().nonnegative(),
|
|
71
|
+
graph_edge_count: z.number().int().nonnegative(),
|
|
72
|
+
module_refs: z.array(z.string()),
|
|
73
|
+
output_refs: z.array(z.string()),
|
|
74
|
+
expected_outputs: z.array(z.string()),
|
|
75
|
+
artifact_count: z.number().int().nonnegative(),
|
|
76
|
+
evidence_count: z.number().int().nonnegative(),
|
|
77
|
+
});
|
|
78
|
+
export const RuntimeExecutionArtifactSchema = z.object({
|
|
79
|
+
ref: z.string().trim().min(1),
|
|
80
|
+
execution_id: z.string().trim().min(1),
|
|
81
|
+
module: z.string().trim().min(1).optional(),
|
|
82
|
+
value: z.unknown(),
|
|
83
|
+
});
|
|
84
|
+
export const RuntimeExecutionEvidenceSchema = z.object({
|
|
85
|
+
ref: z.string().trim().min(1),
|
|
86
|
+
execution_id: z.string().trim().min(1),
|
|
87
|
+
module: z.string().trim().min(1).optional(),
|
|
88
|
+
value: z.unknown(),
|
|
89
|
+
});
|
|
90
|
+
export const RuntimeExecutionResultSummarySchema = z.object({
|
|
91
|
+
runtime_id: z.string().trim().min(1),
|
|
92
|
+
status: z.enum(["success", "failed"]),
|
|
93
|
+
output_refs: z.array(z.string()),
|
|
94
|
+
artifact_count: z.number().int().nonnegative(),
|
|
95
|
+
evidence_count: z.number().int().nonnegative(),
|
|
96
|
+
});
|
|
97
|
+
export const AionisManifestRuntimeHandoffSchema = z.object({
|
|
98
|
+
runtime_handoff_version: z.literal(AIONIS_MANIFEST_RUNTIME_HANDOFF_VERSION),
|
|
99
|
+
source_compile_result_version: z.literal(AIONIS_MANIFEST_COMPILE_RESULT_VERSION),
|
|
100
|
+
generated_at: z.string().min(1),
|
|
101
|
+
source_doc_id: z.string().trim().min(1),
|
|
102
|
+
source_doc_version: z.string().trim().min(1),
|
|
103
|
+
scope: z.string().trim().min(1),
|
|
104
|
+
task_brief: z.string().trim().min(1),
|
|
105
|
+
graph_summary: RuntimeGraphSummarySchema,
|
|
106
|
+
execution_result_summary: RuntimeExecutionResultSummarySchema.nullable(),
|
|
107
|
+
execution_artifacts: z.array(RuntimeExecutionArtifactSchema),
|
|
108
|
+
execution_evidence: z.array(RuntimeExecutionEvidenceSchema),
|
|
109
|
+
execution_state_v1: RuntimeExecutionStateSchema,
|
|
110
|
+
execution_packet_v1: RuntimeExecutionPacketSchema,
|
|
111
|
+
execution_ready_handoff: RuntimeExecutionReadyHandoffSchema,
|
|
112
|
+
});
|
|
113
|
+
export class AionisManifestRuntimeHandoffError extends Error {
|
|
114
|
+
constructor(message) {
|
|
115
|
+
super(message);
|
|
116
|
+
this.name = "AionisManifestRuntimeHandoffError";
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function inferTaskBrief(result) {
|
|
120
|
+
const title = result.ir.doc?.title?.trim();
|
|
121
|
+
if (title)
|
|
122
|
+
return title;
|
|
123
|
+
const objective = result.ir.context.find((entry) => typeof entry.objective === "string" && entry.objective.trim().length > 0)?.objective?.trim();
|
|
124
|
+
if (objective)
|
|
125
|
+
return objective;
|
|
126
|
+
if (result.ir.doc?.kind)
|
|
127
|
+
return `Execute AionisManifest ${result.ir.doc.kind}`;
|
|
128
|
+
return `Execute AionisManifest ${result.ir.doc?.id ?? "unknown"}`;
|
|
129
|
+
}
|
|
130
|
+
function inferStage(result) {
|
|
131
|
+
if (result.ir.executions.length > 0)
|
|
132
|
+
return "patch";
|
|
133
|
+
return "triage";
|
|
134
|
+
}
|
|
135
|
+
function inferRole(stage) {
|
|
136
|
+
if (stage === "patch")
|
|
137
|
+
return "patch";
|
|
138
|
+
if (stage === "review")
|
|
139
|
+
return "review";
|
|
140
|
+
if (stage === "resume")
|
|
141
|
+
return "resume";
|
|
142
|
+
return "triage";
|
|
143
|
+
}
|
|
144
|
+
function collectContextConstraints(result) {
|
|
145
|
+
return result.ir.context.flatMap((entry) => entry.constraints ?? []);
|
|
146
|
+
}
|
|
147
|
+
function collectExpectedOutputs(result) {
|
|
148
|
+
return result.ir.replay.flatMap((entry) => entry.expected_outputs ?? []);
|
|
149
|
+
}
|
|
150
|
+
function collectEvidenceRefs(result) {
|
|
151
|
+
const refs = [];
|
|
152
|
+
for (const evidence of result.ir.evidence) {
|
|
153
|
+
for (const source of evidence.sources ?? []) {
|
|
154
|
+
if (!source || typeof source !== "object" || Array.isArray(source))
|
|
155
|
+
continue;
|
|
156
|
+
const ref = "ref" in source && typeof source.ref === "string"
|
|
157
|
+
? String(source.ref)
|
|
158
|
+
: null;
|
|
159
|
+
if (ref)
|
|
160
|
+
refs.push(ref);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return refs;
|
|
164
|
+
}
|
|
165
|
+
function buildExecutionArtifactRecords(executionResult) {
|
|
166
|
+
const records = executionResult?.artifacts ?? [];
|
|
167
|
+
return records.map((record, index) => RuntimeExecutionArtifactSchema.parse({
|
|
168
|
+
ref: `artifact:${record.execution_id}:${index + 1}`,
|
|
169
|
+
execution_id: record.execution_id,
|
|
170
|
+
module: record.module,
|
|
171
|
+
value: record.value,
|
|
172
|
+
}));
|
|
173
|
+
}
|
|
174
|
+
function buildExecutionEvidenceRecords(executionResult) {
|
|
175
|
+
const records = executionResult?.evidence ?? [];
|
|
176
|
+
return records.map((record, index) => RuntimeExecutionEvidenceSchema.parse({
|
|
177
|
+
ref: `evidence:${record.execution_id}:${index + 1}`,
|
|
178
|
+
execution_id: record.execution_id,
|
|
179
|
+
module: record.module,
|
|
180
|
+
value: record.value,
|
|
181
|
+
}));
|
|
182
|
+
}
|
|
183
|
+
function collectModuleRefs(result) {
|
|
184
|
+
return result.ir.executions.flatMap((entry) => (entry.module ? [entry.module] : []));
|
|
185
|
+
}
|
|
186
|
+
function collectOutputRefs(result) {
|
|
187
|
+
return result.ir.executions.flatMap((entry) => (entry.output_ref ? [entry.output_ref] : []));
|
|
188
|
+
}
|
|
189
|
+
function collectAcceptedFacts(result) {
|
|
190
|
+
const facts = new Set();
|
|
191
|
+
if (result.ir.doc?.id)
|
|
192
|
+
facts.add(`doc_id:${result.ir.doc.id}`);
|
|
193
|
+
if (result.ir.doc?.version)
|
|
194
|
+
facts.add(`doc_version:${result.ir.doc.version}`);
|
|
195
|
+
for (const moduleRef of collectModuleRefs(result)) {
|
|
196
|
+
facts.add(`module:${moduleRef}`);
|
|
197
|
+
}
|
|
198
|
+
for (const outputRef of collectOutputRefs(result)) {
|
|
199
|
+
facts.add(`output_ref:${outputRef}`);
|
|
200
|
+
}
|
|
201
|
+
for (const decision of result.ir.decisions) {
|
|
202
|
+
if (decision.decision)
|
|
203
|
+
facts.add(`decision:${decision.decision}`);
|
|
204
|
+
}
|
|
205
|
+
return [...facts];
|
|
206
|
+
}
|
|
207
|
+
function inferNextAction(result, expectedOutputs) {
|
|
208
|
+
if (expectedOutputs.length > 0) {
|
|
209
|
+
return `Produce expected outputs: ${expectedOutputs.join(" | ")}`;
|
|
210
|
+
}
|
|
211
|
+
const firstModule = result.ir.executions.find((entry) => entry.module)?.module;
|
|
212
|
+
if (firstModule) {
|
|
213
|
+
return `Execute module chain starting with ${firstModule}`;
|
|
214
|
+
}
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
function buildReviewerContract(result, expectedOutputs, acceptanceChecks) {
|
|
218
|
+
if (expectedOutputs.length === 0 && acceptanceChecks.length === 0) {
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
return RuntimeReviewerContractSchema.parse({
|
|
222
|
+
standard: "aionis_manifest_runtime_handoff_v1",
|
|
223
|
+
required_outputs: expectedOutputs,
|
|
224
|
+
acceptance_checks: acceptanceChecks,
|
|
225
|
+
rollback_required: false,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
function ensureRunnable(result, requireErrorFree) {
|
|
229
|
+
if (!result.ir.doc) {
|
|
230
|
+
throw new AionisManifestRuntimeHandoffError("Runtime handoff requires a compiled manifest with @manifest metadata. Legacy @doc is still accepted.");
|
|
231
|
+
}
|
|
232
|
+
if (requireErrorFree && result.diagnostics.some((diagnostic) => diagnostic.severity === "error")) {
|
|
233
|
+
throw new AionisManifestRuntimeHandoffError("Runtime handoff requires an error-free compile result.");
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
export function buildRuntimeHandoffV1(args) {
|
|
237
|
+
const scope = args.scope?.trim() || "default";
|
|
238
|
+
const generatedAt = args.generatedAt ?? new Date().toISOString();
|
|
239
|
+
const requireErrorFree = args.requireErrorFree ?? true;
|
|
240
|
+
ensureRunnable(args.result, requireErrorFree);
|
|
241
|
+
const doc = args.result.ir.doc;
|
|
242
|
+
const taskBrief = inferTaskBrief(args.result);
|
|
243
|
+
const currentStage = args.currentStage ?? inferStage(args.result);
|
|
244
|
+
const activeRole = args.activeRole ?? inferRole(currentStage);
|
|
245
|
+
const expectedOutputs = collectExpectedOutputs(args.result);
|
|
246
|
+
const hardConstraints = collectContextConstraints(args.result);
|
|
247
|
+
const executionArtifacts = buildExecutionArtifactRecords(args.executionResult);
|
|
248
|
+
const executionEvidence = buildExecutionEvidenceRecords(args.executionResult);
|
|
249
|
+
const artifactRefs = executionArtifacts.map((record) => record.ref);
|
|
250
|
+
const evidenceRefs = [
|
|
251
|
+
...collectEvidenceRefs(args.result),
|
|
252
|
+
...executionEvidence.map((record) => record.ref),
|
|
253
|
+
];
|
|
254
|
+
const acceptedFacts = collectAcceptedFacts(args.result);
|
|
255
|
+
const nextAction = inferNextAction(args.result, expectedOutputs);
|
|
256
|
+
const reviewerContract = buildReviewerContract(args.result, expectedOutputs, hardConstraints);
|
|
257
|
+
const executionResultSummary = args.executionResult
|
|
258
|
+
? RuntimeExecutionResultSummarySchema.parse({
|
|
259
|
+
runtime_id: args.executionResult.runtime_id,
|
|
260
|
+
status: args.executionResult.status,
|
|
261
|
+
output_refs: Object.keys(args.executionResult.outputs),
|
|
262
|
+
artifact_count: executionArtifacts.length,
|
|
263
|
+
evidence_count: executionEvidence.length,
|
|
264
|
+
})
|
|
265
|
+
: null;
|
|
266
|
+
const stateId = `aionis-manifest:${doc.id}`;
|
|
267
|
+
const resumeAnchor = RuntimeResumeAnchorSchema.parse({
|
|
268
|
+
anchor: stateId,
|
|
269
|
+
file_path: args.filePath ?? null,
|
|
270
|
+
symbol: args.symbol ?? null,
|
|
271
|
+
repo_root: args.repoRoot ?? null,
|
|
272
|
+
});
|
|
273
|
+
const executionState = RuntimeExecutionStateSchema.parse({
|
|
274
|
+
state_id: stateId,
|
|
275
|
+
scope,
|
|
276
|
+
task_brief: taskBrief,
|
|
277
|
+
current_stage: currentStage,
|
|
278
|
+
active_role: activeRole,
|
|
279
|
+
owned_files: [],
|
|
280
|
+
modified_files: [],
|
|
281
|
+
pending_validations: expectedOutputs,
|
|
282
|
+
completed_validations: [],
|
|
283
|
+
last_accepted_hypothesis: null,
|
|
284
|
+
rejected_paths: [],
|
|
285
|
+
unresolved_blockers: [],
|
|
286
|
+
rollback_notes: [],
|
|
287
|
+
reviewer_contract: reviewerContract,
|
|
288
|
+
resume_anchor: resumeAnchor,
|
|
289
|
+
updated_at: generatedAt,
|
|
290
|
+
version: 1,
|
|
291
|
+
});
|
|
292
|
+
const executionPacket = RuntimeExecutionPacketSchema.parse({
|
|
293
|
+
version: 1,
|
|
294
|
+
state_id: stateId,
|
|
295
|
+
current_stage: currentStage,
|
|
296
|
+
active_role: activeRole,
|
|
297
|
+
task_brief: taskBrief,
|
|
298
|
+
target_files: [],
|
|
299
|
+
next_action: nextAction,
|
|
300
|
+
hard_constraints: hardConstraints,
|
|
301
|
+
accepted_facts: acceptedFacts,
|
|
302
|
+
rejected_paths: [],
|
|
303
|
+
pending_validations: expectedOutputs,
|
|
304
|
+
unresolved_blockers: [],
|
|
305
|
+
rollback_notes: [],
|
|
306
|
+
review_contract: reviewerContract,
|
|
307
|
+
resume_anchor: resumeAnchor,
|
|
308
|
+
artifact_refs: artifactRefs,
|
|
309
|
+
evidence_refs: evidenceRefs,
|
|
310
|
+
});
|
|
311
|
+
const executionReadyHandoff = RuntimeExecutionReadyHandoffSchema.parse({
|
|
312
|
+
anchor: stateId,
|
|
313
|
+
handoff_kind: "task_handoff",
|
|
314
|
+
summary: doc.title ?? taskBrief,
|
|
315
|
+
handoff_text: taskBrief,
|
|
316
|
+
acceptance_checks: reviewerContract?.acceptance_checks ?? [],
|
|
317
|
+
target_files: [],
|
|
318
|
+
next_action: nextAction,
|
|
319
|
+
});
|
|
320
|
+
return AionisManifestRuntimeHandoffSchema.parse({
|
|
321
|
+
runtime_handoff_version: AIONIS_MANIFEST_RUNTIME_HANDOFF_VERSION,
|
|
322
|
+
source_compile_result_version: AIONIS_MANIFEST_COMPILE_RESULT_VERSION,
|
|
323
|
+
generated_at: generatedAt,
|
|
324
|
+
source_doc_id: doc.id,
|
|
325
|
+
source_doc_version: doc.version,
|
|
326
|
+
scope,
|
|
327
|
+
task_brief: taskBrief,
|
|
328
|
+
graph_summary: {
|
|
329
|
+
graph_id: args.result.graph?.graph_id ?? null,
|
|
330
|
+
execution_count: args.result.ir.executions.length,
|
|
331
|
+
graph_node_count: args.result.graph?.nodes.length ?? 0,
|
|
332
|
+
graph_edge_count: args.result.graph?.edges.length ?? 0,
|
|
333
|
+
module_refs: collectModuleRefs(args.result),
|
|
334
|
+
output_refs: collectOutputRefs(args.result),
|
|
335
|
+
expected_outputs: expectedOutputs,
|
|
336
|
+
artifact_count: executionArtifacts.length,
|
|
337
|
+
evidence_count: executionEvidence.length,
|
|
338
|
+
},
|
|
339
|
+
execution_result_summary: executionResultSummary,
|
|
340
|
+
execution_artifacts: executionArtifacts,
|
|
341
|
+
execution_evidence: executionEvidence,
|
|
342
|
+
execution_state_v1: executionState,
|
|
343
|
+
execution_packet_v1: executionPacket,
|
|
344
|
+
execution_ready_handoff: executionReadyHandoff,
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
export function buildRuntimeHandoffV1FromEnvelope(args) {
|
|
348
|
+
const envelope = AionisManifestCompileEnvelopeSchema.parse(args.envelope);
|
|
349
|
+
if (!envelope.artifacts.ir) {
|
|
350
|
+
throw new AionisManifestRuntimeHandoffError(`Runtime handoff requires an envelope with IR artifacts. Re-run compile-aionis-manifest with --emit all or --emit ir; current selected_artifact is '${envelope.selected_artifact}'.`);
|
|
351
|
+
}
|
|
352
|
+
const result = compileResultFromEnvelope(envelope);
|
|
353
|
+
return buildRuntimeHandoffV1({
|
|
354
|
+
inputPath: envelope.input_path,
|
|
355
|
+
result,
|
|
356
|
+
...args,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
function compileResultFromEnvelope(envelope) {
|
|
360
|
+
const ir = envelope.artifacts.ir;
|
|
361
|
+
const graph = envelope.artifacts.graph;
|
|
362
|
+
return {
|
|
363
|
+
ast: (envelope.artifacts.ast ??
|
|
364
|
+
{
|
|
365
|
+
type: "DocumentNode",
|
|
366
|
+
children: [],
|
|
367
|
+
diagnostics: envelope.diagnostics,
|
|
368
|
+
loc: {
|
|
369
|
+
start: { line: 1, column: 1, offset: 0 },
|
|
370
|
+
end: { line: 1, column: 1, offset: 0 },
|
|
371
|
+
},
|
|
372
|
+
}),
|
|
373
|
+
ir,
|
|
374
|
+
graph,
|
|
375
|
+
plan: (envelope.artifacts.plan ??
|
|
376
|
+
buildExecutionPlanV1({
|
|
377
|
+
ir,
|
|
378
|
+
graph,
|
|
379
|
+
diagnostics: envelope.diagnostics,
|
|
380
|
+
})),
|
|
381
|
+
diagnostics: envelope.diagnostics,
|
|
382
|
+
};
|
|
383
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SourcePos, SourceRange } from "../diagnostics/types.js";
|
|
2
|
+
export interface ScanResult {
|
|
3
|
+
source: string;
|
|
4
|
+
lineStarts: number[];
|
|
5
|
+
}
|
|
6
|
+
export declare function scanSource(source: string): ScanResult;
|
|
7
|
+
export declare function findLineIndexAtOffset(scan: ScanResult, offset: number): number;
|
|
8
|
+
export declare function offsetToSourcePos(scan: ScanResult, offset: number): SourcePos;
|
|
9
|
+
export declare function rangeFromOffsets(scan: ScanResult, start: number, end: number): SourceRange;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export function scanSource(source) {
|
|
2
|
+
const lineStarts = [0];
|
|
3
|
+
for (let i = 0; i < source.length; i += 1) {
|
|
4
|
+
if (source[i] === "\n") {
|
|
5
|
+
lineStarts.push(i + 1);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
return { source, lineStarts };
|
|
9
|
+
}
|
|
10
|
+
export function findLineIndexAtOffset(scan, offset) {
|
|
11
|
+
let low = 0;
|
|
12
|
+
let high = scan.lineStarts.length - 1;
|
|
13
|
+
while (low <= high) {
|
|
14
|
+
const mid = Math.floor((low + high) / 2);
|
|
15
|
+
const start = scan.lineStarts[mid];
|
|
16
|
+
const next = mid + 1 < scan.lineStarts.length ? scan.lineStarts[mid + 1] : scan.source.length + 1;
|
|
17
|
+
if (offset < start) {
|
|
18
|
+
high = mid - 1;
|
|
19
|
+
}
|
|
20
|
+
else if (offset >= next) {
|
|
21
|
+
low = mid + 1;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
return mid;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return Math.max(0, scan.lineStarts.length - 1);
|
|
28
|
+
}
|
|
29
|
+
export function offsetToSourcePos(scan, offset) {
|
|
30
|
+
const safeOffset = Math.max(0, Math.min(offset, scan.source.length));
|
|
31
|
+
const lineIndex = findLineIndexAtOffset(scan, safeOffset);
|
|
32
|
+
return {
|
|
33
|
+
line: lineIndex + 1,
|
|
34
|
+
column: safeOffset - scan.lineStarts[lineIndex] + 1,
|
|
35
|
+
offset: safeOffset,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export function rangeFromOffsets(scan, start, end) {
|
|
39
|
+
return {
|
|
40
|
+
start: offsetToSourcePos(scan, start),
|
|
41
|
+
end: offsetToSourcePos(scan, end),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export function validateIrSchemas(ir) {
|
|
2
|
+
const diagnostics = [];
|
|
3
|
+
if (!ir.doc) {
|
|
4
|
+
diagnostics.push({
|
|
5
|
+
severity: "error",
|
|
6
|
+
code: "MISSING_MANIFEST",
|
|
7
|
+
message: "Manifest is missing a @manifest metadata directive. Legacy @doc is still accepted.",
|
|
8
|
+
loc: ir.executions[0]?.loc ?? ir.context[0]?.loc ?? ir.replay[0]?.loc ?? ir.diagnostics[0]?.loc ?? {
|
|
9
|
+
start: { line: 1, column: 1, offset: 0 },
|
|
10
|
+
end: { line: 1, column: 1, offset: 0 },
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
return diagnostics;
|
|
14
|
+
}
|
|
15
|
+
if (ir.doc.id.trim().length === 0) {
|
|
16
|
+
diagnostics.push({
|
|
17
|
+
severity: "error",
|
|
18
|
+
code: "INVALID_SCHEMA",
|
|
19
|
+
message: "@manifest.id must be a non-empty string.",
|
|
20
|
+
loc: ir.doc.loc ?? {
|
|
21
|
+
start: { line: 1, column: 1, offset: 0 },
|
|
22
|
+
end: { line: 1, column: 1, offset: 0 },
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
if (ir.doc.version.trim().length === 0) {
|
|
27
|
+
diagnostics.push({
|
|
28
|
+
severity: "error",
|
|
29
|
+
code: "INVALID_SCHEMA",
|
|
30
|
+
message: "@manifest.version must be a non-empty string.",
|
|
31
|
+
loc: ir.doc.loc ?? {
|
|
32
|
+
start: { line: 1, column: 1, offset: 0 },
|
|
33
|
+
end: { line: 1, column: 1, offset: 0 },
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
for (const execution of ir.executions) {
|
|
38
|
+
if (!execution.module && !execution.tool && !execution.agent) {
|
|
39
|
+
diagnostics.push({
|
|
40
|
+
severity: "error",
|
|
41
|
+
code: "INVALID_SCHEMA",
|
|
42
|
+
message: "@execute requires at least one of module, tool, or agent.",
|
|
43
|
+
loc: execution.loc ?? ir.doc.loc ?? {
|
|
44
|
+
start: { line: 1, column: 1, offset: 0 },
|
|
45
|
+
end: { line: 1, column: 1, offset: 0 },
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
for (const replay of ir.replay) {
|
|
51
|
+
if (replay.mode && !["deterministic", "assisted", "advisory"].includes(replay.mode)) {
|
|
52
|
+
diagnostics.push({
|
|
53
|
+
severity: "error",
|
|
54
|
+
code: "INVALID_SCHEMA",
|
|
55
|
+
message: `Unsupported replay mode '${replay.mode}'.`,
|
|
56
|
+
loc: replay.loc ?? ir.doc.loc ?? {
|
|
57
|
+
start: { line: 1, column: 1, offset: 0 },
|
|
58
|
+
end: { line: 1, column: 1, offset: 0 },
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return diagnostics;
|
|
64
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
import { resolveOutputPath, validateAionisManifestModule, writeValidationOutput } from "./validate.js";
|
|
4
|
+
class CliUsageError extends Error {
|
|
5
|
+
}
|
|
6
|
+
function printHelp() {
|
|
7
|
+
process.stdout.write([
|
|
8
|
+
"validate-aionis-manifest-module",
|
|
9
|
+
"",
|
|
10
|
+
"Usage:",
|
|
11
|
+
" validate-aionis-manifest-module <entry-file> [--declared-module <module>] [--out <path>] [--compact]",
|
|
12
|
+
"",
|
|
13
|
+
"Options:",
|
|
14
|
+
" --declared-module <module> Require the entry manifest to match the declared module id",
|
|
15
|
+
" --out <path> Write output JSON to a file instead of stdout",
|
|
16
|
+
" --compact Print compact JSON instead of pretty JSON",
|
|
17
|
+
" --help Show this message",
|
|
18
|
+
"",
|
|
19
|
+
].join("\n"));
|
|
20
|
+
}
|
|
21
|
+
function parseArgs(argv) {
|
|
22
|
+
let entryPath = null;
|
|
23
|
+
const flags = {
|
|
24
|
+
declaredModule: null,
|
|
25
|
+
out: null,
|
|
26
|
+
compact: false,
|
|
27
|
+
help: false,
|
|
28
|
+
};
|
|
29
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
30
|
+
const token = argv[i];
|
|
31
|
+
if (token === "--help" || token === "-h") {
|
|
32
|
+
flags.help = true;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (token === "--compact") {
|
|
36
|
+
flags.compact = true;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (token === "--declared-module") {
|
|
40
|
+
const next = argv[i + 1];
|
|
41
|
+
if (!next)
|
|
42
|
+
throw new CliUsageError("Missing value for --declared-module.");
|
|
43
|
+
flags.declaredModule = next;
|
|
44
|
+
i += 1;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (token === "--out") {
|
|
48
|
+
const next = argv[i + 1];
|
|
49
|
+
if (!next)
|
|
50
|
+
throw new CliUsageError("Missing value for --out.");
|
|
51
|
+
flags.out = next;
|
|
52
|
+
i += 1;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (token.startsWith("--"))
|
|
56
|
+
throw new CliUsageError(`Unknown flag '${token}'.`);
|
|
57
|
+
if (entryPath)
|
|
58
|
+
throw new CliUsageError("Only one entry file may be provided.");
|
|
59
|
+
entryPath = token;
|
|
60
|
+
}
|
|
61
|
+
return { entryPath, flags };
|
|
62
|
+
}
|
|
63
|
+
async function main() {
|
|
64
|
+
const { entryPath, flags } = parseArgs(process.argv.slice(2));
|
|
65
|
+
if (flags.help) {
|
|
66
|
+
printHelp();
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (!entryPath)
|
|
70
|
+
throw new CliUsageError("An entry file path is required.");
|
|
71
|
+
const result = await validateAionisManifestModule({
|
|
72
|
+
entryPath,
|
|
73
|
+
declaredModule: flags.declaredModule ?? undefined,
|
|
74
|
+
cwd: process.cwd(),
|
|
75
|
+
});
|
|
76
|
+
const rendered = flags.compact ? JSON.stringify(result) : `${JSON.stringify(result, null, 2)}\n`;
|
|
77
|
+
if (flags.out) {
|
|
78
|
+
await writeValidationOutput(resolveOutputPath(flags.out), rendered);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
process.stdout.write(rendered);
|
|
82
|
+
}
|
|
83
|
+
main().catch((error) => {
|
|
84
|
+
if (error instanceof CliUsageError) {
|
|
85
|
+
process.stderr.write(`${error.message}\n`);
|
|
86
|
+
printHelp();
|
|
87
|
+
process.exitCode = 2;
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
91
|
+
process.stderr.write(`${message}\n`);
|
|
92
|
+
process.exitCode = 1;
|
|
93
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import { resolveOutputPath, validateAionisManifestRegistry, writeValidationOutput } from "./validate.js";
|
|
5
|
+
class CliUsageError extends Error {
|
|
6
|
+
}
|
|
7
|
+
function printHelp() {
|
|
8
|
+
process.stdout.write([
|
|
9
|
+
"validate-aionis-manifest-registry",
|
|
10
|
+
"",
|
|
11
|
+
"Usage:",
|
|
12
|
+
" validate-aionis-manifest-registry <registry-file> [--out <path>] [--compact]",
|
|
13
|
+
"",
|
|
14
|
+
"Options:",
|
|
15
|
+
" --out <path> Write output JSON to a file instead of stdout",
|
|
16
|
+
" --compact Print compact JSON instead of pretty JSON",
|
|
17
|
+
" --help Show this message",
|
|
18
|
+
"",
|
|
19
|
+
].join("\n"));
|
|
20
|
+
}
|
|
21
|
+
function parseArgs(argv) {
|
|
22
|
+
let registryPath = null;
|
|
23
|
+
const flags = {
|
|
24
|
+
out: null,
|
|
25
|
+
compact: false,
|
|
26
|
+
help: false,
|
|
27
|
+
};
|
|
28
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
29
|
+
const token = argv[i];
|
|
30
|
+
if (token === "--help" || token === "-h") {
|
|
31
|
+
flags.help = true;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (token === "--compact") {
|
|
35
|
+
flags.compact = true;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (token === "--out") {
|
|
39
|
+
const next = argv[i + 1];
|
|
40
|
+
if (!next)
|
|
41
|
+
throw new CliUsageError("Missing value for --out.");
|
|
42
|
+
flags.out = next;
|
|
43
|
+
i += 1;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (token.startsWith("--"))
|
|
47
|
+
throw new CliUsageError(`Unknown flag '${token}'.`);
|
|
48
|
+
if (registryPath)
|
|
49
|
+
throw new CliUsageError("Only one registry file may be provided.");
|
|
50
|
+
registryPath = token;
|
|
51
|
+
}
|
|
52
|
+
return { registryPath, flags };
|
|
53
|
+
}
|
|
54
|
+
async function main() {
|
|
55
|
+
const { registryPath, flags } = parseArgs(process.argv.slice(2));
|
|
56
|
+
if (flags.help) {
|
|
57
|
+
printHelp();
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (!registryPath)
|
|
61
|
+
throw new CliUsageError("A registry file path is required.");
|
|
62
|
+
const result = await validateAionisManifestRegistry({
|
|
63
|
+
registryPath: resolve(process.cwd(), registryPath),
|
|
64
|
+
});
|
|
65
|
+
const rendered = flags.compact ? JSON.stringify(result) : `${JSON.stringify(result, null, 2)}\n`;
|
|
66
|
+
if (flags.out) {
|
|
67
|
+
await writeValidationOutput(resolveOutputPath(flags.out), rendered);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
process.stdout.write(rendered);
|
|
71
|
+
}
|
|
72
|
+
main().catch((error) => {
|
|
73
|
+
if (error instanceof CliUsageError) {
|
|
74
|
+
process.stderr.write(`${error.message}\n`);
|
|
75
|
+
printHelp();
|
|
76
|
+
process.exitCode = 2;
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
80
|
+
process.stderr.write(`${message}\n`);
|
|
81
|
+
process.exitCode = 1;
|
|
82
|
+
});
|