@kylecheng3146/agent-ops 0.1.11 → 0.1.13
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.
|
@@ -6,6 +6,7 @@ import { formatOperationPlan } from "../plan-output.js";
|
|
|
6
6
|
import { toPublicInstallPlan } from "../public-plan.js";
|
|
7
7
|
export function formatInstallPlan(plan) {
|
|
8
8
|
const hooks = plan.manifest.hooks ?? [];
|
|
9
|
+
const detectedVerification = plan.detectedVerification;
|
|
9
10
|
return formatOperationPlan({
|
|
10
11
|
title: "Installation plan",
|
|
11
12
|
metadata: [
|
|
@@ -17,6 +18,12 @@ export function formatInstallPlan(plan) {
|
|
|
17
18
|
: [
|
|
18
19
|
"Hooks:",
|
|
19
20
|
...hooks.map((hook) => ` - ${hook.harness}: ${hook.path} (${hook.events.join(", ")})`)
|
|
21
|
+
]),
|
|
22
|
+
...(detectedVerification.length === 0
|
|
23
|
+
? []
|
|
24
|
+
: [
|
|
25
|
+
"Detected verifiers (review before confirming):",
|
|
26
|
+
...detectedVerification.map((command) => ` - ${command.id}: ${command.command} ${command.args.join(" ")}`.trimEnd())
|
|
20
27
|
])
|
|
21
28
|
],
|
|
22
29
|
operations: toPublicInstallPlan(plan).operations
|
|
@@ -3,6 +3,7 @@ import { okEnvelope } from "../output.js";
|
|
|
3
3
|
import { formatOperationPlan } from "../plan-output.js";
|
|
4
4
|
import { toPublicUpdatePlan } from "../public-plan.js";
|
|
5
5
|
export function formatUpdatePlan(plan) {
|
|
6
|
+
const detectedVerification = plan.installation.detectedVerification;
|
|
6
7
|
return formatOperationPlan({
|
|
7
8
|
title: "Update plan",
|
|
8
9
|
metadata: [
|
|
@@ -12,7 +13,13 @@ export function formatUpdatePlan(plan) {
|
|
|
12
13
|
? "none"
|
|
13
14
|
: plan.migrationSteps
|
|
14
15
|
.map(({ fromVersion, toVersion }) => `${fromVersion} -> ${toVersion}`)
|
|
15
|
-
.join(", ")}
|
|
16
|
+
.join(", ")}`,
|
|
17
|
+
...(detectedVerification.length === 0
|
|
18
|
+
? []
|
|
19
|
+
: [
|
|
20
|
+
"Detected verifiers (review before confirming):",
|
|
21
|
+
...detectedVerification.map((command) => ` - ${command.id}: ${command.command} ${command.args.join(" ")}`.trimEnd())
|
|
22
|
+
])
|
|
16
23
|
],
|
|
17
24
|
operations: toPublicUpdatePlan(plan).installation.operations
|
|
18
25
|
});
|
|
@@ -42,7 +42,8 @@ export function toPublicInstallPlan(plan) {
|
|
|
42
42
|
profiles: plan.profiles,
|
|
43
43
|
capabilities: plan.capabilities,
|
|
44
44
|
manifest: plan.manifest,
|
|
45
|
-
operations: toPublicOperations(plan.operations)
|
|
45
|
+
operations: toPublicOperations(plan.operations),
|
|
46
|
+
detectedVerification: plan.detectedVerification
|
|
46
47
|
};
|
|
47
48
|
}
|
|
48
49
|
export function toPublicUpdatePlan(plan) {
|
|
@@ -241,7 +241,7 @@ export function managedRules(descriptor, context) {
|
|
|
241
241
|
""
|
|
242
242
|
];
|
|
243
243
|
if (context.capabilities.includes("rules")) {
|
|
244
|
-
lines.push("For every change:", "", "1. Define two to five mechanically verifiable acceptance criteria.", "2. Inspect the smallest relevant scope and preserve unrelated changes.", "3. Apply the smallest safe change.", "4. Run evidence-producing verification for every criterion.", "5. Obtain independent review before claiming completion.", "", "Treat `.agent-ops/config.json` as verifier authority. Discovery output is", "only a proposal until a user confirms it. Repository commands require an", "explicit matching trust record; installation approval never grants trust.", "");
|
|
244
|
+
lines.push("For every change:", "", "1. Define two to five mechanically verifiable acceptance criteria.", "2. Inspect the smallest relevant scope and preserve unrelated changes.", "3. Apply the smallest safe change.", "4. Run evidence-producing verification for every criterion.", "5. Obtain independent review before claiming completion, via", " `agent-ops review` (or the CLI's equivalent invocation). Never call a", " review-target CLI (agy, codex, claude) directly — direct calls skip", " the enforced read-only sandbox flags and can hang or fail on command", " permission prompts.", "", "Treat `.agent-ops/config.json` as verifier authority. Discovery output is", "only a proposal until a user confirms it. Repository commands require an", "explicit matching trust record; installation approval never grants trust.", "");
|
|
245
245
|
}
|
|
246
246
|
if (context.capabilities.includes("lifecycle-summary")) {
|
|
247
247
|
lines.push("Advisory lifecycle summaries and local logs are informational. Advisory", "failures must remain fail-open and cannot become verification evidence.", "");
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { lstat, readFile } from "node:fs/promises";
|
|
2
2
|
import { CONFIG_SCHEMA_VERSION, MANIFEST_SCHEMA_VERSION } from "../contracts.js";
|
|
3
|
+
import { discoverProject } from "../discovery/index.js";
|
|
3
4
|
import { sha256 } from "../fs/hash.js";
|
|
4
5
|
import { applyManagedBlock, managedBlockMarkers, removeManagedBlock } from "../fs/managed-block.js";
|
|
5
6
|
import { formatInstallManifest, parseInstallManifest } from "../fs/manifest.js";
|
|
@@ -40,16 +41,50 @@ async function readCurrentFile(root, path) {
|
|
|
40
41
|
throw error;
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Converts a stack-detected verifier proposal into a verification command.
|
|
46
|
+
* Proposal IDs use a colon-separated namespace (e.g. "node:test"); config
|
|
47
|
+
* IDs must be kebab-case identifiers.
|
|
48
|
+
*/
|
|
49
|
+
function verificationCommandFromProposal(proposal) {
|
|
50
|
+
return {
|
|
51
|
+
id: proposal.id.replace(/:/g, "-"),
|
|
52
|
+
command: proposal.command,
|
|
53
|
+
args: proposal.args,
|
|
54
|
+
cwd: proposal.cwd,
|
|
55
|
+
required: proposal.required,
|
|
56
|
+
evidence: proposal.evidence
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Verification commands are never invented for a project that already
|
|
61
|
+
* declares them; detection only fills the gap while the field is empty, so
|
|
62
|
+
* a deliberate "remove all verifiers" edit is not silently reversed by a
|
|
63
|
+
* different stack adapter next run.
|
|
64
|
+
*/
|
|
65
|
+
async function detectVerificationCommands(root) {
|
|
66
|
+
const discovery = await discoverProject(root);
|
|
67
|
+
if (discovery.kind !== "project") {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
return discovery.proposals
|
|
71
|
+
.filter((proposal) => proposal.confidence === "high")
|
|
72
|
+
.map(verificationCommandFromProposal);
|
|
73
|
+
}
|
|
74
|
+
function formatConfig(profiles, existing, reviewTargets = [], detectedCommands = []) {
|
|
44
75
|
// Absent reviewRoles means external review is disabled; an empty selection
|
|
45
76
|
// must therefore omit the field rather than write an empty array.
|
|
46
77
|
const reviewRoles = reviewTargets.length > 0
|
|
47
78
|
? [{ role: "independent-review", targets: [...reviewTargets] }]
|
|
48
79
|
: existing?.reviewRoles;
|
|
80
|
+
const verification = existing?.verification !== undefined &&
|
|
81
|
+
existing.verification.commands.length > 0
|
|
82
|
+
? existing.verification
|
|
83
|
+
: { commands: detectedCommands };
|
|
49
84
|
return `${JSON.stringify({
|
|
50
85
|
schemaVersion: CONFIG_SCHEMA_VERSION,
|
|
51
86
|
profiles,
|
|
52
|
-
verification
|
|
87
|
+
verification,
|
|
53
88
|
features: existing?.features ?? {
|
|
54
89
|
stopVerification: {
|
|
55
90
|
enabled: false
|
|
@@ -92,7 +127,11 @@ async function planConfig(root, profiles, existingManifest, suppliedConfig, revi
|
|
|
92
127
|
}
|
|
93
128
|
existingConfig = result.value;
|
|
94
129
|
}
|
|
95
|
-
const
|
|
130
|
+
const detectedCommands = existingConfig === undefined ||
|
|
131
|
+
existingConfig.verification.commands.length === 0
|
|
132
|
+
? await detectVerificationCommands(root)
|
|
133
|
+
: [];
|
|
134
|
+
const content = formatConfig(profiles, existingConfig, reviewTargets, detectedCommands);
|
|
96
135
|
return {
|
|
97
136
|
operation: {
|
|
98
137
|
kind: "write",
|
|
@@ -105,7 +144,8 @@ async function planConfig(root, profiles, existingManifest, suppliedConfig, revi
|
|
|
105
144
|
path: CONFIG_PATH,
|
|
106
145
|
hash: sha256(content),
|
|
107
146
|
owner: "agent-ops"
|
|
108
|
-
}
|
|
147
|
+
},
|
|
148
|
+
detectedVerification: detectedCommands
|
|
109
149
|
};
|
|
110
150
|
}
|
|
111
151
|
function pathKey(path) {
|
|
@@ -528,6 +568,7 @@ export async function createInstallPlan(options) {
|
|
|
528
568
|
profiles: resolved.profiles,
|
|
529
569
|
capabilities: resolved.capabilities,
|
|
530
570
|
manifest,
|
|
531
|
-
operations
|
|
571
|
+
operations,
|
|
572
|
+
detectedVerification: config.detectedVerification
|
|
532
573
|
};
|
|
533
574
|
}
|