snipara-companion 3.2.14 → 3.2.16
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 +1 -0
- package/dist/index.d.ts +27 -1
- package/dist/index.js +167 -1
- package/docs/FULL_REFERENCE.md +7 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -77,6 +77,7 @@ These commands are useful without hosted Snipara:
|
|
|
77
77
|
| `workflow start` / `phase-start` / `phase-commit` / `resume` | Agent continuity that survives compaction |
|
|
78
78
|
| `workflow timeline` / `workflow session` | Append-only local activity log and Session Snapshot V0 |
|
|
79
79
|
| `workflow decisions` / `workflow decide` | Local human decision requests and response receipts |
|
|
80
|
+
| `run --emit-policy-decisions` | Project Policy review requests in the agent workflow |
|
|
80
81
|
| `workflow producer-triage` | Ask for human review of unreviewed Producer Loop samples |
|
|
81
82
|
| `workflow producer-report` | Local Producer Loop adoption and calibration report |
|
|
82
83
|
| `workflow producer-review` | Mark local Producer Loop samples reviewed or rejected |
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { ProjectIntentDetectionResult, ProjectPolicyDecision, ProjectRealityCheckResult, ProjectIntelligenceEngineeringLeadPlanSummary, ProjectPolicyRule, OutcomeIntelligenceCalibration, ControlledWorkerExecutionMode, ControlledWorkerExecutionReceipt } from '@snipara/project-intelligence-contracts';
|
|
2
|
+
import { ProjectIntentDetectionResult, ProjectPolicyDecision, ProjectRealityCheckResult, ProjectIntelligenceEngineeringLeadPlanSummary, ProjectPolicyRule, DecisionRequest, OutcomeIntelligenceCalibration, ControlledWorkerExecutionMode, ControlledWorkerExecutionReceipt } from '@snipara/project-intelligence-contracts';
|
|
3
3
|
|
|
4
4
|
declare function resolveQueryFromToolInput(toolInput?: string, tool?: string): string | null;
|
|
5
5
|
|
|
@@ -2073,6 +2073,14 @@ interface RealityCheckCommandOptions {
|
|
|
2073
2073
|
declare function buildLocalProjectRealityCheck(options: RealityCheckCommandOptions): ProjectRealityCheckResult;
|
|
2074
2074
|
declare function realityCheckCommand(options: RealityCheckCommandOptions): Promise<void>;
|
|
2075
2075
|
|
|
2076
|
+
interface DecisionRequestWriteResult {
|
|
2077
|
+
status: "written" | "duplicate_pending" | "duplicate_resolved";
|
|
2078
|
+
requestId: string;
|
|
2079
|
+
fingerprint: string;
|
|
2080
|
+
path?: string;
|
|
2081
|
+
relativePath?: string;
|
|
2082
|
+
}
|
|
2083
|
+
|
|
2076
2084
|
interface MemoryHealthCommandOptions {
|
|
2077
2085
|
scope?: MemoryScope;
|
|
2078
2086
|
includeInactive?: boolean;
|
|
@@ -2463,6 +2471,7 @@ interface ProjectRunCommandOptions {
|
|
|
2463
2471
|
servedJudgmentId?: string;
|
|
2464
2472
|
skipAdvisorReceipts?: boolean;
|
|
2465
2473
|
outcomeReceiptFiles?: string[];
|
|
2474
|
+
emitPolicyDecisions?: boolean;
|
|
2466
2475
|
json?: boolean;
|
|
2467
2476
|
}
|
|
2468
2477
|
interface ProjectRunGuardResult {
|
|
@@ -2509,11 +2518,20 @@ interface ProjectIntelligenceRunResult {
|
|
|
2509
2518
|
guard?: ProjectRunGuardResult;
|
|
2510
2519
|
packageReview?: ProjectRunPackageReview;
|
|
2511
2520
|
policyGates: ProjectPolicyGatesResult;
|
|
2521
|
+
policyDecisionRequests?: ProjectRunPolicyDecisionRequests;
|
|
2512
2522
|
advisorReceiptCapture?: ProjectRunAdvisorReceiptCapture;
|
|
2513
2523
|
outcomeCalibration?: OutcomeIntelligenceCalibration;
|
|
2514
2524
|
judgmentCard: ProjectIntelligenceJudgmentCard;
|
|
2515
2525
|
suggestedCommands: string[];
|
|
2516
2526
|
}
|
|
2527
|
+
interface ProjectRunPolicyDecisionRequests {
|
|
2528
|
+
version: "project-intelligence.policy-decision-requests.v1";
|
|
2529
|
+
emitted: boolean;
|
|
2530
|
+
requestCount: number;
|
|
2531
|
+
requests: DecisionRequest[];
|
|
2532
|
+
writes: DecisionRequestWriteResult[];
|
|
2533
|
+
caveats: string[];
|
|
2534
|
+
}
|
|
2517
2535
|
declare function buildProjectIntelligenceRun(options: ProjectRunCommandOptions): Promise<ProjectIntelligenceRunResult>;
|
|
2518
2536
|
declare function projectIntelligenceRunCommand(options: ProjectRunCommandOptions): Promise<void>;
|
|
2519
2537
|
|
|
@@ -3131,6 +3149,14 @@ interface AgenticWorkStatus {
|
|
|
3131
3149
|
count?: number;
|
|
3132
3150
|
note: string;
|
|
3133
3151
|
};
|
|
3152
|
+
operationalLoop: {
|
|
3153
|
+
status: "clear" | "attention" | "blocked";
|
|
3154
|
+
decisionRequestCount: number;
|
|
3155
|
+
receiptGapCount: number;
|
|
3156
|
+
nextActions: string[];
|
|
3157
|
+
receiptActions: string[];
|
|
3158
|
+
caveats: string[];
|
|
3159
|
+
};
|
|
3134
3160
|
suggestedNextAction: string;
|
|
3135
3161
|
}
|
|
3136
3162
|
interface AgenticTimelineEvent {
|
package/dist/index.js
CHANGED
|
@@ -23292,6 +23292,68 @@ function buildSuggestedAgenticNextAction(state, risks) {
|
|
|
23292
23292
|
}
|
|
23293
23293
|
return "Run snipara-companion workflow status to inspect the managed workflow.";
|
|
23294
23294
|
}
|
|
23295
|
+
function buildAgenticOperationalLoop(args) {
|
|
23296
|
+
const phase = args.state ? currentWorkflowPhase(args.state) : void 0;
|
|
23297
|
+
const nextActions = [];
|
|
23298
|
+
const receiptActions = [];
|
|
23299
|
+
const caveats = [
|
|
23300
|
+
"Operational Loop is local and advisory; it does not edit Project Policy, approve memory, or bypass verification."
|
|
23301
|
+
];
|
|
23302
|
+
let receiptGapCount = 0;
|
|
23303
|
+
if (args.pendingDecisionCount > 0) {
|
|
23304
|
+
nextActions.push(
|
|
23305
|
+
`Resolve ${args.pendingDecisionCount} local Decision Request${args.pendingDecisionCount === 1 ? "" : "s"} with snipara-companion workflow decisions and workflow decide.`
|
|
23306
|
+
);
|
|
23307
|
+
}
|
|
23308
|
+
if (args.teamSyncSummary.staleWorkCount > 0) {
|
|
23309
|
+
nextActions.push(
|
|
23310
|
+
"Review stale Team Sync work with snipara-companion team-sync sweep --dry-run before continuing."
|
|
23311
|
+
);
|
|
23312
|
+
}
|
|
23313
|
+
if (args.dirtyFileCount > 0) {
|
|
23314
|
+
nextActions.push("Review dirty git state and run the relevant checks before phase-commit.");
|
|
23315
|
+
}
|
|
23316
|
+
if (args.latestHandoff?.next) {
|
|
23317
|
+
nextActions.push(
|
|
23318
|
+
`Continue latest handoff next step: ${toPreview(args.latestHandoff.next, 160)}`
|
|
23319
|
+
);
|
|
23320
|
+
}
|
|
23321
|
+
if (phase?.status === "blocked") {
|
|
23322
|
+
nextActions.push(`Unblock current phase '${phase.id}' before new implementation work.`);
|
|
23323
|
+
} else if (phase) {
|
|
23324
|
+
nextActions.push(
|
|
23325
|
+
`Continue phase '${phase.id}' and close it with snipara-companion workflow phase-commit ${phase.id}.`
|
|
23326
|
+
);
|
|
23327
|
+
} else if (!args.state) {
|
|
23328
|
+
nextActions.push("Start a managed workflow before multi-step implementation work.");
|
|
23329
|
+
}
|
|
23330
|
+
if (args.state && args.state.status !== "completed") {
|
|
23331
|
+
receiptGapCount += 1;
|
|
23332
|
+
receiptActions.push(
|
|
23333
|
+
"Before closing the phase, capture why/outcome evidence with snipara-companion outcome-capture preview --emit-outcome-receipt."
|
|
23334
|
+
);
|
|
23335
|
+
}
|
|
23336
|
+
if (args.latestHandoff && args.latestHandoff.attention !== "note") {
|
|
23337
|
+
receiptGapCount += 1;
|
|
23338
|
+
receiptActions.push(
|
|
23339
|
+
"Treat the latest Team Sync handoff as needing proof/review evidence before final-commit."
|
|
23340
|
+
);
|
|
23341
|
+
}
|
|
23342
|
+
if (args.pendingDecisionCount > 0) {
|
|
23343
|
+
receiptActions.push(
|
|
23344
|
+
"Decision Request resolution records the human choice; follow-up policy edits remain explicit."
|
|
23345
|
+
);
|
|
23346
|
+
}
|
|
23347
|
+
const status = phase?.status === "blocked" ? "blocked" : args.risks.length > 0 || args.pendingDecisionCount > 0 || receiptGapCount > 0 ? "attention" : "clear";
|
|
23348
|
+
return {
|
|
23349
|
+
status,
|
|
23350
|
+
decisionRequestCount: args.pendingDecisionCount,
|
|
23351
|
+
receiptGapCount,
|
|
23352
|
+
nextActions: uniqueStrings16(nextActions).slice(0, 6),
|
|
23353
|
+
receiptActions: uniqueStrings16(receiptActions).slice(0, 4),
|
|
23354
|
+
caveats
|
|
23355
|
+
};
|
|
23356
|
+
}
|
|
23295
23357
|
function buildAgenticWorkStatus(cwd = process.cwd()) {
|
|
23296
23358
|
const state = readWorkflowState2(cwd);
|
|
23297
23359
|
const git = readLocalGitState(cwd);
|
|
@@ -23302,6 +23364,7 @@ function buildAgenticWorkStatus(cwd = process.cwd()) {
|
|
|
23302
23364
|
const currentPhase = state ? currentWorkflowPhase(state) : void 0;
|
|
23303
23365
|
const lastPhaseCommit = lastCompletedWorkflowPhase(state);
|
|
23304
23366
|
const dirtyFileCount = git.statusLines?.length ?? 0;
|
|
23367
|
+
const pendingDecisionCount = decisionPendingCount(cwd);
|
|
23305
23368
|
const risks = buildAgenticStatusRisks({
|
|
23306
23369
|
state,
|
|
23307
23370
|
dirtyFileCount,
|
|
@@ -23358,8 +23421,17 @@ function buildAgenticWorkStatus(cwd = process.cwd()) {
|
|
|
23358
23421
|
},
|
|
23359
23422
|
risks,
|
|
23360
23423
|
openDecisions: {
|
|
23424
|
+
count: pendingDecisionCount,
|
|
23361
23425
|
note: "Run snipara-companion brief for hosted decisions and memory authority signals."
|
|
23362
23426
|
},
|
|
23427
|
+
operationalLoop: buildAgenticOperationalLoop({
|
|
23428
|
+
state,
|
|
23429
|
+
dirtyFileCount,
|
|
23430
|
+
risks,
|
|
23431
|
+
pendingDecisionCount,
|
|
23432
|
+
teamSyncSummary,
|
|
23433
|
+
latestHandoff
|
|
23434
|
+
}),
|
|
23363
23435
|
suggestedNextAction: buildSuggestedAgenticNextAction(state, risks)
|
|
23364
23436
|
};
|
|
23365
23437
|
}
|
|
@@ -23418,8 +23490,24 @@ function printAgenticWorkStatus(status) {
|
|
|
23418
23490
|
}
|
|
23419
23491
|
console.log("");
|
|
23420
23492
|
console.log(import_chalk6.default.bold("Open Decisions"));
|
|
23493
|
+
if (typeof status.openDecisions.count === "number") {
|
|
23494
|
+
console.log(`Local pending Decision Requests: ${status.openDecisions.count}`);
|
|
23495
|
+
}
|
|
23421
23496
|
console.log(status.openDecisions.note);
|
|
23422
23497
|
console.log("");
|
|
23498
|
+
console.log(import_chalk6.default.bold("Operational Loop"));
|
|
23499
|
+
console.log(`Status: ${status.operationalLoop.status}`);
|
|
23500
|
+
console.log(`Receipt gaps: ${status.operationalLoop.receiptGapCount}`);
|
|
23501
|
+
for (const action of status.operationalLoop.nextActions) {
|
|
23502
|
+
console.log(`- ${action}`);
|
|
23503
|
+
}
|
|
23504
|
+
for (const action of status.operationalLoop.receiptActions) {
|
|
23505
|
+
console.log(`- ${action}`);
|
|
23506
|
+
}
|
|
23507
|
+
for (const caveat of status.operationalLoop.caveats) {
|
|
23508
|
+
console.log(`- ${caveat}`);
|
|
23509
|
+
}
|
|
23510
|
+
console.log("");
|
|
23423
23511
|
printKeyValue2("Next suggested action:", status.suggestedNextAction);
|
|
23424
23512
|
if (status.workflow) {
|
|
23425
23513
|
printKeyValue2("Resume:", status.workflow.resumeCommand);
|
|
@@ -30575,6 +30663,9 @@ var ADVISOR_RECEIPT_WRITE_LIMIT = 6;
|
|
|
30575
30663
|
function normalizeStringList6(values) {
|
|
30576
30664
|
return [...new Set((values ?? []).map((value) => value.trim()).filter(Boolean))];
|
|
30577
30665
|
}
|
|
30666
|
+
function uniqueStrings18(values) {
|
|
30667
|
+
return [...new Set(values.map((value) => value.trim()).filter(Boolean))];
|
|
30668
|
+
}
|
|
30578
30669
|
function isRecord17(value) {
|
|
30579
30670
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
30580
30671
|
}
|
|
@@ -30832,6 +30923,73 @@ function verificationExecutedFromEvidence(evidence) {
|
|
|
30832
30923
|
(item) => item.command ? `${item.label}: ${item.command} (${item.status})` : `${item.label}: ${item.status}`
|
|
30833
30924
|
);
|
|
30834
30925
|
}
|
|
30926
|
+
function buildPolicyDecisionRequest(args) {
|
|
30927
|
+
const decision = args.run.policyGates.projectPolicyDecision;
|
|
30928
|
+
if (!decision || decision.verdict === "allow") return void 0;
|
|
30929
|
+
const changedFiles = args.run.brief.changedFiles.slice(0, 24);
|
|
30930
|
+
const matchedRules = decision.matchedRules.slice(0, 8);
|
|
30931
|
+
const options = decision.verdict === "block" ? ["respect_block", "request_exception", "mark_policy_stale"] : ["approve_once", "require_changes", "mark_policy_stale", "keep_advisory"];
|
|
30932
|
+
const recommendation = decision.verdict === "block" ? "respect_block" : "approve_once";
|
|
30933
|
+
return buildDecisionRequest({
|
|
30934
|
+
producer: {
|
|
30935
|
+
kind: "project_policy_review",
|
|
30936
|
+
command: "run --emit-policy-decisions",
|
|
30937
|
+
sourceRef: decision.receipt.receiptId
|
|
30938
|
+
},
|
|
30939
|
+
decision: `project_policy_${decision.verdict}`,
|
|
30940
|
+
question: decision.verdict === "block" ? "Project Policy blocked this action. Should the agent stop, request an exception, or mark the policy stale?" : "Project Policy requires human review. May the agent proceed once, change plan, or mark the policy stale?",
|
|
30941
|
+
evidence: {
|
|
30942
|
+
summary: `Project Policy verdict ${decision.verdict} for task '${args.run.brief.task ?? "unspecified"}'. Receipt ${decision.receipt.receiptId}.`,
|
|
30943
|
+
refs: uniqueStrings18([decision.receipt.receiptId, ...decision.receipt.ruleRefs]),
|
|
30944
|
+
items: matchedRules.map((rule) => ({
|
|
30945
|
+
ref: rule.source.ref,
|
|
30946
|
+
title: rule.title,
|
|
30947
|
+
summary: rule.requirement,
|
|
30948
|
+
kind: rule.source.kind,
|
|
30949
|
+
status: rule.strength,
|
|
30950
|
+
metadata: {
|
|
30951
|
+
ruleId: rule.id,
|
|
30952
|
+
scope: rule.scope,
|
|
30953
|
+
confidence: rule.confidence,
|
|
30954
|
+
reviewStatus: rule.source.reviewStatus ?? null
|
|
30955
|
+
}
|
|
30956
|
+
})),
|
|
30957
|
+
reasonCodes: uniqueStrings18(["project_policy_review", ...decision.reasonCodes]),
|
|
30958
|
+
files: changedFiles,
|
|
30959
|
+
applyPath: "manual_context_review",
|
|
30960
|
+
applyCommand: "Resolve with `snipara-companion workflow decide <request-id> --choose <option> --reviewer <name>`; if policy is stale, update or invalidate the cited decision/policy before rerunning `snipara-companion run`."
|
|
30961
|
+
},
|
|
30962
|
+
options,
|
|
30963
|
+
recommendation,
|
|
30964
|
+
rationale: "Project Policy decisions stay agent-first: the agent asks for explicit human governance and records a response receipt; no dashboard or silent policy mutation is required.",
|
|
30965
|
+
blocking: true,
|
|
30966
|
+
fingerprintParts: [
|
|
30967
|
+
"project_policy_review_v1",
|
|
30968
|
+
decision.receipt.receiptId,
|
|
30969
|
+
decision.verdict,
|
|
30970
|
+
decision.receipt.ruleRefs,
|
|
30971
|
+
changedFiles
|
|
30972
|
+
]
|
|
30973
|
+
});
|
|
30974
|
+
}
|
|
30975
|
+
function emitPolicyDecisionRequests(run) {
|
|
30976
|
+
const requests = [buildPolicyDecisionRequest({ run })].filter(
|
|
30977
|
+
(request) => Boolean(request)
|
|
30978
|
+
);
|
|
30979
|
+
const writes = requests.map((request) => writeDecisionRequest(request));
|
|
30980
|
+
return {
|
|
30981
|
+
version: "project-intelligence.policy-decision-requests.v1",
|
|
30982
|
+
emitted: true,
|
|
30983
|
+
requestCount: requests.length,
|
|
30984
|
+
requests,
|
|
30985
|
+
writes,
|
|
30986
|
+
caveats: [
|
|
30987
|
+
"Policy decision requests never apply policy changes automatically.",
|
|
30988
|
+
"Resolve them with workflow decide so the human choice is recorded as a local response receipt.",
|
|
30989
|
+
"Marking a policy stale is a governance signal; the cited memory or policy still needs explicit update or invalidation."
|
|
30990
|
+
]
|
|
30991
|
+
};
|
|
30992
|
+
}
|
|
30835
30993
|
async function recordFirstPartyAdvisorReceipts(args) {
|
|
30836
30994
|
const allRecommendations = args.judgmentCard.advisorRecommendations;
|
|
30837
30995
|
if (args.options.skipAdvisorReceipts) {
|
|
@@ -31123,7 +31281,7 @@ async function buildProjectIntelligenceRun(options) {
|
|
|
31123
31281
|
...!options.skipPackageReview && packageReview?.status !== "ok" ? [packageReviewCommand3()] : []
|
|
31124
31282
|
] : []
|
|
31125
31283
|
];
|
|
31126
|
-
|
|
31284
|
+
const result = {
|
|
31127
31285
|
version: "project-intelligence.production-run.v1",
|
|
31128
31286
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
31129
31287
|
release: Boolean(options.release),
|
|
@@ -31136,6 +31294,10 @@ async function buildProjectIntelligenceRun(options) {
|
|
|
31136
31294
|
judgmentCard,
|
|
31137
31295
|
suggestedCommands: [...new Set(suggestedCommands3)]
|
|
31138
31296
|
};
|
|
31297
|
+
if (options.emitPolicyDecisions) {
|
|
31298
|
+
result.policyDecisionRequests = emitPolicyDecisionRequests(result);
|
|
31299
|
+
}
|
|
31300
|
+
return result;
|
|
31139
31301
|
}
|
|
31140
31302
|
async function projectIntelligenceRunCommand(options) {
|
|
31141
31303
|
const result = await buildProjectIntelligenceRun(options);
|
|
@@ -33304,6 +33466,9 @@ program.command("lead-plan").description("Create a fail-closed Companion Enginee
|
|
|
33304
33466
|
program.command("run").description("Run the production Project Intelligence judgment flow for a task or release").option("--task <task>", "Current task or change summary").option("--branch <branch>", "Branch to scope continuity signals").option("--changed-files <changedFiles...>", "Changed files to analyze").option("--recent-files <recentFiles...>", "Recently touched files for continuity lookup").option("--diff-summary <diffSummary>", "Natural-language summary for code impact").option("--max-tokens <number>", "Resume context token budget", "4000").option("--release", "Run release-oriented guard and package surface review").option("--skip-impact", "Do not run companion code impact").option("--skip-memory-health", "Do not call snipara_memory_health").option("--skip-guard", "Skip collaboration guard during release runs").option("--skip-package-review", "Skip npm package surface review").option("--served-judgment-id <id>", "Served judgment id to use for first-party advisor receipts").option("--skip-advisor-receipts", "Skip first-party advisor influence receipt capture").option(
|
|
33305
33467
|
"--outcome-receipts <files...>",
|
|
33306
33468
|
"Outcome Intelligence V0 receipt JSON files for local calibration"
|
|
33469
|
+
).option(
|
|
33470
|
+
"--emit-policy-decisions",
|
|
33471
|
+
"Write local Decision Requests for Project Policy review/block findings"
|
|
33307
33472
|
).option("--json", "Print raw JSON").action(async (options) => {
|
|
33308
33473
|
await projectIntelligenceRunCommand({
|
|
33309
33474
|
task: options.task,
|
|
@@ -33320,6 +33485,7 @@ program.command("run").description("Run the production Project Intelligence judg
|
|
|
33320
33485
|
servedJudgmentId: options.servedJudgmentId,
|
|
33321
33486
|
skipAdvisorReceipts: Boolean(options.skipAdvisorReceipts),
|
|
33322
33487
|
outcomeReceiptFiles: options.outcomeReceipts,
|
|
33488
|
+
emitPolicyDecisions: Boolean(options.emitPolicyDecisions),
|
|
33323
33489
|
json: Boolean(options.json)
|
|
33324
33490
|
});
|
|
33325
33491
|
});
|
package/docs/FULL_REFERENCE.md
CHANGED
|
@@ -288,6 +288,13 @@ snipara-companion workflow resume --include-session-context
|
|
|
288
288
|
path declared. Repeated resolved receipts with the same human choice and
|
|
289
289
|
rationale can emit a review-only policy suggestion decision request; the
|
|
290
290
|
suggestion still has a manual apply path and is never auto-applied.
|
|
291
|
+
- `run --emit-policy-decisions` keeps Project Policy administration agent-first:
|
|
292
|
+
when reviewed project policy evidence produces a `require_review` or `block`
|
|
293
|
+
verdict, Companion writes a local `project_policy_review` Decision Request.
|
|
294
|
+
The human resolves it with `workflow decide`; choices such as approving once,
|
|
295
|
+
requiring changes, respecting a block, requesting an exception, or marking
|
|
296
|
+
policy stale are recorded as receipts. No policy is edited or invalidated
|
|
297
|
+
automatically.
|
|
291
298
|
- `memory reviews --scope project --emit-decisions` reads hosted memory review
|
|
292
299
|
queue, clean-candidate, and duplicate-candidate surfaces, summarizes each item,
|
|
293
300
|
and writes local Decision Request artifacts without mutating hosted memory.
|