snipara-companion 3.3.0 → 3.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/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  Release notes for `snipara-companion`, newest first.
4
4
 
5
+ ## New In 3.4.0
6
+
7
+ - Adds repeatable `workers execute --output-fragment` contracts.
8
+ - Fails a worker receipt closed when declared output fragments are missing,
9
+ while preserving explicit approval, proof, and Git scope gates.
10
+ - Persists missing output fragments in the receipt for review and calibration.
11
+
5
12
  ## New In 3.3.0
6
13
 
7
14
  - Adds reviewed, scoped Worker Trust Promotion commands: `workers trust
package/dist/index.d.ts CHANGED
@@ -4575,6 +4575,7 @@ interface ControlledWorkerExecuteOptions {
4575
4575
  writeScope?: string[];
4576
4576
  acceptance?: string[];
4577
4577
  proof?: string[];
4578
+ outputFragments?: string[];
4578
4579
  workCategory?: WorkerTrustCategory;
4579
4580
  trustEvent?: string;
4580
4581
  profileHash?: string;
package/dist/index.js CHANGED
@@ -11247,6 +11247,8 @@ function buildControlledWorkerExecutionReceipt(input) {
11247
11247
  const writeScope = uniqueStrings9(input.writeScope ?? []);
11248
11248
  const acceptanceCriteria = uniqueStrings9(input.acceptanceCriteria ?? []);
11249
11249
  const proofRequired = uniqueStrings9(input.proofRequired ?? []);
11250
+ const outputFragments = uniqueStrings9(input.outputFragments ?? []);
11251
+ const missingOutputFragments = uniqueStrings9(input.missingOutputFragments ?? []);
11250
11252
  const reasonCodes = /* @__PURE__ */ new Set([
11251
11253
  "controlled_worker_execution_v0",
11252
11254
  `controlled_worker_execution_${mode}`,
@@ -11266,6 +11268,8 @@ function buildControlledWorkerExecutionReceipt(input) {
11266
11268
  writeScope,
11267
11269
  acceptanceCriteria,
11268
11270
  proofRequired,
11271
+ outputFragments,
11272
+ missingOutputFragments,
11269
11273
  approvalReceiptId: input.approvalReceiptId ?? null,
11270
11274
  outcomeReceiptId: input.outcomeReceiptId ?? null,
11271
11275
  command,
@@ -11282,6 +11286,9 @@ function buildControlledWorkerExecutionReceipt(input) {
11282
11286
  if (acceptanceCriteria.length === 0) {
11283
11287
  reasonCodes.add("controlled_worker_execution_missing_acceptance");
11284
11288
  }
11289
+ if (missingOutputFragments.length > 0) {
11290
+ reasonCodes.add("controlled_worker_execution_output_contract_failed");
11291
+ }
11285
11292
  return {
11286
11293
  version: CONTROLLED_WORKER_EXECUTION_RECEIPT_VERSION,
11287
11294
  receiptId: `worker-exec-${receiptHash.slice(0, 16)}`,
@@ -11294,6 +11301,8 @@ function buildControlledWorkerExecutionReceipt(input) {
11294
11301
  writeScope,
11295
11302
  acceptanceCriteria,
11296
11303
  proofRequired,
11304
+ outputFragments,
11305
+ missingOutputFragments,
11297
11306
  approvalReceiptId: input.approvalReceiptId ?? null,
11298
11307
  outcomeReceiptId: input.outcomeReceiptId ?? null
11299
11308
  },
@@ -29914,6 +29923,7 @@ function controlledWorkerExecuteCommand(options) {
29914
29923
  const execute = Boolean(options.execute);
29915
29924
  const mode = normalizeMode(options.mode, execute);
29916
29925
  const commandArgs = normalizeCommandArgs(options.commandArgs);
29926
+ const outputFragments = normalizeOutputFragments(options.outputFragments);
29917
29927
  const legacyCommand = stringValue8(options.command);
29918
29928
  const command = commandArgs.length > 0 ? commandArgs.join(" ") : legacyCommand;
29919
29929
  const risk = command ? commandRisk(command) : "none";
@@ -29959,6 +29969,7 @@ function controlledWorkerExecuteCommand(options) {
29959
29969
  let executionAttempted = false;
29960
29970
  let changedFiles = [];
29961
29971
  let scopeViolations = [];
29972
+ let missingOutputFragments = [];
29962
29973
  if (execute) reasonCodes.add("controlled_worker_execution_requested");
29963
29974
  if (!execute) reasonCodes.add("controlled_worker_execution_dry_run_only");
29964
29975
  if (missingApproval) reasonCodes.add("controlled_worker_execution_missing_approval");
@@ -29996,6 +30007,13 @@ function controlledWorkerExecuteCommand(options) {
29996
30007
  exitCode = typeof result2.status === "number" ? result2.status : 1;
29997
30008
  stdout = result2.stdout ?? "";
29998
30009
  stderr = result2.stderr ?? "";
30010
+ missingOutputFragments = outputFragments.filter(
30011
+ (fragment) => !normalizeComparableText(stdout).includes(normalizeComparableText(fragment))
30012
+ );
30013
+ if (missingOutputFragments.length > 0) {
30014
+ blocked = true;
30015
+ reasonCodes.add("controlled_worker_execution_output_contract_failed");
30016
+ }
29999
30017
  reasonCodes.add(
30000
30018
  exitCode === 0 ? "controlled_worker_execution_command_succeeded" : "controlled_worker_execution_command_failed"
30001
30019
  );
@@ -30030,6 +30048,8 @@ function controlledWorkerExecuteCommand(options) {
30030
30048
  writeScope: options.writeScope,
30031
30049
  acceptanceCriteria: options.acceptance,
30032
30050
  proofRequired: options.proof,
30051
+ outputFragments,
30052
+ missingOutputFragments,
30033
30053
  approvalReceiptId: options.approvalReceipt ?? null,
30034
30054
  outcomeReceiptId: options.outcomeReceipt ?? null,
30035
30055
  command: command ?? null,
@@ -30100,6 +30120,12 @@ function controlledWorkerExecuteCommand(options) {
30100
30120
  function normalizeCommandArgs(values) {
30101
30121
  return (values ?? []).map((value) => value.trim()).filter(Boolean);
30102
30122
  }
30123
+ function normalizeOutputFragments(values) {
30124
+ return [...new Set((values ?? []).map((value) => value.trim()).filter(Boolean))].slice(0, 32);
30125
+ }
30126
+ function normalizeComparableText(value) {
30127
+ return value.toLowerCase().replace(/\s+/g, "");
30128
+ }
30103
30129
  function gitScopeSnapshot(workspaceRoot2) {
30104
30130
  const status = (0, import_node_child_process12.spawnSync)("git", ["status", "--porcelain=v1", "-z", "--untracked-files=all"], {
30105
30131
  cwd: workspaceRoot2,
@@ -38841,6 +38867,11 @@ workers.command("execute").description("Create a policy-gated Controlled Worker
38841
38867
  "Required proof or verification command; repeatable",
38842
38868
  collectOption,
38843
38869
  []
38870
+ ).option(
38871
+ "--output-fragment <fragment>",
38872
+ "Required output fragment; repeatable and checked after execution",
38873
+ collectOption,
38874
+ []
38844
38875
  ).option(
38845
38876
  "--work-category <category>",
38846
38877
  "Trust category; conservative task and scope signals can only escalate it"
@@ -38862,6 +38893,7 @@ workers.command("execute").description("Create a policy-gated Controlled Worker
38862
38893
  writeScope: options.writeScope,
38863
38894
  acceptance: options.acceptance,
38864
38895
  proof: options.proof,
38896
+ outputFragments: options.outputFragment,
38865
38897
  workCategory: options.workCategory,
38866
38898
  trustEvent: options.trustEvent,
38867
38899
  profileHash: options.profileHash,
@@ -1335,6 +1335,7 @@ snipara-companion workers execute \
1335
1335
  --write-scope docs/features/PROJECT_INTELLIGENCE.md \
1336
1336
  --acceptance "docs match shipped behavior" \
1337
1337
  --proof "pnpm --filter @snipara/web type-check" \
1338
+ --output-fragment "expected output line" \
1338
1339
  --project-id proj_123 \
1339
1340
  --json
1340
1341
  ```
@@ -1345,6 +1346,8 @@ values for real execution. A legacy `--command` string still requires a fresh
1345
1346
  approval receipt and cannot consume delegated trust. High-risk commands are
1346
1347
  blocked locally, and successful low-risk commands produce
1347
1348
  `verification_required` receipts so proof review remains explicit. When
1349
+ `--output-fragment` is provided, every declared fragment must appear in stdout;
1350
+ missing fragments fail the receipt closed and are listed in the contract.
1348
1351
  `--project-id` is provided,
1349
1352
  Companion also writes a local Unified Receipt Ledger projection under
1350
1353
  `.snipara/unified-receipts/`; use `--unified-output <file>` to choose the sidecar
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snipara-companion",
3
- "version": "3.3.0",
3
+ "version": "3.4.0",
4
4
  "description": "Local-first CLI that asks your repo what breaks before an AI coding agent edits it.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {