@hilbras/omninode 2.0.0-alpha.8 → 2.0.0-alpha.9
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 +10 -3
- package/dist/cli/index.js +122 -23
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +94 -17
- package/dist/index.js +117 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,9 +18,9 @@ existing intelligence; it does not try to become another model.
|
|
|
18
18
|
|
|
19
19
|
## Status
|
|
20
20
|
|
|
21
|
-
**v2.0.0-alpha.
|
|
21
|
+
**v2.0.0-alpha.9 — v2 Phase 9: Report System v2**
|
|
22
22
|
(the reliability & interoperability line: architecture → execution →
|
|
23
|
-
protocol → adapters → pipelines → providers → OmniHilbras → memory) (the v2
|
|
23
|
+
protocol → adapters → pipelines → providers → OmniHilbras → memory → reports) (the v2
|
|
24
24
|
roadmap is [docs/ROADMAP_V2.md](docs/ROADMAP_V2.md); the v1 plan is complete:
|
|
25
25
|
the
|
|
26
26
|
full loop from §28 runs in one command —
|
|
@@ -31,6 +31,13 @@ for the plan and [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the design).
|
|
|
31
31
|
|
|
32
32
|
### What's new in v2 (so far)
|
|
33
33
|
|
|
34
|
+
- **Phase 9 — Report System v2**: reports are validated machine-readable
|
|
35
|
+
objects — `validateReport()` runs on everything entering the system and
|
|
36
|
+
malformed reports are rejected with diagnostics instead of poisoning
|
|
37
|
+
aggregation. Findings gain description/confidence/source/recommendation,
|
|
38
|
+
evidence is typed (`file`, `line`, `url`, `command`, `observation`,
|
|
39
|
+
`artifact`), and reports carry artifacts and run provenance.
|
|
40
|
+
Details: [REPORTS.md](docs/REPORTS.md).
|
|
34
41
|
- **Phase 8 — Remembera / Memory v2**: the memory contract is formalized
|
|
35
42
|
(`retrieve` / `store` / `search` / `metadata` with v1 `query` / `write`
|
|
36
43
|
aliases kept working), memory gains structured **categories** (decisions,
|
|
@@ -339,7 +346,7 @@ required for the core engine.
|
|
|
339
346
|
- [Architecture](docs/ARCHITECTURE.md) — module map, workflow, local state
|
|
340
347
|
- [Security model](docs/SECURITY.md) — secrets, process execution, env isolation, audit log
|
|
341
348
|
- [API stability policy](docs/API_STABILITY.md) and [public API inventory](docs/API.md)
|
|
342
|
-
- [Agent Protocol v2 spec](docs/PROTOCOL.md) · [Providers](docs/PROVIDERS.md) · [Memory](docs/MEMORY.md) · [Deprecations](docs/DEPRECATIONS.md) · [Changelog](CHANGELOG.md) · [v2 roadmap](docs/ROADMAP_V2.md)
|
|
349
|
+
- [Agent Protocol v2 spec](docs/PROTOCOL.md) · [Providers](docs/PROVIDERS.md) · [Memory](docs/MEMORY.md) · [Reports](docs/REPORTS.md) · [Deprecations](docs/DEPRECATIONS.md) · [Changelog](CHANGELOG.md) · [v2 roadmap](docs/ROADMAP_V2.md)
|
|
343
350
|
- [Example project](examples/demo/) — a runnable end-to-end demo (`./demo.sh`)
|
|
344
351
|
|
|
345
352
|
Prefer a container? `docker build -t omninode .` then
|
package/dist/cli/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { realpathSync } from "fs";
|
|
|
6
6
|
import { Command } from "commander";
|
|
7
7
|
|
|
8
8
|
// src/version.ts
|
|
9
|
-
var OMNINODE_VERSION = "2.0.0-alpha.
|
|
9
|
+
var OMNINODE_VERSION = "2.0.0-alpha.9";
|
|
10
10
|
|
|
11
11
|
// src/errors/index.ts
|
|
12
12
|
var OmniNodeError = class extends Error {
|
|
@@ -2997,6 +2997,84 @@ function truncate2(text, max) {
|
|
|
2997
2997
|
|
|
2998
2998
|
// src/reports/aggregate.ts
|
|
2999
2999
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
3000
|
+
|
|
3001
|
+
// src/reports/schema.ts
|
|
3002
|
+
import { z as z2 } from "zod";
|
|
3003
|
+
var evidenceSchema = z2.union([
|
|
3004
|
+
z2.string().transform((excerpt) => ({ kind: "observation", excerpt })),
|
|
3005
|
+
z2.object({
|
|
3006
|
+
kind: z2.enum(["file", "line", "url", "command", "observation", "artifact"]),
|
|
3007
|
+
ref: z2.string().optional(),
|
|
3008
|
+
line: z2.number().int().optional(),
|
|
3009
|
+
excerpt: z2.string().optional(),
|
|
3010
|
+
agent: z2.string().optional()
|
|
3011
|
+
})
|
|
3012
|
+
]);
|
|
3013
|
+
var findingSchema = z2.object({
|
|
3014
|
+
id: z2.string().min(1),
|
|
3015
|
+
title: z2.string().min(1),
|
|
3016
|
+
detail: z2.string().default(""),
|
|
3017
|
+
description: z2.string().optional(),
|
|
3018
|
+
severity: z2.enum(["info", "low", "medium", "high", "critical"]).optional(),
|
|
3019
|
+
confidence: z2.enum(["low", "medium", "high"]).optional(),
|
|
3020
|
+
evidence: z2.array(evidenceSchema).optional(),
|
|
3021
|
+
location: z2.string().optional(),
|
|
3022
|
+
tags: z2.array(z2.string()).optional(),
|
|
3023
|
+
source: z2.object({ agent: z2.string().optional(), reportId: z2.string().optional(), pipelineRunId: z2.string().optional() }).optional(),
|
|
3024
|
+
recommendation: z2.string().optional()
|
|
3025
|
+
});
|
|
3026
|
+
var artifactSchema = z2.object({
|
|
3027
|
+
kind: z2.enum(["file", "patch", "log", "screenshot", "document", "data"]),
|
|
3028
|
+
ref: z2.string().min(1),
|
|
3029
|
+
description: z2.string().optional(),
|
|
3030
|
+
mediaType: z2.string().optional(),
|
|
3031
|
+
bytes: z2.number().int().optional()
|
|
3032
|
+
});
|
|
3033
|
+
var reportSchema = z2.object({
|
|
3034
|
+
id: z2.string().min(1),
|
|
3035
|
+
taskId: z2.string().min(1),
|
|
3036
|
+
agent: z2.string().min(1),
|
|
3037
|
+
agentId: z2.string().optional(),
|
|
3038
|
+
pipelineRunId: z2.string().optional(),
|
|
3039
|
+
model: z2.string().optional(),
|
|
3040
|
+
summary: z2.string(),
|
|
3041
|
+
findings: z2.array(findingSchema),
|
|
3042
|
+
recommendations: z2.array(z2.string()),
|
|
3043
|
+
confidence: z2.enum(["low", "medium", "high"]).optional(),
|
|
3044
|
+
evidence: z2.array(evidenceSchema).optional(),
|
|
3045
|
+
artifacts: z2.array(artifactSchema).optional(),
|
|
3046
|
+
createdAt: z2.string().min(1),
|
|
3047
|
+
metadata: z2.record(z2.unknown()).optional()
|
|
3048
|
+
});
|
|
3049
|
+
function validateReport(value) {
|
|
3050
|
+
const parsed = reportSchema.safeParse(value);
|
|
3051
|
+
if (!parsed.success) {
|
|
3052
|
+
const issues = parsed.error.issues.map((issue) => ({
|
|
3053
|
+
path: issue.path.join(".") || "(root)",
|
|
3054
|
+
message: issue.message
|
|
3055
|
+
}));
|
|
3056
|
+
return {
|
|
3057
|
+
valid: false,
|
|
3058
|
+
issues,
|
|
3059
|
+
reason: `report failed schema validation (${issues.length} issue(s))`
|
|
3060
|
+
};
|
|
3061
|
+
}
|
|
3062
|
+
const report = parsed.data;
|
|
3063
|
+
report.findings = report.findings.map((finding) => ({
|
|
3064
|
+
...finding,
|
|
3065
|
+
description: finding.description ?? finding.detail,
|
|
3066
|
+
...finding.source === void 0 ? { source: { agent: report.agent, reportId: report.id, ...report.pipelineRunId !== void 0 ? { pipelineRunId: report.pipelineRunId } : {} } } : {}
|
|
3067
|
+
}));
|
|
3068
|
+
return { valid: true, report };
|
|
3069
|
+
}
|
|
3070
|
+
function normalizeEvidence(input) {
|
|
3071
|
+
if (input === void 0) return void 0;
|
|
3072
|
+
return input.map(
|
|
3073
|
+
(item) => typeof item === "string" ? { kind: "observation", excerpt: item } : item
|
|
3074
|
+
);
|
|
3075
|
+
}
|
|
3076
|
+
|
|
3077
|
+
// src/reports/aggregate.ts
|
|
3000
3078
|
var SEVERITY_RANK = {
|
|
3001
3079
|
info: 0,
|
|
3002
3080
|
low: 1,
|
|
@@ -3043,7 +3121,7 @@ function mergeFinding(groups, finding, report, threshold) {
|
|
|
3043
3121
|
group.occurrences += 1;
|
|
3044
3122
|
group.details.push(finding.detail);
|
|
3045
3123
|
group.sources.push(source);
|
|
3046
|
-
group.evidence.push(...finding.evidence ?? []);
|
|
3124
|
+
group.evidence.push(...normalizeEvidence(finding.evidence) ?? []);
|
|
3047
3125
|
if (finding.severity && (!group.severity || SEVERITY_RANK[finding.severity] > SEVERITY_RANK[group.severity])) {
|
|
3048
3126
|
group.severity = finding.severity;
|
|
3049
3127
|
}
|
|
@@ -3055,7 +3133,7 @@ function mergeFinding(groups, finding, report, threshold) {
|
|
|
3055
3133
|
sources: [source],
|
|
3056
3134
|
occurrences: 1,
|
|
3057
3135
|
...finding.severity ? { severity: finding.severity } : {},
|
|
3058
|
-
evidence: [...finding.evidence ?? []]
|
|
3136
|
+
evidence: [...normalizeEvidence(finding.evidence) ?? []]
|
|
3059
3137
|
});
|
|
3060
3138
|
}
|
|
3061
3139
|
function mergeRecommendation(groups, text, report, threshold) {
|
|
@@ -3137,6 +3215,7 @@ function extractReportFromText(raw, meta) {
|
|
|
3137
3215
|
id: `${meta.taskId}-f-${index + 1}`,
|
|
3138
3216
|
title: truncate4(text, 120),
|
|
3139
3217
|
detail: text,
|
|
3218
|
+
description: text,
|
|
3140
3219
|
severity: guessSeverity(text)
|
|
3141
3220
|
}));
|
|
3142
3221
|
return {
|
|
@@ -3147,7 +3226,8 @@ function extractReportFromText(raw, meta) {
|
|
|
3147
3226
|
summary,
|
|
3148
3227
|
findings,
|
|
3149
3228
|
recommendations: recommendationTexts.map((t) => truncate4(t, 200)),
|
|
3150
|
-
|
|
3229
|
+
...evidenceTexts.length > 0 ? { evidence: evidenceTexts.map((excerpt) => ({ kind: "observation", excerpt })) } : {},
|
|
3230
|
+
metadata: evidenceTexts.length > 0 ? { evidenceCount: evidenceTexts.length } : void 0,
|
|
3151
3231
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3152
3232
|
};
|
|
3153
3233
|
}
|
|
@@ -3163,27 +3243,46 @@ var ReportService = class {
|
|
|
3163
3243
|
}
|
|
3164
3244
|
store;
|
|
3165
3245
|
log;
|
|
3246
|
+
/** Rejected reports from the last collection (§13 — malformed never enters aggregation). */
|
|
3247
|
+
lastDiagnostics = { collected: 0, accepted: 0, rejected: [] };
|
|
3166
3248
|
get storeRef() {
|
|
3167
3249
|
return this.store;
|
|
3168
3250
|
}
|
|
3169
|
-
/** Normalizes finished tasks into reports (§17 — normalizer)
|
|
3251
|
+
/** Normalizes finished tasks into reports (§17 — normalizer), validating each
|
|
3252
|
+
* one so malformed reports never reach aggregation (§13). */
|
|
3170
3253
|
async collectFromTasks(tasks) {
|
|
3171
|
-
const
|
|
3254
|
+
const candidates = [];
|
|
3172
3255
|
for (const task of tasks) {
|
|
3173
3256
|
const structured = task.result?.reports ?? [];
|
|
3174
3257
|
if (structured.length > 0) {
|
|
3175
|
-
|
|
3258
|
+
candidates.push(...structured);
|
|
3176
3259
|
continue;
|
|
3177
3260
|
}
|
|
3178
3261
|
const text = task.result?.rawOutput ?? task.result?.summary ?? "";
|
|
3179
3262
|
if (text.trim().length === 0) continue;
|
|
3180
|
-
|
|
3263
|
+
candidates.push(
|
|
3181
3264
|
extractReportFromText(text, {
|
|
3182
3265
|
taskId: task.id,
|
|
3183
3266
|
agent: task.agent ?? "unknown"
|
|
3184
3267
|
})
|
|
3185
3268
|
);
|
|
3186
3269
|
}
|
|
3270
|
+
const reports = [];
|
|
3271
|
+
const rejected = [];
|
|
3272
|
+
for (const candidate of candidates) {
|
|
3273
|
+
const result = validateReport(candidate);
|
|
3274
|
+
if (result.valid) {
|
|
3275
|
+
reports.push(result.report);
|
|
3276
|
+
} else {
|
|
3277
|
+
rejected.push({
|
|
3278
|
+
key: candidate?.id ?? "(unknown)",
|
|
3279
|
+
reason: result.reason,
|
|
3280
|
+
issues: result.issues.map((issue) => `${issue.path}: ${issue.message}`)
|
|
3281
|
+
});
|
|
3282
|
+
this.log.warn(`Rejected malformed report: ${result.reason}`);
|
|
3283
|
+
}
|
|
3284
|
+
}
|
|
3285
|
+
this.lastDiagnostics = { collected: candidates.length, accepted: reports.length, rejected };
|
|
3187
3286
|
return reports;
|
|
3188
3287
|
}
|
|
3189
3288
|
async saveReports(reports) {
|
|
@@ -3403,7 +3502,7 @@ function truncate5(text, max) {
|
|
|
3403
3502
|
|
|
3404
3503
|
// src/planner/model.ts
|
|
3405
3504
|
import { randomBytes as randomBytes4 } from "crypto";
|
|
3406
|
-
import { z as
|
|
3505
|
+
import { z as z3 } from "zod";
|
|
3407
3506
|
|
|
3408
3507
|
// src/planner/context.ts
|
|
3409
3508
|
function buildPlannerContext(request) {
|
|
@@ -3456,21 +3555,21 @@ ${request.context}`);
|
|
|
3456
3555
|
}
|
|
3457
3556
|
|
|
3458
3557
|
// src/planner/model.ts
|
|
3459
|
-
var planStepJsonSchema =
|
|
3460
|
-
id:
|
|
3461
|
-
title:
|
|
3462
|
-
description:
|
|
3463
|
-
order:
|
|
3464
|
-
targets:
|
|
3465
|
-
acceptance_criteria:
|
|
3466
|
-
depends_on:
|
|
3467
|
-
source_findings:
|
|
3558
|
+
var planStepJsonSchema = z3.object({
|
|
3559
|
+
id: z3.string().optional(),
|
|
3560
|
+
title: z3.string().min(1),
|
|
3561
|
+
description: z3.string().optional(),
|
|
3562
|
+
order: z3.number().int().optional(),
|
|
3563
|
+
targets: z3.array(z3.string()).optional(),
|
|
3564
|
+
acceptance_criteria: z3.array(z3.string()).optional(),
|
|
3565
|
+
depends_on: z3.array(z3.string()).optional(),
|
|
3566
|
+
source_findings: z3.array(z3.string()).optional()
|
|
3468
3567
|
}).strict();
|
|
3469
|
-
var planJsonSchema =
|
|
3470
|
-
summary:
|
|
3471
|
-
steps:
|
|
3472
|
-
risks:
|
|
3473
|
-
notes:
|
|
3568
|
+
var planJsonSchema = z3.object({
|
|
3569
|
+
summary: z3.string().min(1),
|
|
3570
|
+
steps: z3.array(planStepJsonSchema).min(1),
|
|
3571
|
+
risks: z3.array(z3.string()).optional(),
|
|
3572
|
+
notes: z3.array(z3.string()).optional()
|
|
3474
3573
|
}).strict();
|
|
3475
3574
|
var ModelPlanner = class {
|
|
3476
3575
|
constructor(options) {
|