snipara-companion 3.5.2 → 3.5.4
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 +20 -0
- package/README.md +5 -1
- package/dist/index.d.ts +27 -2
- package/dist/index.js +452 -78
- package/docs/FULL_REFERENCE.md +16 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
Release notes for `snipara-companion`, newest first.
|
|
4
4
|
|
|
5
|
+
## New In 3.5.4
|
|
6
|
+
|
|
7
|
+
- Makes `reality-check` auto-link bounded reviewed Team Sync decisions, keyword
|
|
8
|
+
document context, managed workflow receipts, and current verification
|
|
9
|
+
evidence while preserving explicit CLI inputs and failing open when hosted
|
|
10
|
+
context is unavailable.
|
|
11
|
+
- Keeps the evidence used by Reality Check inspectable in JSON and Markdown
|
|
12
|
+
findings instead of using verification only as a hidden severity signal.
|
|
13
|
+
- Gives `query` a 30-second default timeout plus explicit search-mode,
|
|
14
|
+
Answer Pack, decomposition, and shared-context controls for fast recovery.
|
|
15
|
+
|
|
16
|
+
## New In 3.5.3
|
|
17
|
+
|
|
18
|
+
- Propagates the configured Companion `sessionId` as
|
|
19
|
+
`X-Snipara-Session-Id` on Hosted MCP calls.
|
|
20
|
+
- Labels supported retrieval calls as `snipara-companion` while preserving an
|
|
21
|
+
explicit caller-provided client label and correlation context.
|
|
22
|
+
- Keeps correlation telemetry-only and project-scoped; authentication and
|
|
23
|
+
ranking promotion remain separate contracts.
|
|
24
|
+
|
|
5
25
|
## New In 3.5.2
|
|
6
26
|
|
|
7
27
|
- Replaces the retired Windsurf preset with Kimi Code CLI across setup,
|
package/README.md
CHANGED
|
@@ -60,6 +60,10 @@ same value as `correlation_context.session_id` on retrieval tools.
|
|
|
60
60
|
|
|
61
61
|
The identifier is opaque, project-scoped telemetry. It does not grant access or
|
|
62
62
|
change authorization, and explicit per-call correlation remains authoritative.
|
|
63
|
+
Companion also forwards its configured `sessionId` automatically on every
|
|
64
|
+
Hosted MCP call and labels supported retrieval traffic as
|
|
65
|
+
`snipara-companion`, unless the caller supplied an explicit client label. This
|
|
66
|
+
improves join coverage without inventing a second server-side identity.
|
|
63
67
|
|
|
64
68
|
Example output excerpt:
|
|
65
69
|
|
|
@@ -90,7 +94,7 @@ These commands are useful without hosted Snipara:
|
|
|
90
94
|
| ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
|
|
91
95
|
| `source init` / `source sync` / `source status` | Local source snapshot, document preview, and code overlay |
|
|
92
96
|
| `impact` / `code impact` | File-level blast-radius from the local code overlay |
|
|
93
|
-
| `reality-check` | Intent Ledger, Unknown Registry, and
|
|
97
|
+
| `reality-check` | Intent Ledger, Unknown Registry, auto-linked context, and inspectable proof |
|
|
94
98
|
| `code callers` / `imports` / `neighbors` / `shortest-path` | Structural repo questions from local files |
|
|
95
99
|
| `workflow start` / `phase-start` / `phase-commit` / `resume` | Agent continuity that survives compaction |
|
|
96
100
|
| `workflow timeline` / `workflow session` | Append-only local activity log and Session Snapshot V0 |
|
package/dist/index.d.ts
CHANGED
|
@@ -269,6 +269,19 @@ interface ContextQueryResult {
|
|
|
269
269
|
graph_hybrid_used?: boolean;
|
|
270
270
|
graph_context_tool?: string;
|
|
271
271
|
graph_context_summary?: string;
|
|
272
|
+
search_mode?: ContextQuerySearchMode;
|
|
273
|
+
timing?: Record<string, number>;
|
|
274
|
+
retrieval_diagnostics?: Record<string, unknown>;
|
|
275
|
+
}
|
|
276
|
+
type ContextQuerySearchMode = "keyword" | "semantic" | "hybrid";
|
|
277
|
+
interface ContextQueryOptions {
|
|
278
|
+
searchMode?: ContextQuerySearchMode;
|
|
279
|
+
includeMetadata?: boolean;
|
|
280
|
+
includeAnswerPack?: boolean;
|
|
281
|
+
autoDecompose?: boolean;
|
|
282
|
+
includeSharedContext?: boolean;
|
|
283
|
+
includeAllTiers?: boolean;
|
|
284
|
+
returnReferences?: boolean;
|
|
272
285
|
}
|
|
273
286
|
interface AnswerPackSource {
|
|
274
287
|
title?: string;
|
|
@@ -1222,7 +1235,7 @@ declare class RLMClient {
|
|
|
1222
1235
|
/**
|
|
1223
1236
|
* Query for optimized context using snipara_context_query
|
|
1224
1237
|
*/
|
|
1225
|
-
queryContext(query: string, maxTokens?: number): Promise<ContextQueryResult>;
|
|
1238
|
+
queryContext(query: string, maxTokens?: number, options?: ContextQueryOptions): Promise<ContextQueryResult>;
|
|
1226
1239
|
sharedContext(options?: {
|
|
1227
1240
|
maxTokens?: number;
|
|
1228
1241
|
categories?: string[];
|
|
@@ -2183,12 +2196,24 @@ interface RealityCheckCommandOptions {
|
|
|
2183
2196
|
decision?: string[];
|
|
2184
2197
|
document?: string[];
|
|
2185
2198
|
verification?: string[];
|
|
2199
|
+
autoContext?: boolean;
|
|
2200
|
+
autoContextTimeoutMs?: number;
|
|
2186
2201
|
includeDirty?: boolean;
|
|
2187
2202
|
enforce?: boolean;
|
|
2188
2203
|
dir?: string;
|
|
2189
2204
|
json?: boolean;
|
|
2190
2205
|
}
|
|
2206
|
+
interface RealityCheckAutoContextClient {
|
|
2207
|
+
queryContext(query: string, maxTokens?: number, options?: ContextQueryOptions): Promise<ContextQueryResult>;
|
|
2208
|
+
getTeamSyncWhatChanged(args: {
|
|
2209
|
+
limit?: number;
|
|
2210
|
+
branch?: string;
|
|
2211
|
+
paths?: string[];
|
|
2212
|
+
recentFiles?: string[];
|
|
2213
|
+
}): Promise<TeamSyncChangesResponse>;
|
|
2214
|
+
}
|
|
2191
2215
|
declare function buildLocalProjectRealityCheck(options: RealityCheckCommandOptions): ProjectRealityCheckResult;
|
|
2216
|
+
declare function buildLocalProjectRealityCheckWithAutoContext(options: RealityCheckCommandOptions, clientOverride?: RealityCheckAutoContextClient): Promise<ProjectRealityCheckResult>;
|
|
2192
2217
|
declare function realityCheckCommand(options: RealityCheckCommandOptions): Promise<void>;
|
|
2193
2218
|
|
|
2194
2219
|
interface DecisionRequestWriteResult {
|
|
@@ -4906,4 +4931,4 @@ declare function installAutomationBundle(args: {
|
|
|
4906
4931
|
}): Promise<AutomationInstallResult>;
|
|
4907
4932
|
declare function getAutomationStatus(projectDir?: string): AutomationStatusResult;
|
|
4908
4933
|
|
|
4909
|
-
export { AUTOMATION_MANIFEST_RELATIVE_PATH, AutomationInstallConflictError, AutomationUnsupportedHookBundleError, CODING_INTELLIGENCE_LEDGER_VERSION, COLLABORATION_STATE_RELATIVE_PATH, ENGINEERING_LEAD_EXECUTION_RECEIPT_STAGES, ENGINEERING_LEAD_EXECUTION_RECEIPT_STATUSES, ENGINEERING_LEAD_POSTURES, ENGINEERING_LEAD_PROOF_VERIFICATION_SOURCES, ENGINEERING_LEAD_PROOF_VERIFICATION_STATUSES, ENGINEERING_LEAD_ROUTING_MODES, ENGINEERING_LEAD_STATUSES, ENGINEERING_LEAD_SUPERVISION_STATUSES, ENGINEERING_LEAD_WORKER_ROLES, ENGINEERING_LEAD_WORK_PACKAGE_STATUSES, FINAL_COMMIT_REPORT_RELATIVE_PATH, FINAL_COMMIT_REPORT_VERSION, ORCHESTRATOR_HANDOFF_RELATIVE_PATH, POLICY_LEDGER_SYNC_REPORT_VERSION, PRODUCER_LOOP_ARTIFACT_VERSION, PRODUCER_LOOP_RELATIVE_DIR, PRODUCER_LOOP_REPORT_VERSION, TEAM_SYNC_STATE_RELATIVE_PATH, WHY_OUTCOME_CAPTURE_VERSION, WORKFLOW_PLANS_RELATIVE_DIR, WORKFLOW_STATE_RELATIVE_PATH, addLocalWorker, agentReadinessAuditCommand, appendActivityEvent, applyLocalContextMutationPlan, archiveInactiveTeamSyncWork, attachLocalContextPackReceipts, autoArchiveTeamSyncState, buildAdaptiveWorkRoutingRecommendation, buildAgentReadinessAuditReport, buildAgenticHandoffMarkdown, buildAgenticTimeline, buildAgenticWorkStatus, buildAutomationInstallPlan, buildCanonicalEvent, buildCodeHooksInstallPlan, buildCodePromotionResult, buildCodeStatusResult, buildCodeSyncResult, buildCodingIntelligenceLedger, buildCollaborationActor, buildCollaborationGuardActionCards, buildCollaborationHooksInstallPlan, buildCommitResultMetadata, buildCompanionEngineeringLeadPlanReport, buildContextPackStats, buildEvalCaseArtifact, buildFinalCommitReport, buildGeneratedWorkflowPlanDocument, buildHostedCodeOverlayUploadPayload, buildHostedGuardPayload, buildJournalCheckpointEntry, buildLocalCallersResult, buildLocalCodeOverlay, buildLocalContextMutationPlan, buildLocalContextPackReceipt, buildLocalContextPackReceipts, buildLocalImpactResult, buildLocalImportsResult, buildLocalNeighborsResult, buildLocalProjectContextValidationReport, buildLocalProjectDriftReport, buildLocalProjectRealityCheck, buildLocalShortestPathResult, buildLocalSourceSnapshot, buildLocalSourceStatus, buildLocalSourceSyncResult, buildMemoryAudit, buildOnboardFolderManifest, buildOrchestratorHandoff, buildPolicyLedgerSyncReport, buildProducerLoopReport, buildProjectIntelligenceBrief, buildProjectIntelligenceRun, buildProjectJudgmentCard, buildSessionBootstrapBrief, buildSessionBootstrapQuality, buildSessionSnapshot, buildSyncDocumentsDryRun, buildTeamSyncHandoffRecord, buildTeamSyncStartWorkRecord, buildTeamSyncSummary, buildToolCallPayload, buildToolResultPayload, buildVerificationPlan, buildWhyOutcomeCaptureReport, buildWorkerTrustCandidates, buildWorkflowImpactGate, buildWorkflowPhaseCommitReceipt, buildWorkflowPhaseCommitSummary, buildWorkflowPlanScaffold, categoryFromGuardTag, classifyToolResult, cleanContextPacks, codingLedgerExportCommand, collaborationIdeStatusCommand, collectAgentReadinessLocalSignals, collectPolicyLedgerSyncArtifacts, collectSyncDocuments, collectSyncDocumentsInput, compactHostedGuardResources, compareLocalSourceSnapshots, completeTeamSyncStateFromEvidence, completeTeamSyncWorkFromEvidence, contextControlApplyCommand, contextControlDriftCommand, contextControlHostedApplyCommand, contextControlHostedDiffCommand, contextControlPlanCommand, contextControlValidateCommand, contextPackCleanCommand, contextPackPackCommand, contextPackRetrieveCommand, contextPackStatsCommand, controlledWorkerExecuteCommand, createClient, createEmptyCollaborationState, createEmptyTeamSyncState, createLocalQueryCache, deriveLocalCollaborationResourcesFromFiles, detectReleaseSurfacesFromFiles, detectRuntimeEnvironment, evalExportCommand, evalRunCommand, evaluateProjectPolicyGates, extractCommandFromToolInput, extractFilesFromToolInput, formatAgentReadinessAuditReport, formatCompanionEngineeringLeadPlanReport, formatFinalCommitReport, formatOrchestratorRecommendationReason, formatPolicyGateDecision, formatProjectJudgmentCard, formatStuckGuardDecision, getAutomationManifestPath, getAutomationStatus, getCollaborationStatePath, getConfigPath, getContextPackStoragePaths, getLocalCodeOverlayCachePath, getLocalCodePromotionStatePath, getLocalSourceSnapshotPath, getOrchestratorRecommendation, getPlanStepDisplayTitle, getStagedFiles, getStuckGuardInjection, getTeamSyncStatePath, hashWorkerProfile, ingestReferences, installAutomationBundle, leadPlanCommand, listProjectsForApiKey, loadAutomationManifest, loadCollaborationState, loadConfig, loadTeamSyncState, memoryAuditCommand, memoryCleanCandidatesCommand, memoryCompactCommand, memoryHealthCommand, memoryLocalCommand, memoryReviewsCommand, normalizeCollaborationFiles, normalizeGuardTag, normalizeWorkflowPlanInput, outcomeCapturePreviewCommand, packContext, parseCollaborationResources, projectIntelligenceBriefCommand, projectIntelligenceRunCommand, readActivityTimeline, readLocalCodeOverlayCache, readLocalCodePromotionState, readLocalSourceSnapshot, readLocalWorkersConfig, readSessionSnapshot, readWorkerTrustEvent, realityCheckCommand, referencesIngestCommand, referencesScanCommand, resolveAutoWorkflowMode, resolveContextPackRecord, resolveFullWorkflowTokenBudget, resolveLocalWorkerRoutingDefaults, resolveQueryFromToolInput, retrieveContextPack, runMemoryGuardCheck, saveCollaborationState, saveConfig, saveTeamSyncState, scanReferences, shouldFailCollaborationGuard, shouldSuggestOrchestratorForWorkflow, shouldSuggestRuntimeForWorkflow, summarizeLocalCodeOverlay, teamSyncSweepCommand, validatePlanResult, verifyCommand, workerTrustCandidateCommand, workerTrustReviewCommand, workerTrustStatusCommand, workersLocalAddCommand, workersLocalListCommand, workersLocalProbePrintCommand, workersLocalRemoveCommand, workersLocalStatusCommand, workflowSyncPolicyLedgerCommand, writeFinalCommitReport, writeLocalCodeOverlayCache, writeLocalCodePromotionState, writeLocalSourceSnapshot, writeOrchestratorHandoff, writeProducerLoopArtifact, writeSessionSnapshot };
|
|
4934
|
+
export { AUTOMATION_MANIFEST_RELATIVE_PATH, AutomationInstallConflictError, AutomationUnsupportedHookBundleError, CODING_INTELLIGENCE_LEDGER_VERSION, COLLABORATION_STATE_RELATIVE_PATH, ENGINEERING_LEAD_EXECUTION_RECEIPT_STAGES, ENGINEERING_LEAD_EXECUTION_RECEIPT_STATUSES, ENGINEERING_LEAD_POSTURES, ENGINEERING_LEAD_PROOF_VERIFICATION_SOURCES, ENGINEERING_LEAD_PROOF_VERIFICATION_STATUSES, ENGINEERING_LEAD_ROUTING_MODES, ENGINEERING_LEAD_STATUSES, ENGINEERING_LEAD_SUPERVISION_STATUSES, ENGINEERING_LEAD_WORKER_ROLES, ENGINEERING_LEAD_WORK_PACKAGE_STATUSES, FINAL_COMMIT_REPORT_RELATIVE_PATH, FINAL_COMMIT_REPORT_VERSION, ORCHESTRATOR_HANDOFF_RELATIVE_PATH, POLICY_LEDGER_SYNC_REPORT_VERSION, PRODUCER_LOOP_ARTIFACT_VERSION, PRODUCER_LOOP_RELATIVE_DIR, PRODUCER_LOOP_REPORT_VERSION, TEAM_SYNC_STATE_RELATIVE_PATH, WHY_OUTCOME_CAPTURE_VERSION, WORKFLOW_PLANS_RELATIVE_DIR, WORKFLOW_STATE_RELATIVE_PATH, addLocalWorker, agentReadinessAuditCommand, appendActivityEvent, applyLocalContextMutationPlan, archiveInactiveTeamSyncWork, attachLocalContextPackReceipts, autoArchiveTeamSyncState, buildAdaptiveWorkRoutingRecommendation, buildAgentReadinessAuditReport, buildAgenticHandoffMarkdown, buildAgenticTimeline, buildAgenticWorkStatus, buildAutomationInstallPlan, buildCanonicalEvent, buildCodeHooksInstallPlan, buildCodePromotionResult, buildCodeStatusResult, buildCodeSyncResult, buildCodingIntelligenceLedger, buildCollaborationActor, buildCollaborationGuardActionCards, buildCollaborationHooksInstallPlan, buildCommitResultMetadata, buildCompanionEngineeringLeadPlanReport, buildContextPackStats, buildEvalCaseArtifact, buildFinalCommitReport, buildGeneratedWorkflowPlanDocument, buildHostedCodeOverlayUploadPayload, buildHostedGuardPayload, buildJournalCheckpointEntry, buildLocalCallersResult, buildLocalCodeOverlay, buildLocalContextMutationPlan, buildLocalContextPackReceipt, buildLocalContextPackReceipts, buildLocalImpactResult, buildLocalImportsResult, buildLocalNeighborsResult, buildLocalProjectContextValidationReport, buildLocalProjectDriftReport, buildLocalProjectRealityCheck, buildLocalProjectRealityCheckWithAutoContext, buildLocalShortestPathResult, buildLocalSourceSnapshot, buildLocalSourceStatus, buildLocalSourceSyncResult, buildMemoryAudit, buildOnboardFolderManifest, buildOrchestratorHandoff, buildPolicyLedgerSyncReport, buildProducerLoopReport, buildProjectIntelligenceBrief, buildProjectIntelligenceRun, buildProjectJudgmentCard, buildSessionBootstrapBrief, buildSessionBootstrapQuality, buildSessionSnapshot, buildSyncDocumentsDryRun, buildTeamSyncHandoffRecord, buildTeamSyncStartWorkRecord, buildTeamSyncSummary, buildToolCallPayload, buildToolResultPayload, buildVerificationPlan, buildWhyOutcomeCaptureReport, buildWorkerTrustCandidates, buildWorkflowImpactGate, buildWorkflowPhaseCommitReceipt, buildWorkflowPhaseCommitSummary, buildWorkflowPlanScaffold, categoryFromGuardTag, classifyToolResult, cleanContextPacks, codingLedgerExportCommand, collaborationIdeStatusCommand, collectAgentReadinessLocalSignals, collectPolicyLedgerSyncArtifacts, collectSyncDocuments, collectSyncDocumentsInput, compactHostedGuardResources, compareLocalSourceSnapshots, completeTeamSyncStateFromEvidence, completeTeamSyncWorkFromEvidence, contextControlApplyCommand, contextControlDriftCommand, contextControlHostedApplyCommand, contextControlHostedDiffCommand, contextControlPlanCommand, contextControlValidateCommand, contextPackCleanCommand, contextPackPackCommand, contextPackRetrieveCommand, contextPackStatsCommand, controlledWorkerExecuteCommand, createClient, createEmptyCollaborationState, createEmptyTeamSyncState, createLocalQueryCache, deriveLocalCollaborationResourcesFromFiles, detectReleaseSurfacesFromFiles, detectRuntimeEnvironment, evalExportCommand, evalRunCommand, evaluateProjectPolicyGates, extractCommandFromToolInput, extractFilesFromToolInput, formatAgentReadinessAuditReport, formatCompanionEngineeringLeadPlanReport, formatFinalCommitReport, formatOrchestratorRecommendationReason, formatPolicyGateDecision, formatProjectJudgmentCard, formatStuckGuardDecision, getAutomationManifestPath, getAutomationStatus, getCollaborationStatePath, getConfigPath, getContextPackStoragePaths, getLocalCodeOverlayCachePath, getLocalCodePromotionStatePath, getLocalSourceSnapshotPath, getOrchestratorRecommendation, getPlanStepDisplayTitle, getStagedFiles, getStuckGuardInjection, getTeamSyncStatePath, hashWorkerProfile, ingestReferences, installAutomationBundle, leadPlanCommand, listProjectsForApiKey, loadAutomationManifest, loadCollaborationState, loadConfig, loadTeamSyncState, memoryAuditCommand, memoryCleanCandidatesCommand, memoryCompactCommand, memoryHealthCommand, memoryLocalCommand, memoryReviewsCommand, normalizeCollaborationFiles, normalizeGuardTag, normalizeWorkflowPlanInput, outcomeCapturePreviewCommand, packContext, parseCollaborationResources, projectIntelligenceBriefCommand, projectIntelligenceRunCommand, readActivityTimeline, readLocalCodeOverlayCache, readLocalCodePromotionState, readLocalSourceSnapshot, readLocalWorkersConfig, readSessionSnapshot, readWorkerTrustEvent, realityCheckCommand, referencesIngestCommand, referencesScanCommand, resolveAutoWorkflowMode, resolveContextPackRecord, resolveFullWorkflowTokenBudget, resolveLocalWorkerRoutingDefaults, resolveQueryFromToolInput, retrieveContextPack, runMemoryGuardCheck, saveCollaborationState, saveConfig, saveTeamSyncState, scanReferences, shouldFailCollaborationGuard, shouldSuggestOrchestratorForWorkflow, shouldSuggestRuntimeForWorkflow, summarizeLocalCodeOverlay, teamSyncSweepCommand, validatePlanResult, verifyCommand, workerTrustCandidateCommand, workerTrustReviewCommand, workerTrustStatusCommand, workersLocalAddCommand, workersLocalListCommand, workersLocalProbePrintCommand, workersLocalRemoveCommand, workersLocalStatusCommand, workflowSyncPolicyLedgerCommand, writeFinalCommitReport, writeLocalCodeOverlayCache, writeLocalCodePromotionState, writeLocalSourceSnapshot, writeOrchestratorHandoff, writeProducerLoopArtifact, writeSessionSnapshot };
|
package/dist/index.js
CHANGED
|
@@ -99,6 +99,7 @@ __export(index_exports, {
|
|
|
99
99
|
buildLocalProjectContextValidationReport: () => buildLocalProjectContextValidationReport,
|
|
100
100
|
buildLocalProjectDriftReport: () => buildLocalProjectDriftReport,
|
|
101
101
|
buildLocalProjectRealityCheck: () => buildLocalProjectRealityCheck,
|
|
102
|
+
buildLocalProjectRealityCheckWithAutoContext: () => buildLocalProjectRealityCheckWithAutoContext,
|
|
102
103
|
buildLocalShortestPathResult: () => buildLocalShortestPathResult,
|
|
103
104
|
buildLocalSourceSnapshot: () => buildLocalSourceSnapshot,
|
|
104
105
|
buildLocalSourceStatus: () => buildLocalSourceStatus,
|
|
@@ -522,6 +523,27 @@ function readGitRemote(cwd) {
|
|
|
522
523
|
}
|
|
523
524
|
|
|
524
525
|
// src/api/client.ts
|
|
526
|
+
var CORRELATED_RETRIEVAL_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
527
|
+
"snipara_context_query",
|
|
528
|
+
"snipara_ask",
|
|
529
|
+
"snipara_search",
|
|
530
|
+
"snipara_recall",
|
|
531
|
+
"snipara_get_chunk",
|
|
532
|
+
"rlm_context_query",
|
|
533
|
+
"rlm_ask",
|
|
534
|
+
"rlm_search",
|
|
535
|
+
"rlm_recall",
|
|
536
|
+
"rlm_get_chunk"
|
|
537
|
+
]);
|
|
538
|
+
function withCompanionRetrievalClient(toolName, args) {
|
|
539
|
+
if (!CORRELATED_RETRIEVAL_TOOL_NAMES.has(toolName) || args.client !== void 0) {
|
|
540
|
+
return args;
|
|
541
|
+
}
|
|
542
|
+
return {
|
|
543
|
+
...args,
|
|
544
|
+
client: "snipara-companion"
|
|
545
|
+
};
|
|
546
|
+
}
|
|
525
547
|
function getSniparaTokenStorePath() {
|
|
526
548
|
return path3.join(os2.homedir(), ".snipara", "tokens.json");
|
|
527
549
|
}
|
|
@@ -743,7 +765,7 @@ var RLMClient = class {
|
|
|
743
765
|
method: "tools/call",
|
|
744
766
|
params: {
|
|
745
767
|
name: toolName,
|
|
746
|
-
arguments: args
|
|
768
|
+
arguments: withCompanionRetrievalClient(toolName, args)
|
|
747
769
|
}
|
|
748
770
|
};
|
|
749
771
|
const controller = new AbortController();
|
|
@@ -754,7 +776,8 @@ var RLMClient = class {
|
|
|
754
776
|
{
|
|
755
777
|
method: "POST",
|
|
756
778
|
headers: {
|
|
757
|
-
"Content-Type": "application/json"
|
|
779
|
+
"Content-Type": "application/json",
|
|
780
|
+
...this.config.sessionId ? { "X-Snipara-Session-Id": this.config.sessionId } : {}
|
|
758
781
|
},
|
|
759
782
|
body: JSON.stringify(payload),
|
|
760
783
|
signal: controller.signal
|
|
@@ -783,13 +806,17 @@ var RLMClient = class {
|
|
|
783
806
|
/**
|
|
784
807
|
* Query for optimized context using snipara_context_query
|
|
785
808
|
*/
|
|
786
|
-
async queryContext(query, maxTokens = 8e3) {
|
|
809
|
+
async queryContext(query, maxTokens = 8e3, options = {}) {
|
|
787
810
|
const result = await this.mcpCall("snipara_context_query", {
|
|
788
811
|
query,
|
|
789
812
|
max_tokens: maxTokens,
|
|
790
|
-
search_mode: "hybrid",
|
|
791
|
-
include_metadata: true,
|
|
792
|
-
include_answer_pack: true
|
|
813
|
+
search_mode: options.searchMode ?? "hybrid",
|
|
814
|
+
include_metadata: options.includeMetadata ?? true,
|
|
815
|
+
include_answer_pack: options.includeAnswerPack ?? true,
|
|
816
|
+
auto_decompose: options.autoDecompose,
|
|
817
|
+
include_shared_context: options.includeSharedContext,
|
|
818
|
+
include_all_tiers: options.includeAllTiers,
|
|
819
|
+
return_references: options.returnReferences
|
|
793
820
|
});
|
|
794
821
|
return {
|
|
795
822
|
sections: (result.sections || []).map((s) => ({
|
|
@@ -818,7 +845,10 @@ var RLMClient = class {
|
|
|
818
845
|
recommended_tool_arguments: result.recommended_tool_arguments || {},
|
|
819
846
|
graph_hybrid_used: result.graph_hybrid_used,
|
|
820
847
|
graph_context_tool: result.graph_context_tool,
|
|
821
|
-
graph_context_summary: result.graph_context_summary
|
|
848
|
+
graph_context_summary: result.graph_context_summary,
|
|
849
|
+
search_mode: result.search_mode,
|
|
850
|
+
timing: result.timing,
|
|
851
|
+
retrieval_diagnostics: result.retrieval_diagnostics
|
|
822
852
|
};
|
|
823
853
|
}
|
|
824
854
|
async sharedContext(options = {}) {
|
|
@@ -9519,6 +9549,9 @@ function buildDocumentIntentEntry(doc, policy) {
|
|
|
9519
9549
|
doc.intent?.freshnessHorizonDays ?? doc.freshnessHorizonDays ?? sectionIntent.freshnessHorizonDays,
|
|
9520
9550
|
policy
|
|
9521
9551
|
);
|
|
9552
|
+
const affectedAnchors = uniqueStrings3(
|
|
9553
|
+
doc.affectedAnchors && doc.affectedAnchors.length > 0 ? doc.affectedAnchors : [doc.path]
|
|
9554
|
+
);
|
|
9522
9555
|
return {
|
|
9523
9556
|
id: `intent:doc:${doc.path}`,
|
|
9524
9557
|
title: doc.title || doc.path,
|
|
@@ -9546,7 +9579,7 @@ function buildDocumentIntentEntry(doc, policy) {
|
|
|
9546
9579
|
structuredSections: sectionIntent,
|
|
9547
9580
|
fallbackUsed: goal === doc.path || goal === doc.title
|
|
9548
9581
|
}),
|
|
9549
|
-
affectedAnchors
|
|
9582
|
+
affectedAnchors,
|
|
9550
9583
|
owner: doc.intent?.owner ?? sectionIntent.owner ?? doc.owner ?? null,
|
|
9551
9584
|
evidence: [
|
|
9552
9585
|
{
|
|
@@ -10174,6 +10207,23 @@ function decisionEvidence(decisions) {
|
|
|
10174
10207
|
strength: decision.confidenceScore ?? 0.8
|
|
10175
10208
|
}));
|
|
10176
10209
|
}
|
|
10210
|
+
function verificationEvidence(input) {
|
|
10211
|
+
return (input.verificationChecklist ?? []).slice(0, 8).map((item, index) => ({
|
|
10212
|
+
kind: /test|spec|vitest|pytest|e2e|smoke|lint|type.?check|build|health|ready|migration|schema|pack/i.test(
|
|
10213
|
+
item
|
|
10214
|
+
) ? "test" : "manual",
|
|
10215
|
+
label: item,
|
|
10216
|
+
sourceRef: `verification:${index + 1}`,
|
|
10217
|
+
strength: 0.75
|
|
10218
|
+
}));
|
|
10219
|
+
}
|
|
10220
|
+
function uniqueEvidence(evidence) {
|
|
10221
|
+
return [
|
|
10222
|
+
...new Map(
|
|
10223
|
+
evidence.map((item) => [`${item.kind}:${item.sourceRef ?? item.label}`, item])
|
|
10224
|
+
).values()
|
|
10225
|
+
];
|
|
10226
|
+
}
|
|
10177
10227
|
function buildProjectRealityCheck(input) {
|
|
10178
10228
|
const changedFiles = uniqueStrings3(input.changedFiles);
|
|
10179
10229
|
const dirtyFiles = uniqueStrings3(input.dirtyFiles ?? []);
|
|
@@ -10181,7 +10231,17 @@ function buildProjectRealityCheck(input) {
|
|
|
10181
10231
|
const tests = testFiles(changedFiles);
|
|
10182
10232
|
const findings = [];
|
|
10183
10233
|
const decisions = input.decisions ?? [];
|
|
10184
|
-
const
|
|
10234
|
+
const verificationRefs = verificationEvidence(input);
|
|
10235
|
+
const contextEvidence2 = uniqueEvidence([
|
|
10236
|
+
...docEvidence(input),
|
|
10237
|
+
...symbolEvidence(input),
|
|
10238
|
+
...input.evidence ?? []
|
|
10239
|
+
]);
|
|
10240
|
+
const allEvidence = uniqueEvidence([
|
|
10241
|
+
...decisionEvidence(decisions),
|
|
10242
|
+
...verificationRefs,
|
|
10243
|
+
...contextEvidence2
|
|
10244
|
+
]).slice(0, 20);
|
|
10185
10245
|
const intentLedger = buildProjectIntentLedger(input, changedFiles);
|
|
10186
10246
|
for (const surface of SENSITIVE_SURFACES) {
|
|
10187
10247
|
const files = surfaceFiles(surface, changedFiles);
|
|
@@ -10210,7 +10270,11 @@ function buildProjectRealityCheck(input) {
|
|
|
10210
10270
|
summary: `${files.length} changed file(s) touch ${surface.label.toLowerCase()} with ${relatedDecisions.length > 0 ? `${relatedDecisions.length} linked decision(s)` : "no linked decision"} and ${hasVerification ? "some verification evidence" : "no obvious verification evidence"}.`,
|
|
10211
10271
|
changedFiles: files.slice(0, 12),
|
|
10212
10272
|
decisionIds: relatedDecisions.map((decision) => decision.id).slice(0, 8),
|
|
10213
|
-
evidence: [
|
|
10273
|
+
evidence: uniqueEvidence([
|
|
10274
|
+
...decisionEvidence(relatedDecisions),
|
|
10275
|
+
...verificationRefs,
|
|
10276
|
+
...contextEvidence2
|
|
10277
|
+
]).slice(0, 8),
|
|
10214
10278
|
reasonCodes: reasonCodes2,
|
|
10215
10279
|
recommendedActions,
|
|
10216
10280
|
caveats: [
|
|
@@ -10232,7 +10296,7 @@ function buildProjectRealityCheck(input) {
|
|
|
10232
10296
|
summary: "This change spans architectural boundaries. Verify that the dependency direction and runtime ownership still match the intended architecture.",
|
|
10233
10297
|
changedFiles: files.slice(0, 12),
|
|
10234
10298
|
decisionIds: [],
|
|
10235
|
-
evidence: contextEvidence2.slice(0,
|
|
10299
|
+
evidence: uniqueEvidence([...verificationRefs, ...contextEvidence2]).slice(0, 8),
|
|
10236
10300
|
reasonCodes: [rule.key, "cross_boundary_change"],
|
|
10237
10301
|
recommendedActions: [
|
|
10238
10302
|
"Check that the changed modules do not introduce a forbidden runtime dependency.",
|
|
@@ -10331,6 +10395,7 @@ function buildProjectRealityCheck(input) {
|
|
|
10331
10395
|
findings,
|
|
10332
10396
|
intentLedger,
|
|
10333
10397
|
unknownRegistry,
|
|
10398
|
+
evidence: allEvidence,
|
|
10334
10399
|
requiredActions,
|
|
10335
10400
|
watchItems,
|
|
10336
10401
|
reasonCodes: uniqueStrings3([
|
|
@@ -10399,11 +10464,24 @@ function renderProjectRealityCheckMarkdown(result) {
|
|
|
10399
10464
|
if (finding.decisionIds.length > 0) {
|
|
10400
10465
|
lines.push(` Decisions: ${finding.decisionIds.join(", ")}`);
|
|
10401
10466
|
}
|
|
10467
|
+
if (finding.evidence.length > 0) {
|
|
10468
|
+
lines.push(
|
|
10469
|
+
` Evidence: ${finding.evidence.slice(0, 4).map((item) => `${item.kind}:${item.label}`).join("; ")}`
|
|
10470
|
+
);
|
|
10471
|
+
}
|
|
10402
10472
|
if (finding.recommendedActions.length > 0) {
|
|
10403
10473
|
lines.push(` Action: ${finding.recommendedActions[0]}`);
|
|
10404
10474
|
}
|
|
10405
10475
|
}
|
|
10406
10476
|
}
|
|
10477
|
+
if (result.evidence.length > 0) {
|
|
10478
|
+
lines.push("", "Evidence:");
|
|
10479
|
+
lines.push(
|
|
10480
|
+
...result.evidence.slice(0, 10).map(
|
|
10481
|
+
(item) => `- ${item.kind}: ${item.label}${item.sourceRef ? ` (${item.sourceRef})` : ""}`
|
|
10482
|
+
)
|
|
10483
|
+
);
|
|
10484
|
+
}
|
|
10407
10485
|
if (result.requiredActions.length > 0) {
|
|
10408
10486
|
lines.push("", "Required actions:");
|
|
10409
10487
|
lines.push(...result.requiredActions.map((action) => `- ${action}`));
|
|
@@ -26096,8 +26174,18 @@ function printRecallResult(result) {
|
|
|
26096
26174
|
}
|
|
26097
26175
|
async function queryCommand(options) {
|
|
26098
26176
|
ensureConfigured();
|
|
26099
|
-
const
|
|
26100
|
-
|
|
26177
|
+
const searchMode = options.searchMode ?? "hybrid";
|
|
26178
|
+
if (!["keyword", "semantic", "hybrid"].includes(searchMode)) {
|
|
26179
|
+
throw new Error("--search-mode must be keyword, semantic, or hybrid");
|
|
26180
|
+
}
|
|
26181
|
+
const timeoutMs = Math.max(1e3, Math.min(options.timeoutMs ?? 3e4, 12e4));
|
|
26182
|
+
const client = createClient(timeoutMs);
|
|
26183
|
+
const result = await client.queryContext(options.query, options.maxTokens || 8e3, {
|
|
26184
|
+
searchMode,
|
|
26185
|
+
includeAnswerPack: options.includeAnswerPack,
|
|
26186
|
+
autoDecompose: options.autoDecompose,
|
|
26187
|
+
includeSharedContext: options.includeSharedContext
|
|
26188
|
+
});
|
|
26101
26189
|
const recommendedExecution = options.followRecommendation && result.recommended_tool ? await runRecommendedTool(result) : null;
|
|
26102
26190
|
if (options.json) {
|
|
26103
26191
|
printJson2(
|
|
@@ -34828,6 +34916,7 @@ async function projectIntelligenceBriefCommand(options) {
|
|
|
34828
34916
|
|
|
34829
34917
|
// src/commands/reality-check.ts
|
|
34830
34918
|
var import_node_child_process14 = require("child_process");
|
|
34919
|
+
var import_node_fs2 = __toESM(require("fs"));
|
|
34831
34920
|
var import_node_path2 = __toESM(require("path"));
|
|
34832
34921
|
var import_chalk12 = __toESM(require("chalk"));
|
|
34833
34922
|
function runGit2(args, cwd, options = {}) {
|
|
@@ -34922,8 +35011,263 @@ function parseDocument(value) {
|
|
|
34922
35011
|
contentPreview: rest.join(":").trim() || null
|
|
34923
35012
|
};
|
|
34924
35013
|
}
|
|
34925
|
-
function
|
|
34926
|
-
|
|
35014
|
+
function emptyAutoContext() {
|
|
35015
|
+
return {
|
|
35016
|
+
decisions: [],
|
|
35017
|
+
documents: [],
|
|
35018
|
+
evidence: [],
|
|
35019
|
+
verification: [],
|
|
35020
|
+
caveats: []
|
|
35021
|
+
};
|
|
35022
|
+
}
|
|
35023
|
+
function isRecord19(value) {
|
|
35024
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
35025
|
+
}
|
|
35026
|
+
function stringValue14(value) {
|
|
35027
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
35028
|
+
}
|
|
35029
|
+
function stringList3(value) {
|
|
35030
|
+
return Array.isArray(value) ? unique5(value.map((item) => typeof item === "string" ? item : void 0)) : [];
|
|
35031
|
+
}
|
|
35032
|
+
function readJsonRecord3(filePath) {
|
|
35033
|
+
try {
|
|
35034
|
+
const parsed = JSON.parse(import_node_fs2.default.readFileSync(filePath, "utf8"));
|
|
35035
|
+
return isRecord19(parsed) ? parsed : void 0;
|
|
35036
|
+
} catch {
|
|
35037
|
+
return void 0;
|
|
35038
|
+
}
|
|
35039
|
+
}
|
|
35040
|
+
var GENERIC_SCOPE_TOKENS = /* @__PURE__ */ new Set([
|
|
35041
|
+
"apps",
|
|
35042
|
+
"packages",
|
|
35043
|
+
"src",
|
|
35044
|
+
"test",
|
|
35045
|
+
"tests",
|
|
35046
|
+
"index",
|
|
35047
|
+
"server",
|
|
35048
|
+
"project",
|
|
35049
|
+
"snipara",
|
|
35050
|
+
"file",
|
|
35051
|
+
"files",
|
|
35052
|
+
"change",
|
|
35053
|
+
"changed"
|
|
35054
|
+
]);
|
|
35055
|
+
function scopeTokens(value) {
|
|
35056
|
+
const tokens = new Set(
|
|
35057
|
+
(value.toLowerCase().match(/[a-z0-9][a-z0-9_-]{2,}/g) ?? []).flatMap((token) => token.split(/[-_]/g)).filter((token) => token.length >= 3 && !GENERIC_SCOPE_TOKENS.has(token))
|
|
35058
|
+
);
|
|
35059
|
+
if (/packages\/cli\//i.test(value)) {
|
|
35060
|
+
tokens.add("cli");
|
|
35061
|
+
tokens.add("companion");
|
|
35062
|
+
}
|
|
35063
|
+
if (/project-intelligence-contracts/i.test(value)) {
|
|
35064
|
+
tokens.add("intelligence");
|
|
35065
|
+
tokens.add("intent");
|
|
35066
|
+
tokens.add("reality");
|
|
35067
|
+
}
|
|
35068
|
+
if (/mcp-server/i.test(value)) {
|
|
35069
|
+
tokens.add("mcp");
|
|
35070
|
+
tokens.add("context");
|
|
35071
|
+
tokens.add("retrieval");
|
|
35072
|
+
}
|
|
35073
|
+
if (/prisma|migration|document_chunks/i.test(value)) {
|
|
35074
|
+
tokens.add("database");
|
|
35075
|
+
tokens.add("schema");
|
|
35076
|
+
tokens.add("pgvector");
|
|
35077
|
+
}
|
|
35078
|
+
return tokens;
|
|
35079
|
+
}
|
|
35080
|
+
function matchingAnchors(text, changedFiles) {
|
|
35081
|
+
const textTokens = scopeTokens(text);
|
|
35082
|
+
return changedFiles.filter((file) => {
|
|
35083
|
+
const fileTokens = scopeTokens(file);
|
|
35084
|
+
return [...fileTokens].some((token) => textTokens.has(token));
|
|
35085
|
+
});
|
|
35086
|
+
}
|
|
35087
|
+
function hasFileOverlap(left, right) {
|
|
35088
|
+
const rightSet = new Set(right);
|
|
35089
|
+
return left.some((item) => rightSet.has(item));
|
|
35090
|
+
}
|
|
35091
|
+
function collectLocalReceiptContext(scope) {
|
|
35092
|
+
const context = emptyAutoContext();
|
|
35093
|
+
const workflowRef = ".snipara/workflow/current.json";
|
|
35094
|
+
const workflow2 = readJsonRecord3(import_node_path2.default.join(scope.root, workflowRef));
|
|
35095
|
+
if (workflow2) {
|
|
35096
|
+
const workflowId = stringValue14(workflow2.workflowId) ?? "managed workflow";
|
|
35097
|
+
const phases = Array.isArray(workflow2.phases) ? workflow2.phases.filter(isRecord19) : [];
|
|
35098
|
+
for (const phase of phases) {
|
|
35099
|
+
const phaseFiles = stringList3(phase.files);
|
|
35100
|
+
if (!hasFileOverlap(phaseFiles, scope.changedFiles)) continue;
|
|
35101
|
+
const title = stringValue14(phase.title) ?? stringValue14(phase.id) ?? "workflow phase";
|
|
35102
|
+
const status = stringValue14(phase.status) ?? "unknown";
|
|
35103
|
+
context.evidence.push({
|
|
35104
|
+
kind: "workflow",
|
|
35105
|
+
label: `${workflowId}: ${title} (${status})`,
|
|
35106
|
+
sourceRef: workflowRef,
|
|
35107
|
+
strength: status === "completed" ? 0.78 : 0.62
|
|
35108
|
+
});
|
|
35109
|
+
}
|
|
35110
|
+
}
|
|
35111
|
+
const finalReportRef = ".snipara/workflow/final-report.json";
|
|
35112
|
+
const finalReport = readJsonRecord3(import_node_path2.default.join(scope.root, finalReportRef));
|
|
35113
|
+
const changed = isRecord19(finalReport?.changed) ? finalReport.changed : void 0;
|
|
35114
|
+
const reportFiles = stringList3(changed?.files);
|
|
35115
|
+
const overlappingFiles = reportFiles.filter((file) => scope.changedFiles.includes(file));
|
|
35116
|
+
if (finalReport && overlappingFiles.length > 0) {
|
|
35117
|
+
const workflowId = stringValue14(finalReport.workflowId) ?? "completed workflow";
|
|
35118
|
+
const outcome = stringValue14(finalReport.outcome) ?? "unknown";
|
|
35119
|
+
context.evidence.push({
|
|
35120
|
+
kind: "workflow",
|
|
35121
|
+
label: `${workflowId}: final report (${outcome})`,
|
|
35122
|
+
sourceRef: finalReportRef,
|
|
35123
|
+
strength: outcome === "completed" ? 0.82 : 0.6
|
|
35124
|
+
});
|
|
35125
|
+
const repository = isRecord19(changed?.repository) ? changed.repository : void 0;
|
|
35126
|
+
const reportHead = stringValue14(repository?.head);
|
|
35127
|
+
const dirtyOverlap = hasFileOverlap(scope.dirtyFiles, overlappingFiles);
|
|
35128
|
+
const receiptMatchesCurrentHead = Boolean(reportHead && reportHead === scope.headRef);
|
|
35129
|
+
const evidence = isRecord19(finalReport.evidence) ? finalReport.evidence : void 0;
|
|
35130
|
+
const items = Array.isArray(evidence?.items) ? evidence.items.filter(isRecord19) : [];
|
|
35131
|
+
if (receiptMatchesCurrentHead && !dirtyOverlap) {
|
|
35132
|
+
for (const [index, item] of items.entries()) {
|
|
35133
|
+
if (stringValue14(item.status)?.toLowerCase() !== "passed") continue;
|
|
35134
|
+
const label = stringValue14(item.text);
|
|
35135
|
+
if (!label) continue;
|
|
35136
|
+
context.verification.push(label);
|
|
35137
|
+
context.evidence.push({
|
|
35138
|
+
kind: "test",
|
|
35139
|
+
label,
|
|
35140
|
+
sourceRef: `${finalReportRef}#evidence-${index + 1}`,
|
|
35141
|
+
strength: 0.88
|
|
35142
|
+
});
|
|
35143
|
+
}
|
|
35144
|
+
} else if (items.length > 0) {
|
|
35145
|
+
context.caveats.push(
|
|
35146
|
+
"A prior workflow report overlaps this scope, but its passed checks were not counted as current verification because the receipt does not cover the current dirty/HEAD state."
|
|
35147
|
+
);
|
|
35148
|
+
}
|
|
35149
|
+
}
|
|
35150
|
+
return context;
|
|
35151
|
+
}
|
|
35152
|
+
function isReviewedDecisionSignal(signal) {
|
|
35153
|
+
const status = signal.status.toUpperCase();
|
|
35154
|
+
if (!["ACTIVE", "APPROVED", "ACCEPTED", "CONFIRMED"].includes(status)) return false;
|
|
35155
|
+
const tags = signal.tags.map((tag) => tag.toLowerCase());
|
|
35156
|
+
if (tags.some(
|
|
35157
|
+
(tag) => tag === "workflow-phase" || tag === "release" || tag === "auto-captured" || tag === "review-pending" || tag.startsWith("journal:")
|
|
35158
|
+
)) {
|
|
35159
|
+
return false;
|
|
35160
|
+
}
|
|
35161
|
+
return /decision/i.test(signal.recommendedAction);
|
|
35162
|
+
}
|
|
35163
|
+
function decisionsFromTeamSync(response, changedFiles) {
|
|
35164
|
+
const decisions = [];
|
|
35165
|
+
for (const signal of response.whatChanged.decisions.filter(isReviewedDecisionSignal)) {
|
|
35166
|
+
const affectedAnchors = matchingAnchors(
|
|
35167
|
+
[signal.title, signal.summary, ...signal.tags].join(" "),
|
|
35168
|
+
changedFiles
|
|
35169
|
+
);
|
|
35170
|
+
if (affectedAnchors.length === 0) continue;
|
|
35171
|
+
decisions.push({
|
|
35172
|
+
id: signal.id,
|
|
35173
|
+
title: signal.title,
|
|
35174
|
+
decision: signal.summary,
|
|
35175
|
+
status: "approved",
|
|
35176
|
+
confidenceScore: signal.impact?.toUpperCase() === "HIGH" ? 0.9 : 0.84,
|
|
35177
|
+
affectedAnchors,
|
|
35178
|
+
evidence: [
|
|
35179
|
+
{
|
|
35180
|
+
kind: "decision",
|
|
35181
|
+
label: `${signal.id}: ${signal.title}`,
|
|
35182
|
+
sourceRef: signal.id,
|
|
35183
|
+
strength: signal.impact?.toUpperCase() === "HIGH" ? 0.9 : 0.84
|
|
35184
|
+
}
|
|
35185
|
+
]
|
|
35186
|
+
});
|
|
35187
|
+
}
|
|
35188
|
+
return decisions.slice(0, 8);
|
|
35189
|
+
}
|
|
35190
|
+
function contextQueryText(options, scope) {
|
|
35191
|
+
const task = options.task?.trim() || "Project Reality Check governing intent";
|
|
35192
|
+
const tokens = unique5([
|
|
35193
|
+
...scopeTokens(task),
|
|
35194
|
+
...scope.changedFiles.slice(0, 12).flatMap((file) => [...scopeTokens(file)]),
|
|
35195
|
+
"decision",
|
|
35196
|
+
"constraint"
|
|
35197
|
+
]).slice(0, 8);
|
|
35198
|
+
return tokens.join(" ");
|
|
35199
|
+
}
|
|
35200
|
+
function documentsFromContext(result, changedFiles) {
|
|
35201
|
+
return result.sections.filter((section) => section.file && section.file !== "(unknown)").map((section) => ({
|
|
35202
|
+
path: section.file,
|
|
35203
|
+
title: section.title,
|
|
35204
|
+
contentPreview: section.content.slice(0, 1600),
|
|
35205
|
+
kind: /adr|decision/i.test(`${section.file} ${section.title}`) ? "ADR" : "DOC",
|
|
35206
|
+
sourceRef: `${section.file}#L${section.lines[0]}-L${section.lines[1]}`,
|
|
35207
|
+
affectedAnchors: matchingAnchors(
|
|
35208
|
+
`${section.file} ${section.title} ${section.content.slice(0, 800)}`,
|
|
35209
|
+
changedFiles
|
|
35210
|
+
)
|
|
35211
|
+
})).slice(0, 8);
|
|
35212
|
+
}
|
|
35213
|
+
async function collectHostedAutoContext(client, options, scope) {
|
|
35214
|
+
const context = emptyAutoContext();
|
|
35215
|
+
const [teamSync2, documents] = await Promise.allSettled([
|
|
35216
|
+
client.getTeamSyncWhatChanged({
|
|
35217
|
+
limit: 50,
|
|
35218
|
+
branch: scope.branch,
|
|
35219
|
+
paths: scope.changedFiles.slice(0, 20),
|
|
35220
|
+
recentFiles: scope.changedFiles.slice(0, 10)
|
|
35221
|
+
}),
|
|
35222
|
+
client.queryContext(contextQueryText(options, scope), 1200, {
|
|
35223
|
+
searchMode: "keyword",
|
|
35224
|
+
includeMetadata: true,
|
|
35225
|
+
includeAnswerPack: false,
|
|
35226
|
+
autoDecompose: false,
|
|
35227
|
+
includeSharedContext: false,
|
|
35228
|
+
includeAllTiers: false
|
|
35229
|
+
})
|
|
35230
|
+
]);
|
|
35231
|
+
if (teamSync2.status === "fulfilled") {
|
|
35232
|
+
context.decisions = decisionsFromTeamSync(teamSync2.value, scope.changedFiles);
|
|
35233
|
+
} else {
|
|
35234
|
+
context.caveats.push(
|
|
35235
|
+
"Hosted reviewed-decision auto-linking was unavailable; explicit --decision inputs remain authoritative."
|
|
35236
|
+
);
|
|
35237
|
+
}
|
|
35238
|
+
if (documents.status === "fulfilled") {
|
|
35239
|
+
context.documents = documentsFromContext(documents.value, scope.changedFiles);
|
|
35240
|
+
} else {
|
|
35241
|
+
context.caveats.push(
|
|
35242
|
+
"Hosted document auto-context was unavailable; Reality Check continued with local and explicit evidence."
|
|
35243
|
+
);
|
|
35244
|
+
}
|
|
35245
|
+
return context;
|
|
35246
|
+
}
|
|
35247
|
+
function mergeAutoContext(local, hosted) {
|
|
35248
|
+
return {
|
|
35249
|
+
decisions: [...local.decisions, ...hosted.decisions],
|
|
35250
|
+
documents: [...local.documents, ...hosted.documents],
|
|
35251
|
+
evidence: [...local.evidence, ...hosted.evidence],
|
|
35252
|
+
verification: unique5([...local.verification, ...hosted.verification]),
|
|
35253
|
+
caveats: unique5([...local.caveats, ...hosted.caveats])
|
|
35254
|
+
};
|
|
35255
|
+
}
|
|
35256
|
+
function buildProjectRealityCheckForScope(options, scope, autoContext = emptyAutoContext()) {
|
|
35257
|
+
const decisionsById = new Map(
|
|
35258
|
+
autoContext.decisions.map((decision) => [decision.id, decision])
|
|
35259
|
+
);
|
|
35260
|
+
for (const [index, value] of (options.decision ?? []).entries()) {
|
|
35261
|
+
const decision = parseDecision(value, index);
|
|
35262
|
+
decisionsById.set(decision.id, decision);
|
|
35263
|
+
}
|
|
35264
|
+
const documentsByPath = new Map(
|
|
35265
|
+
autoContext.documents.map((document) => [document.path, document])
|
|
35266
|
+
);
|
|
35267
|
+
for (const value of options.document ?? []) {
|
|
35268
|
+
const document = parseDocument(value);
|
|
35269
|
+
documentsByPath.set(document.path, document);
|
|
35270
|
+
}
|
|
34927
35271
|
const result = buildProjectRealityCheck({
|
|
34928
35272
|
source: "local",
|
|
34929
35273
|
task: options.task,
|
|
@@ -34933,17 +35277,35 @@ function buildLocalProjectRealityCheck(options) {
|
|
|
34933
35277
|
changedFiles: scope.changedFiles,
|
|
34934
35278
|
dirtyFiles: scope.dirtyFiles,
|
|
34935
35279
|
diffSummary: scope.diffSummary,
|
|
34936
|
-
decisions:
|
|
34937
|
-
documents:
|
|
34938
|
-
|
|
35280
|
+
decisions: [...decisionsById.values()],
|
|
35281
|
+
documents: [...documentsByPath.values()],
|
|
35282
|
+
evidence: autoContext.evidence,
|
|
35283
|
+
verificationChecklist: unique5([...autoContext.verification, ...options.verification ?? []])
|
|
34939
35284
|
});
|
|
34940
|
-
|
|
34941
|
-
|
|
35285
|
+
const caveats = unique5([...result.caveats, ...scope.caveats, ...autoContext.caveats]);
|
|
35286
|
+
return { ...result, caveats };
|
|
35287
|
+
}
|
|
35288
|
+
function buildLocalProjectRealityCheck(options) {
|
|
35289
|
+
const scope = buildLocalGitScope(options);
|
|
35290
|
+
return buildProjectRealityCheckForScope(options, scope);
|
|
35291
|
+
}
|
|
35292
|
+
async function buildLocalProjectRealityCheckWithAutoContext(options, clientOverride) {
|
|
35293
|
+
const scope = buildLocalGitScope(options);
|
|
35294
|
+
let autoContext = collectLocalReceiptContext(scope);
|
|
35295
|
+
const configured = Boolean(clientOverride) || isConfigured({ cwd: scope.root });
|
|
35296
|
+
if (configured) {
|
|
35297
|
+
const timeoutMs = Math.max(1e3, Math.min(options.autoContextTimeoutMs ?? 12e3, 3e4));
|
|
35298
|
+
const client = clientOverride ?? createClient(timeoutMs, { cwd: scope.root });
|
|
35299
|
+
autoContext = mergeAutoContext(
|
|
35300
|
+
autoContext,
|
|
35301
|
+
await collectHostedAutoContext(client, options, scope)
|
|
35302
|
+
);
|
|
35303
|
+
} else {
|
|
35304
|
+
autoContext.caveats.push(
|
|
35305
|
+
"Hosted auto-context was skipped because this workspace is not configured; use --decision, --document, and --verification for explicit evidence."
|
|
35306
|
+
);
|
|
34942
35307
|
}
|
|
34943
|
-
return
|
|
34944
|
-
...result,
|
|
34945
|
-
caveats: [...result.caveats, ...scope.caveats]
|
|
34946
|
-
};
|
|
35308
|
+
return buildProjectRealityCheckForScope(options, scope, autoContext);
|
|
34947
35309
|
}
|
|
34948
35310
|
function printRealityCheck(result) {
|
|
34949
35311
|
console.log(import_chalk12.default.bold("Project Reality Check"));
|
|
@@ -34955,7 +35317,7 @@ function printRealityCheck(result) {
|
|
|
34955
35317
|
console.log(renderProjectRealityCheckMarkdown(result));
|
|
34956
35318
|
}
|
|
34957
35319
|
async function realityCheckCommand(options) {
|
|
34958
|
-
const result = buildLocalProjectRealityCheck(options);
|
|
35320
|
+
const result = options.autoContext === false ? buildLocalProjectRealityCheck(options) : await buildLocalProjectRealityCheckWithAutoContext(options);
|
|
34959
35321
|
if (options.json) {
|
|
34960
35322
|
console.log(JSON.stringify(result, null, 2));
|
|
34961
35323
|
} else {
|
|
@@ -34967,7 +35329,7 @@ async function realityCheckCommand(options) {
|
|
|
34967
35329
|
}
|
|
34968
35330
|
|
|
34969
35331
|
// src/commands/context-control.ts
|
|
34970
|
-
var
|
|
35332
|
+
var fs34 = __toESM(require("fs"));
|
|
34971
35333
|
var path33 = __toESM(require("path"));
|
|
34972
35334
|
var import_node_child_process15 = require("child_process");
|
|
34973
35335
|
var import_chalk13 = __toESM(require("chalk"));
|
|
@@ -35018,7 +35380,7 @@ function resolveGitDriftScopePaths(cwd) {
|
|
|
35018
35380
|
path33.join(".snipara", "decisions")
|
|
35019
35381
|
];
|
|
35020
35382
|
const manifestPath = resolveManifestPath(cwd);
|
|
35021
|
-
if (!
|
|
35383
|
+
if (!fs34.existsSync(manifestPath)) {
|
|
35022
35384
|
return normalizeScopePaths(scopePaths, cwd);
|
|
35023
35385
|
}
|
|
35024
35386
|
const manifestRead = readJsonFileSafe(manifestPath);
|
|
@@ -35068,12 +35430,12 @@ function receiptPathFor(receipt, cwd) {
|
|
|
35068
35430
|
return path33.resolve(cwd, CONTEXT_CONTROL_APPLIED_RELATIVE_DIR, `${receipt.receiptId}.json`);
|
|
35069
35431
|
}
|
|
35070
35432
|
function writeStableJsonFile(filePath, value) {
|
|
35071
|
-
|
|
35072
|
-
|
|
35433
|
+
fs34.mkdirSync(path33.dirname(filePath), { recursive: true });
|
|
35434
|
+
fs34.writeFileSync(filePath, `${stableDecisionJsonStringify(value)}
|
|
35073
35435
|
`, "utf8");
|
|
35074
35436
|
}
|
|
35075
35437
|
function readJsonFile4(filePath) {
|
|
35076
|
-
return JSON.parse(
|
|
35438
|
+
return JSON.parse(fs34.readFileSync(filePath, "utf8"));
|
|
35077
35439
|
}
|
|
35078
35440
|
function buildStateOperation(options) {
|
|
35079
35441
|
const target = assertContextControlTarget(
|
|
@@ -35265,7 +35627,7 @@ function applyLocalContextMutationPlan(options) {
|
|
|
35265
35627
|
baseRevisionAtApply: currentRevision
|
|
35266
35628
|
});
|
|
35267
35629
|
const receiptPath = receiptPathFor(pendingReceipt, cwd);
|
|
35268
|
-
if (
|
|
35630
|
+
if (fs34.existsSync(receiptPath)) {
|
|
35269
35631
|
const receipt2 = buildContextMutationApplyReceipt({
|
|
35270
35632
|
plan,
|
|
35271
35633
|
appliedAt: options.now,
|
|
@@ -35303,7 +35665,7 @@ function applyLocalContextMutationPlan(options) {
|
|
|
35303
35665
|
continue;
|
|
35304
35666
|
}
|
|
35305
35667
|
const absoluteTarget = path33.resolve(cwd, target);
|
|
35306
|
-
if (operation.mode === "create" &&
|
|
35668
|
+
if (operation.mode === "create" && fs34.existsSync(absoluteTarget)) {
|
|
35307
35669
|
throw new Error(`Refusing to overwrite existing context-control file: ${target}`);
|
|
35308
35670
|
}
|
|
35309
35671
|
writeStableJsonFile(absoluteTarget, operation.content ?? {});
|
|
@@ -35337,8 +35699,8 @@ function applyLocalContextMutationPlan(options) {
|
|
|
35337
35699
|
};
|
|
35338
35700
|
}
|
|
35339
35701
|
function listJsonFiles2(dir) {
|
|
35340
|
-
if (!
|
|
35341
|
-
return
|
|
35702
|
+
if (!fs34.existsSync(dir)) return [];
|
|
35703
|
+
return fs34.readdirSync(dir).filter((name) => name.endsWith(".json")).map((name) => path33.join(dir, name)).sort((left, right) => left.localeCompare(right));
|
|
35342
35704
|
}
|
|
35343
35705
|
function readJsonFileSafe(filePath) {
|
|
35344
35706
|
try {
|
|
@@ -35417,7 +35779,7 @@ function collectGitDriftSignals(cwd) {
|
|
|
35417
35779
|
}
|
|
35418
35780
|
function collectWorkflowDriftSignals(cwd) {
|
|
35419
35781
|
const workflowPath = path33.join(cwd, ".snipara", "workflow", "current.json");
|
|
35420
|
-
if (!
|
|
35782
|
+
if (!fs34.existsSync(workflowPath)) {
|
|
35421
35783
|
return [
|
|
35422
35784
|
{
|
|
35423
35785
|
id: "workflow-state-missing",
|
|
@@ -35560,7 +35922,7 @@ function collectContextControlDriftSignals(cwd) {
|
|
|
35560
35922
|
function collectProjectContextManifestDriftSignals(cwd) {
|
|
35561
35923
|
const manifestPath = resolveManifestPath(cwd);
|
|
35562
35924
|
const relative11 = toProjectRelativePath4(manifestPath, cwd);
|
|
35563
|
-
if (!
|
|
35925
|
+
if (!fs34.existsSync(manifestPath)) {
|
|
35564
35926
|
return [
|
|
35565
35927
|
{
|
|
35566
35928
|
id: "project-context-manifest-missing",
|
|
@@ -35763,23 +36125,23 @@ function resolveHostedContextSources(cwd, manifestPath, report) {
|
|
|
35763
36125
|
if (!report.manifest || report.status === "invalid") {
|
|
35764
36126
|
throw new Error("ProjectContext manifest is invalid; run context-control validate first.");
|
|
35765
36127
|
}
|
|
35766
|
-
const workspaceRoot2 =
|
|
36128
|
+
const workspaceRoot2 = fs34.realpathSync(cwd);
|
|
35767
36129
|
return report.manifest.sources.map((source2) => {
|
|
35768
36130
|
const candidate = path33.resolve(cwd, source2.path);
|
|
35769
|
-
if (!
|
|
36131
|
+
if (!fs34.existsSync(candidate)) {
|
|
35770
36132
|
throw new Error(`ProjectContext source is missing: ${source2.path}`);
|
|
35771
36133
|
}
|
|
35772
|
-
if (
|
|
36134
|
+
if (fs34.lstatSync(candidate).isSymbolicLink()) {
|
|
35773
36135
|
throw new Error(`ProjectContext source symlinks are not allowed: ${source2.path}`);
|
|
35774
36136
|
}
|
|
35775
|
-
const canonical =
|
|
36137
|
+
const canonical = fs34.realpathSync(candidate);
|
|
35776
36138
|
if (canonical !== workspaceRoot2 && !canonical.startsWith(`${workspaceRoot2}${path33.sep}`)) {
|
|
35777
36139
|
throw new Error(`ProjectContext source escapes the workspace: ${source2.path}`);
|
|
35778
36140
|
}
|
|
35779
|
-
if (!
|
|
36141
|
+
if (!fs34.statSync(canonical).isFile()) {
|
|
35780
36142
|
throw new Error(`ProjectContext source must be a file: ${source2.path}`);
|
|
35781
36143
|
}
|
|
35782
|
-
const content =
|
|
36144
|
+
const content = fs34.readFileSync(canonical, "utf8");
|
|
35783
36145
|
if (Buffer.byteLength(content, "utf8") > 1e6) {
|
|
35784
36146
|
throw new Error(`ProjectContext source exceeds 1 MB: ${source2.path}`);
|
|
35785
36147
|
}
|
|
@@ -35914,7 +36276,7 @@ function uniqueStrings22(values) {
|
|
|
35914
36276
|
|
|
35915
36277
|
// src/commands/references.ts
|
|
35916
36278
|
var crypto6 = __toESM(require("crypto"));
|
|
35917
|
-
var
|
|
36279
|
+
var fs35 = __toESM(require("fs"));
|
|
35918
36280
|
var path34 = __toESM(require("path"));
|
|
35919
36281
|
var import_chalk14 = __toESM(require("chalk"));
|
|
35920
36282
|
var MANIFEST_VERSION2 = "snipara.references.v1";
|
|
@@ -35998,13 +36360,13 @@ function toRelative(root, file) {
|
|
|
35998
36360
|
return path34.relative(root, file).split(path34.sep).join("/");
|
|
35999
36361
|
}
|
|
36000
36362
|
function ensureParentDir(file) {
|
|
36001
|
-
|
|
36363
|
+
fs35.mkdirSync(path34.dirname(file), { recursive: true });
|
|
36002
36364
|
}
|
|
36003
36365
|
function walkFiles(root, extensions, maxFiles, files = []) {
|
|
36004
36366
|
if (files.length >= maxFiles) {
|
|
36005
36367
|
return files;
|
|
36006
36368
|
}
|
|
36007
|
-
for (const entry of
|
|
36369
|
+
for (const entry of fs35.readdirSync(root, { withFileTypes: true })) {
|
|
36008
36370
|
if (files.length >= maxFiles) {
|
|
36009
36371
|
break;
|
|
36010
36372
|
}
|
|
@@ -36025,7 +36387,7 @@ function collectReferenceItems(root, files, allowDomains, denyDomains) {
|
|
|
36025
36387
|
const byUrl = /* @__PURE__ */ new Map();
|
|
36026
36388
|
const discoveredAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
36027
36389
|
for (const file of files) {
|
|
36028
|
-
const content =
|
|
36390
|
+
const content = fs35.readFileSync(file, "utf-8");
|
|
36029
36391
|
const lines = content.split(/\r?\n/);
|
|
36030
36392
|
const markdownLink = /\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)/g;
|
|
36031
36393
|
const bareUrl = /https?:\/\/[^\s<>"'`]+/g;
|
|
@@ -36091,7 +36453,7 @@ function scanReferences(options = {}) {
|
|
|
36091
36453
|
items
|
|
36092
36454
|
};
|
|
36093
36455
|
ensureParentDir(outputPath);
|
|
36094
|
-
|
|
36456
|
+
fs35.writeFileSync(outputPath, `${JSON.stringify(manifest, null, 2)}
|
|
36095
36457
|
`, "utf-8");
|
|
36096
36458
|
return {
|
|
36097
36459
|
manifest,
|
|
@@ -36105,7 +36467,7 @@ function scanReferences(options = {}) {
|
|
|
36105
36467
|
};
|
|
36106
36468
|
}
|
|
36107
36469
|
function readManifest2(file) {
|
|
36108
|
-
const manifest = JSON.parse(
|
|
36470
|
+
const manifest = JSON.parse(fs35.readFileSync(file, "utf-8"));
|
|
36109
36471
|
if (manifest.version !== MANIFEST_VERSION2 || !Array.isArray(manifest.items)) {
|
|
36110
36472
|
throw new Error(`${file} is not a ${MANIFEST_VERSION2} manifest`);
|
|
36111
36473
|
}
|
|
@@ -36190,7 +36552,7 @@ async function fetchReference(item, outputDir, destinationPrefix, timeoutMs, max
|
|
|
36190
36552
|
bodyHash: hash
|
|
36191
36553
|
});
|
|
36192
36554
|
ensureParentDir(snapshotPath);
|
|
36193
|
-
|
|
36555
|
+
fs35.writeFileSync(snapshotPath, markdown, "utf-8");
|
|
36194
36556
|
return {
|
|
36195
36557
|
item,
|
|
36196
36558
|
fetchedAt,
|
|
@@ -36300,7 +36662,7 @@ async function ingestReferences(options = {}) {
|
|
|
36300
36662
|
});
|
|
36301
36663
|
}
|
|
36302
36664
|
}
|
|
36303
|
-
|
|
36665
|
+
fs35.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}
|
|
36304
36666
|
`, "utf-8");
|
|
36305
36667
|
if (options.reindex && client) {
|
|
36306
36668
|
await client.reindex({ kind: "doc", mode: "incremental" });
|
|
@@ -36354,7 +36716,7 @@ async function referencesIngestCommand(options) {
|
|
|
36354
36716
|
// src/commands/run.ts
|
|
36355
36717
|
var import_node_child_process16 = require("child_process");
|
|
36356
36718
|
var import_node_crypto12 = require("crypto");
|
|
36357
|
-
var
|
|
36719
|
+
var fs36 = __toESM(require("fs"));
|
|
36358
36720
|
var path35 = __toESM(require("path"));
|
|
36359
36721
|
var import_chalk15 = __toESM(require("chalk"));
|
|
36360
36722
|
|
|
@@ -36363,21 +36725,21 @@ var REGISTRY_VERSION = "project-intelligence.policy-gates.registry.v1";
|
|
|
36363
36725
|
function normalizeChangedFiles(changedFiles) {
|
|
36364
36726
|
return [...new Set((changedFiles ?? []).map((file) => file.trim()).filter(Boolean))];
|
|
36365
36727
|
}
|
|
36366
|
-
function
|
|
36728
|
+
function isRecord20(value) {
|
|
36367
36729
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
36368
36730
|
}
|
|
36369
|
-
function
|
|
36731
|
+
function stringValue15(value) {
|
|
36370
36732
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
36371
36733
|
}
|
|
36372
36734
|
function nestedRecord3(root, keys) {
|
|
36373
36735
|
let current = root;
|
|
36374
36736
|
for (const key of keys) {
|
|
36375
|
-
if (!
|
|
36737
|
+
if (!isRecord20(current) || !isRecord20(current[key])) {
|
|
36376
36738
|
return {};
|
|
36377
36739
|
}
|
|
36378
36740
|
current = current[key];
|
|
36379
36741
|
}
|
|
36380
|
-
return
|
|
36742
|
+
return isRecord20(current) ? current : {};
|
|
36381
36743
|
}
|
|
36382
36744
|
function combinedText(input) {
|
|
36383
36745
|
return [input.task, input.diffSummary, ...input.changedFiles ?? []].filter(Boolean).join("\n").toLowerCase();
|
|
@@ -36547,7 +36909,7 @@ function evaluateProjectPolicyGates(input) {
|
|
|
36547
36909
|
);
|
|
36548
36910
|
}
|
|
36549
36911
|
const guardEval = guardEvaluation2(input.guard?.payload);
|
|
36550
|
-
const guardDecision =
|
|
36912
|
+
const guardDecision = stringValue15(guardEval.decision)?.toUpperCase();
|
|
36551
36913
|
if (guardDecision === "BLOCKED" || input.release && input.guard?.status !== void 0 && input.guard.status !== 0) {
|
|
36552
36914
|
gates.push(
|
|
36553
36915
|
gate({
|
|
@@ -36785,8 +37147,8 @@ var GUARD_MAX_BUFFER_BYTES = 16 * 1024 * 1024;
|
|
|
36785
37147
|
var RAW_OUTPUT_PREVIEW_BYTES = 64e3;
|
|
36786
37148
|
var ADVISOR_RECEIPT_WRITE_LIMIT = 6;
|
|
36787
37149
|
function buildProjectIntelligenceRunEnvelope(startedAt = /* @__PURE__ */ new Date()) {
|
|
36788
|
-
const sniparaSessionId =
|
|
36789
|
-
const codexSessionId =
|
|
37150
|
+
const sniparaSessionId = stringValue16(process.env.SNIPARA_SESSION_ID)?.slice(0, 200);
|
|
37151
|
+
const codexSessionId = stringValue16(process.env.CODEX_SESSION_ID)?.slice(0, 200);
|
|
36790
37152
|
return {
|
|
36791
37153
|
version: "project-intelligence.judgment-run-envelope.v1",
|
|
36792
37154
|
runId: sniparaSessionId ?? codexSessionId ?? `judgment-run:${(0, import_node_crypto12.randomUUID)()}`,
|
|
@@ -36800,7 +37162,7 @@ function normalizeStringList6(values) {
|
|
|
36800
37162
|
function uniqueStrings23(values) {
|
|
36801
37163
|
return [...new Set(values.map((value) => value.trim()).filter(Boolean))];
|
|
36802
37164
|
}
|
|
36803
|
-
function
|
|
37165
|
+
function isRecord21(value) {
|
|
36804
37166
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
36805
37167
|
}
|
|
36806
37168
|
function guardPayload(guard) {
|
|
@@ -36813,7 +37175,7 @@ function readOutcomeReceipts(files) {
|
|
|
36813
37175
|
const receipts = [];
|
|
36814
37176
|
for (const file of normalizeStringList6(files)) {
|
|
36815
37177
|
const resolved = path35.resolve(process.cwd(), file);
|
|
36816
|
-
const parsed = JSON.parse(
|
|
37178
|
+
const parsed = JSON.parse(fs36.readFileSync(resolved, "utf8"));
|
|
36817
37179
|
receipts.push(...outcomeReceiptsFromUnknown(parsed));
|
|
36818
37180
|
}
|
|
36819
37181
|
return receipts;
|
|
@@ -36822,13 +37184,13 @@ function outcomeReceiptsFromUnknown(value) {
|
|
|
36822
37184
|
if (Array.isArray(value)) {
|
|
36823
37185
|
return value.flatMap(outcomeReceiptsFromUnknown);
|
|
36824
37186
|
}
|
|
36825
|
-
if (!
|
|
37187
|
+
if (!isRecord21(value)) {
|
|
36826
37188
|
return [];
|
|
36827
37189
|
}
|
|
36828
37190
|
if (value.version === "snipara.outcome_intelligence.receipt.v0") {
|
|
36829
37191
|
return [value];
|
|
36830
37192
|
}
|
|
36831
|
-
if (
|
|
37193
|
+
if (isRecord21(value.outcomeReceipt)) {
|
|
36832
37194
|
return outcomeReceiptsFromUnknown(value.outcomeReceipt);
|
|
36833
37195
|
}
|
|
36834
37196
|
if (Array.isArray(value.outcomeReceipts)) {
|
|
@@ -36846,11 +37208,11 @@ function outputPreview(value) {
|
|
|
36846
37208
|
return `${value.slice(0, RAW_OUTPUT_PREVIEW_BYTES)}
|
|
36847
37209
|
...[truncated]`;
|
|
36848
37210
|
}
|
|
36849
|
-
function
|
|
37211
|
+
function stringValue16(value) {
|
|
36850
37212
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
36851
37213
|
}
|
|
36852
37214
|
function servedJudgmentIdForRun(options, brief) {
|
|
36853
|
-
return
|
|
37215
|
+
return stringValue16(options.servedJudgmentId) ?? stringValue16(brief.servedJudgmentId) ?? servedJudgmentIdFromContext(brief.resumeContext) ?? servedJudgmentIdFromContext(brief.verificationPlan);
|
|
36854
37216
|
}
|
|
36855
37217
|
function advisorMeasurementState(args) {
|
|
36856
37218
|
if (args.agentDecision === "blocked") return "blocked";
|
|
@@ -36927,7 +37289,7 @@ function boundedLifecycleText(value, maxChars) {
|
|
|
36927
37289
|
return value.trim().replace(/\s+/g, " ").slice(0, maxChars);
|
|
36928
37290
|
}
|
|
36929
37291
|
function advisorRecommendationPlanScope(args) {
|
|
36930
|
-
const requestedRecommendationId =
|
|
37292
|
+
const requestedRecommendationId = stringValue16(args.options.advisorRecommendationId) ?? null;
|
|
36931
37293
|
if (requestedRecommendationId) {
|
|
36932
37294
|
const targeted = requestedRecommendationId === args.recommendationId;
|
|
36933
37295
|
return {
|
|
@@ -37235,7 +37597,7 @@ async function recordFirstPartyAdvisorReceipts(args) {
|
|
|
37235
37597
|
};
|
|
37236
37598
|
}
|
|
37237
37599
|
const client = createClient(1e4);
|
|
37238
|
-
const
|
|
37600
|
+
const verificationEvidence2 = args.verificationEvidence ?? [];
|
|
37239
37601
|
const outcomeReceipts = args.outcomeReceipts ?? [];
|
|
37240
37602
|
const selectedRecommendations = allRecommendations.slice(0, ADVISOR_RECEIPT_WRITE_LIMIT);
|
|
37241
37603
|
const overflowWrites = allRecommendations.slice(ADVISOR_RECEIPT_WRITE_LIMIT).map((recommendation) => skippedAdvisorReceiptWrite(recommendation, "write_limit_exceeded"));
|
|
@@ -37293,7 +37655,7 @@ async function recordFirstPartyAdvisorReceipts(args) {
|
|
|
37293
37655
|
recommendation,
|
|
37294
37656
|
recommendationIndex,
|
|
37295
37657
|
totalRecommendations: allRecommendations.length,
|
|
37296
|
-
verificationEvidence,
|
|
37658
|
+
verificationEvidence: verificationEvidence2,
|
|
37297
37659
|
lifecycle,
|
|
37298
37660
|
planScope,
|
|
37299
37661
|
measurementState,
|
|
@@ -37379,7 +37741,7 @@ function runGuard(options, changedFiles) {
|
|
|
37379
37741
|
let payload;
|
|
37380
37742
|
try {
|
|
37381
37743
|
const parsed = JSON.parse(result.stdout);
|
|
37382
|
-
if (
|
|
37744
|
+
if (isRecord21(parsed)) {
|
|
37383
37745
|
payload = parsed;
|
|
37384
37746
|
}
|
|
37385
37747
|
} catch {
|
|
@@ -37500,7 +37862,7 @@ async function buildProjectIntelligenceRun(options) {
|
|
|
37500
37862
|
decision: brief.projectPolicyDecision
|
|
37501
37863
|
} : void 0
|
|
37502
37864
|
});
|
|
37503
|
-
const
|
|
37865
|
+
const verificationEvidence2 = verificationEvidenceFromRun({
|
|
37504
37866
|
guard,
|
|
37505
37867
|
packageReview,
|
|
37506
37868
|
policyGates
|
|
@@ -37509,7 +37871,7 @@ async function buildProjectIntelligenceRun(options) {
|
|
|
37509
37871
|
options,
|
|
37510
37872
|
brief,
|
|
37511
37873
|
judgmentCard,
|
|
37512
|
-
verificationEvidence,
|
|
37874
|
+
verificationEvidence: verificationEvidence2,
|
|
37513
37875
|
outcomeReceipts,
|
|
37514
37876
|
runEnvelope
|
|
37515
37877
|
});
|
|
@@ -37572,10 +37934,10 @@ async function projectIntelligenceRunCommand(options) {
|
|
|
37572
37934
|
if (result.guard) {
|
|
37573
37935
|
console.log(import_chalk15.default.bold("Guard"));
|
|
37574
37936
|
console.log(`Status: ${result.guard.status}`);
|
|
37575
|
-
const actionCards =
|
|
37937
|
+
const actionCards = isRecord21(result.guard.payload) ? result.guard.payload.actionCards : [];
|
|
37576
37938
|
if (Array.isArray(actionCards) && actionCards.length > 0) {
|
|
37577
37939
|
for (const card of actionCards.slice(0, 6)) {
|
|
37578
|
-
if (!
|
|
37940
|
+
if (!isRecord21(card)) continue;
|
|
37579
37941
|
console.log(`- ${card.kind}: ${card.title ?? card.reason ?? "guard action"}`);
|
|
37580
37942
|
}
|
|
37581
37943
|
}
|
|
@@ -37640,7 +38002,7 @@ async function projectIntelligenceRunCommand(options) {
|
|
|
37640
38002
|
}
|
|
37641
38003
|
|
|
37642
38004
|
// src/commands/policy-ledger-sync.ts
|
|
37643
|
-
var
|
|
38005
|
+
var fs37 = __toESM(require("fs"));
|
|
37644
38006
|
var path36 = __toESM(require("path"));
|
|
37645
38007
|
var POLICY_LEDGER_SYNC_REPORT_VERSION = "snipara.workflow_policy_ledger_sync.v0";
|
|
37646
38008
|
function buildPolicyLedgerSyncReport(options = {}) {
|
|
@@ -37788,12 +38150,12 @@ function statusForChoiceClass(choiceClass) {
|
|
|
37788
38150
|
return "modified";
|
|
37789
38151
|
}
|
|
37790
38152
|
function readJsonFiles(directory, cwd) {
|
|
37791
|
-
if (!
|
|
38153
|
+
if (!fs37.existsSync(directory)) {
|
|
37792
38154
|
return [];
|
|
37793
38155
|
}
|
|
37794
|
-
return
|
|
38156
|
+
return fs37.readdirSync(directory).filter((fileName) => fileName.endsWith(".json")).sort().map((fileName) => {
|
|
37795
38157
|
const filePath = path36.join(directory, fileName);
|
|
37796
|
-
const parsed = JSON.parse(
|
|
38158
|
+
const parsed = JSON.parse(fs37.readFileSync(filePath, "utf8"));
|
|
37797
38159
|
return { parsed, relativePath: toProjectRelativePath5(filePath, cwd) };
|
|
37798
38160
|
});
|
|
37799
38161
|
}
|
|
@@ -37998,7 +38360,11 @@ function collectOption(value, previous = []) {
|
|
|
37998
38360
|
return [...previous, value];
|
|
37999
38361
|
}
|
|
38000
38362
|
function configureRealityCheckCommand(command) {
|
|
38001
|
-
return command.description("Run a Project Reality Check against local or supplied change scope").option("--task <task>", "Task or change summary").option("--branch <branch>", "Branch to scope the check").option("--base <ref>", "Base ref for committed local changes (default: upstream)").option("--changed-files <files...>", "Changed files to analyze").option("--diff-summary <summary>", "Natural-language diff summary").option("--decision <decision...>", "Decision or intent in ID: text form").option("--document <document...>", "Document/context hint in path: preview form").option("--verification <item...>", "Verification evidence or checklist item").option("--no-
|
|
38363
|
+
return command.description("Run a Project Reality Check against local or supplied change scope").option("--task <task>", "Task or change summary").option("--branch <branch>", "Branch to scope the check").option("--base <ref>", "Base ref for committed local changes (default: upstream)").option("--changed-files <files...>", "Changed files to analyze").option("--diff-summary <summary>", "Natural-language diff summary").option("--decision <decision...>", "Decision or intent in ID: text form").option("--document <document...>", "Document/context hint in path: preview form").option("--verification <item...>", "Verification evidence or checklist item").option("--no-auto-context", "Disable bounded hosted/local context auto-linking").option(
|
|
38364
|
+
"--auto-context-timeout-ms <number>",
|
|
38365
|
+
"Timeout for each hosted auto-context source",
|
|
38366
|
+
"12000"
|
|
38367
|
+
).option("--no-include-dirty", "Exclude dirty working-tree files from local scope").option("--enforce", "Exit non-zero for review-required or blocking findings").option("-d, --dir <directory>", "Project directory (default: current)").option("--json", "Print raw JSON").action(async (options) => {
|
|
38002
38368
|
await realityCheckCommand({
|
|
38003
38369
|
task: options.task,
|
|
38004
38370
|
branch: options.branch,
|
|
@@ -38008,6 +38374,8 @@ function configureRealityCheckCommand(command) {
|
|
|
38008
38374
|
decision: options.decision,
|
|
38009
38375
|
document: options.document,
|
|
38010
38376
|
verification: options.verification,
|
|
38377
|
+
autoContext: options.autoContext !== false,
|
|
38378
|
+
autoContextTimeoutMs: Number.parseInt(options.autoContextTimeoutMs, 10),
|
|
38011
38379
|
includeDirty: options.includeDirty,
|
|
38012
38380
|
enforce: Boolean(options.enforce),
|
|
38013
38381
|
dir: options.dir,
|
|
@@ -38487,13 +38855,18 @@ program.command("memory-guard").description(
|
|
|
38487
38855
|
);
|
|
38488
38856
|
program.command("query").description(
|
|
38489
38857
|
"Search project documents, parsed files, and current truth through hosted Snipara context"
|
|
38490
|
-
).requiredOption("-q, --query <query>", "Search query").option("-m, --max-tokens <number>", "Maximum tokens", "8000").option(
|
|
38858
|
+
).requiredOption("-q, --query <query>", "Search query").option("-m, --max-tokens <number>", "Maximum tokens", "8000").option("--search-mode <mode>", "Search mode: keyword|semantic|hybrid", "hybrid").option("--timeout-ms <number>", "Hosted context query timeout in milliseconds", "30000").option("--no-answer-pack", "Skip Answer Pack generation").option("--no-auto-decompose", "Disable automatic query decomposition").option("--no-shared-context", "Exclude linked shared context").option(
|
|
38491
38859
|
"--follow-recommendation",
|
|
38492
38860
|
"Automatically execute the recommended structural tool when Snipara returns one"
|
|
38493
38861
|
).option("--json", "Print raw JSON").action(async (options) => {
|
|
38494
38862
|
await queryCommand({
|
|
38495
38863
|
query: options.query,
|
|
38496
38864
|
maxTokens: parseInt(options.maxTokens, 10),
|
|
38865
|
+
searchMode: options.searchMode,
|
|
38866
|
+
timeoutMs: parseInt(options.timeoutMs, 10),
|
|
38867
|
+
includeAnswerPack: options.answerPack !== false,
|
|
38868
|
+
autoDecompose: options.autoDecompose !== false,
|
|
38869
|
+
includeSharedContext: options.sharedContext !== false,
|
|
38497
38870
|
followRecommendation: Boolean(options.followRecommendation),
|
|
38498
38871
|
json: options.json
|
|
38499
38872
|
});
|
|
@@ -40262,6 +40635,7 @@ if (require.main === module) {
|
|
|
40262
40635
|
buildLocalProjectContextValidationReport,
|
|
40263
40636
|
buildLocalProjectDriftReport,
|
|
40264
40637
|
buildLocalProjectRealityCheck,
|
|
40638
|
+
buildLocalProjectRealityCheckWithAutoContext,
|
|
40265
40639
|
buildLocalShortestPathResult,
|
|
40266
40640
|
buildLocalSourceSnapshot,
|
|
40267
40641
|
buildLocalSourceStatus,
|
package/docs/FULL_REFERENCE.md
CHANGED
|
@@ -913,6 +913,12 @@ headers, pass the same value as `correlation_context.session_id` on
|
|
|
913
913
|
`snipara_context_query`, `snipara_recall`, `snipara_search`, `snipara_ask`, and
|
|
914
914
|
`snipara_get_chunk`.
|
|
915
915
|
|
|
916
|
+
Companion's own Hosted MCP client always forwards the configured workspace
|
|
917
|
+
`sessionId` as `X-Snipara-Session-Id`. For the five correlated retrieval tools,
|
|
918
|
+
it also supplies `client: "snipara-companion"` when the caller did not provide a
|
|
919
|
+
client label. The session value is telemetry-only: it never authenticates the
|
|
920
|
+
request, changes project scope, or overrides explicit per-call correlation.
|
|
921
|
+
|
|
916
922
|
OpenClaw hooks remain separate:
|
|
917
923
|
|
|
918
924
|
```bash
|
|
@@ -1044,6 +1050,7 @@ npx -y snipara-companion@latest plan --query "plan the auth refactor" --write-pl
|
|
|
1044
1050
|
npx -y snipara-companion@latest task-commit --summary "Shipped auth refactor" --files apps/web/src/lib/auth.ts
|
|
1045
1051
|
|
|
1046
1052
|
snipara-companion query --query "auth middleware"
|
|
1053
|
+
snipara-companion query --query "auth middleware" --search-mode keyword --no-answer-pack --timeout-ms 30000
|
|
1047
1054
|
snipara-companion query --query "who calls src.mcp_transport.handle_call_tool" --follow-recommendation
|
|
1048
1055
|
snipara-companion status
|
|
1049
1056
|
snipara-companion brief --task "ship auth hardening" --changed-files apps/web/src/lib/auth.ts tests/auth.test.ts --diff-summary "auth hardening"
|
|
@@ -1266,7 +1273,13 @@ snipara-companion reality-check \
|
|
|
1266
1273
|
|
|
1267
1274
|
The command reads the local Git scope by default, includes dirty files unless
|
|
1268
1275
|
`--no-include-dirty` is set, and also accepts explicit `--changed-files` for
|
|
1269
|
-
hooks or CI collectors.
|
|
1276
|
+
hooks or CI collectors. When the workspace is configured, bounded auto-context
|
|
1277
|
+
loads reviewed Team Sync decisions, a narrow keyword document query, and local
|
|
1278
|
+
workflow receipts in parallel. Explicit `--decision`, `--document`, and
|
|
1279
|
+
`--verification` values take precedence. Use `--no-auto-context` for a purely
|
|
1280
|
+
local/explicit run or `--auto-context-timeout-ms` to tighten the hosted budget.
|
|
1281
|
+
Verification and workflow sources are retained in each finding's `evidence`
|
|
1282
|
+
array and in the top-level evidence summary. `--enforce` exits non-zero for `review_required` or
|
|
1270
1283
|
`blocking` findings, but should stay opt-in until the matched surfaces,
|
|
1271
1284
|
verification signals, and project-specific thresholds have been calibrated.
|
|
1272
1285
|
Intent can be supplied as structured sections inside `--decision` or
|
|
@@ -1455,7 +1468,7 @@ snipara-companion workflow scaffold \
|
|
|
1455
1468
|
|
|
1456
1469
|
Semantics:
|
|
1457
1470
|
|
|
1458
|
-
- `snipara-companion query --follow-recommendation` = execute the hosted recommended structural tool instead of only printing it
|
|
1471
|
+
- `snipara-companion query --follow-recommendation` = execute the hosted recommended structural tool instead of only printing it; context retrieval defaults to a 30-second timeout and supports `--search-mode keyword|semantic|hybrid`, `--no-answer-pack`, `--no-auto-decompose`, and `--no-shared-context`
|
|
1459
1472
|
- `snipara-companion workflow run --mode lite` = zero mandatory hosted calls for small known-file work
|
|
1460
1473
|
- `snipara-companion workflow run --mode standard` = context query plus automatic `snipara_code_*` follow-up when Snipara recommends one
|
|
1461
1474
|
- `snipara-companion workflow run --mode auto` = routes to lite, standard, full, or orchestrate from task intent
|
|
@@ -1467,7 +1480,7 @@ Semantics:
|
|
|
1467
1480
|
- `snipara-companion status` = top-level agentic work status across local workflow state, git dirtiness, and Team Sync carryover
|
|
1468
1481
|
- `snipara-companion source init|sync|status|snapshot|watch` = automatic local source activation for folders with or without Git metadata; writes `.snipara/source/latest.json`, previews document sync, and refreshes the local code overlay cache
|
|
1469
1482
|
- `snipara-companion brief` = short alias for `snipara-companion intelligence brief`
|
|
1470
|
-
- `snipara-companion reality-check` =
|
|
1483
|
+
- `snipara-companion reality-check` = Project Reality Check plus Intent Ledger, Unknown Registry, bounded auto-context, and inspectable evidence for supplied or Git-derived changed files; `--no-auto-context` keeps it local/explicit and `--enforce` is an opt-in strict mode for calibrated hooks
|
|
1471
1484
|
- `snipara-companion timeline` = local timeline of workflow starts, phase starts, phase commits, final commits, and Team Sync handoffs
|
|
1472
1485
|
- `snipara-companion workflow timeline` = append-only activity timeline from `.snipara/activity/timeline.jsonl`, including workflow, Producer Loop, Decision Request, and Team Sync events emitted by Companion commands; add `--export md` for a redacted Markdown artifact
|
|
1473
1486
|
- `snipara-companion workflow session` = writes and prints Session Snapshot V0 at `.snipara/activity/session.json` with latest activity, risk, touched files, next action, advisory Intent Detection V0 intent/confidence/signals/suggested mode, workflow/session counts, Producer Loop calibration, decision counts, Team Sync counts, and `hardRoutingAllowed=false`
|