snipara-companion 3.6.2 → 3.6.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/dist/index.d.ts +42 -0
- package/dist/index.js +255 -39
- package/docs/CODE_GRAPH.md +37 -5
- 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.6.4
|
|
6
|
+
|
|
7
|
+
- Correlates hosted Judgment responses with their immutable snapshot, append-only
|
|
8
|
+
exposure, run, and served-Judgment identities.
|
|
9
|
+
- Sends those canonical identities back with advisor influence receipts so the
|
|
10
|
+
backend can reject mismatched client correlation data.
|
|
11
|
+
- Keeps hosted Judgment failures best-effort for local runs while reporting the
|
|
12
|
+
failure boundary explicitly.
|
|
13
|
+
|
|
14
|
+
## New In 3.6.3
|
|
15
|
+
|
|
16
|
+
- Labels every semantic `confidence` value as an uncalibrated
|
|
17
|
+
`heuristic_prior`, preserving the numeric compatibility field without
|
|
18
|
+
presenting it as a measured probability.
|
|
19
|
+
- Loads bounded, literal project naming terms from
|
|
20
|
+
`.snipara/semantic-rules.json`; teams can extend or replace English defaults
|
|
21
|
+
without enabling arbitrary regular expressions.
|
|
22
|
+
- Keeps historical regression associations strictly shadow-only and marks
|
|
23
|
+
their association strength as uncalibrated.
|
|
24
|
+
|
|
5
25
|
## New In 3.6.2
|
|
6
26
|
|
|
7
27
|
- Adds `snipara.semantic.v1` to local code overlays and impact results with
|
package/dist/index.d.ts
CHANGED
|
@@ -688,6 +688,9 @@ interface AdvisorInfluenceRecommendationInput {
|
|
|
688
688
|
}
|
|
689
689
|
interface RecordAdvisorInfluenceReceiptInput {
|
|
690
690
|
servedJudgmentId: string;
|
|
691
|
+
judgmentSnapshotId?: string;
|
|
692
|
+
judgmentExposureId?: string;
|
|
693
|
+
runId?: string;
|
|
691
694
|
recommendation: AdvisorInfluenceRecommendationInput;
|
|
692
695
|
agentDecision: AdvisorInfluenceAgentDecision;
|
|
693
696
|
behaviorChange: string;
|
|
@@ -725,6 +728,16 @@ interface ProjectIntelligenceBriefRequest {
|
|
|
725
728
|
changedFiles?: string[];
|
|
726
729
|
symbols?: string[];
|
|
727
730
|
routes?: string[];
|
|
731
|
+
codeContext?: {
|
|
732
|
+
localHeadSha?: string;
|
|
733
|
+
branch?: string;
|
|
734
|
+
workingTreeDirty?: boolean;
|
|
735
|
+
};
|
|
736
|
+
correlation?: {
|
|
737
|
+
surface?: "companion";
|
|
738
|
+
runId?: string;
|
|
739
|
+
sessionId?: string;
|
|
740
|
+
};
|
|
728
741
|
}
|
|
729
742
|
interface HostedProjectIntelligenceBriefResult {
|
|
730
743
|
project: {
|
|
@@ -733,6 +746,8 @@ interface HostedProjectIntelligenceBriefResult {
|
|
|
733
746
|
slug: string;
|
|
734
747
|
};
|
|
735
748
|
servedJudgmentId: string | null;
|
|
749
|
+
judgmentSnapshotId: string | null;
|
|
750
|
+
judgmentExposureId: string | null;
|
|
736
751
|
persistedShadowSignalCount: number;
|
|
737
752
|
brief: {
|
|
738
753
|
version: string;
|
|
@@ -1825,6 +1840,8 @@ interface LocalSemanticAssertion {
|
|
|
1825
1840
|
predicate: LocalSemanticPredicate;
|
|
1826
1841
|
value: string | boolean;
|
|
1827
1842
|
confidence: number;
|
|
1843
|
+
scoreKind: "heuristic_prior";
|
|
1844
|
+
calibrated: false;
|
|
1828
1845
|
source: "typescript-compiler-api" | "language-parser" | "architecture-pattern-rules" | "criticality-rules" | "graph-criticality-rules";
|
|
1829
1846
|
extractorVersion: 1;
|
|
1830
1847
|
evidence: LocalSemanticEvidence[];
|
|
@@ -1833,6 +1850,29 @@ interface LocalSemanticModel {
|
|
|
1833
1850
|
version: "snipara.semantic.v1";
|
|
1834
1851
|
extractorVersion: 1;
|
|
1835
1852
|
source: "deterministic-graph-inference";
|
|
1853
|
+
modelType: "rule-based-heuristic";
|
|
1854
|
+
scoreContract: {
|
|
1855
|
+
kind: "heuristic_prior";
|
|
1856
|
+
calibrated: false;
|
|
1857
|
+
probability: false;
|
|
1858
|
+
comparableAcrossProjects: false;
|
|
1859
|
+
basis: "hand-tuned-v1";
|
|
1860
|
+
rulesetVersion: 1;
|
|
1861
|
+
interpretation: string;
|
|
1862
|
+
};
|
|
1863
|
+
ruleConfig: {
|
|
1864
|
+
version: "snipara.semantic.rules.v1";
|
|
1865
|
+
source: "defaults" | "project-file";
|
|
1866
|
+
path: ".snipara/semantic-rules.json";
|
|
1867
|
+
replaceDefaults: boolean;
|
|
1868
|
+
sensitivePathTermCount: number;
|
|
1869
|
+
contractPathTermCount: number;
|
|
1870
|
+
testPathTermCount: number;
|
|
1871
|
+
architectureRoleTermCount: number;
|
|
1872
|
+
configuredRoles: string[];
|
|
1873
|
+
configHash: string;
|
|
1874
|
+
warnings: string[];
|
|
1875
|
+
};
|
|
1836
1876
|
scope: "repository" | "impact";
|
|
1837
1877
|
assertions: LocalSemanticAssertion[];
|
|
1838
1878
|
publicContracts: LocalSemanticAssertion[];
|
|
@@ -2908,6 +2948,8 @@ interface ProjectRunHostedJudgmentLink {
|
|
|
2908
2948
|
status: "linked" | "unlinked" | "unavailable";
|
|
2909
2949
|
timeoutMs: number;
|
|
2910
2950
|
servedJudgmentId?: string;
|
|
2951
|
+
judgmentSnapshotId?: string;
|
|
2952
|
+
judgmentExposureId?: string;
|
|
2911
2953
|
error?: string;
|
|
2912
2954
|
}
|
|
2913
2955
|
interface ProjectIntelligenceRunResult {
|
package/dist/index.js
CHANGED
|
@@ -3822,7 +3822,10 @@ function buildLocalCodeOverlay(options = {}) {
|
|
|
3822
3822
|
extractedEdges.push(...extracted.edges);
|
|
3823
3823
|
}
|
|
3824
3824
|
const edges = resolveLocalGraphEdges(files, symbols, imports, references2, extractedEdges);
|
|
3825
|
-
const semantic = buildLocalSemanticModel(
|
|
3825
|
+
const semantic = buildLocalSemanticModel(
|
|
3826
|
+
{ symbols, edges },
|
|
3827
|
+
{ semanticRules: loadLocalSemanticRuleConfig(repoRoot) }
|
|
3828
|
+
);
|
|
3826
3829
|
for (const file of files) {
|
|
3827
3830
|
file.edgeCount = edges.filter((edge) => edge.filePath === file.path).length;
|
|
3828
3831
|
}
|
|
@@ -4308,9 +4311,125 @@ function uniqueTraversalFiles(nodes, excluded) {
|
|
|
4308
4311
|
)
|
|
4309
4312
|
].sort();
|
|
4310
4313
|
}
|
|
4314
|
+
var LOCAL_SEMANTIC_RULE_CONFIG_PATH = import_path.default.join(".snipara", "semantic-rules.json");
|
|
4315
|
+
var LOCAL_SEMANTIC_RULE_CONFIG_VERSION = "snipara.semantic.rules.v1";
|
|
4316
|
+
var LOCAL_SEMANTIC_MAX_TERMS = 64;
|
|
4317
|
+
var LOCAL_SEMANTIC_MAX_TERM_LENGTH = 80;
|
|
4318
|
+
var LOCAL_SEMANTIC_MAX_ROLES = 24;
|
|
4311
4319
|
var LOCAL_SEMANTIC_TEST_PATH = /(^|\/)(tests?|__tests__|fixtures?)(\/|$)|\.(test|spec)\./i;
|
|
4312
4320
|
var LOCAL_SEMANTIC_SENSITIVE_PATH = /(^|\/)(auth|middleware|billing|payments?|stripe|webhooks?|prisma|schema|migrations?|deploy)(\/|\.|$)/i;
|
|
4313
4321
|
var LOCAL_SEMANTIC_CONTRACT_PATH = /(^|\/)(schemas?|contracts?|protocols?|interfaces?|config|tool_defs)(\/|\.|$)|route\.(ts|tsx|py)$/i;
|
|
4322
|
+
function localSemanticTerms(raw, label, warnings) {
|
|
4323
|
+
if (raw === void 0 || raw === null) return [];
|
|
4324
|
+
if (!Array.isArray(raw)) {
|
|
4325
|
+
warnings.push(`${label} terms must be an array.`);
|
|
4326
|
+
return [];
|
|
4327
|
+
}
|
|
4328
|
+
const terms = [];
|
|
4329
|
+
for (const value of raw.slice(0, LOCAL_SEMANTIC_MAX_TERMS)) {
|
|
4330
|
+
const term = String(value).trim().toLowerCase();
|
|
4331
|
+
if (!term) continue;
|
|
4332
|
+
if (term.length > LOCAL_SEMANTIC_MAX_TERM_LENGTH) {
|
|
4333
|
+
warnings.push(
|
|
4334
|
+
`Ignored a ${label} term longer than ${LOCAL_SEMANTIC_MAX_TERM_LENGTH} characters.`
|
|
4335
|
+
);
|
|
4336
|
+
continue;
|
|
4337
|
+
}
|
|
4338
|
+
terms.push(term);
|
|
4339
|
+
}
|
|
4340
|
+
if (raw.length > LOCAL_SEMANTIC_MAX_TERMS) {
|
|
4341
|
+
warnings.push(`Limited ${label} terms to ${LOCAL_SEMANTIC_MAX_TERMS} entries.`);
|
|
4342
|
+
}
|
|
4343
|
+
return [...new Set(terms)];
|
|
4344
|
+
}
|
|
4345
|
+
function loadLocalSemanticRuleConfig(repoRoot) {
|
|
4346
|
+
const defaults = {
|
|
4347
|
+
replaceDefaults: false,
|
|
4348
|
+
sensitivePathTerms: [],
|
|
4349
|
+
contractPathTerms: [],
|
|
4350
|
+
testPathTerms: [],
|
|
4351
|
+
architectureRoleTerms: {},
|
|
4352
|
+
source: "defaults",
|
|
4353
|
+
warnings: []
|
|
4354
|
+
};
|
|
4355
|
+
const configPath = import_path.default.join(repoRoot, LOCAL_SEMANTIC_RULE_CONFIG_PATH);
|
|
4356
|
+
if (!import_fs.default.existsSync(configPath)) return defaults;
|
|
4357
|
+
try {
|
|
4358
|
+
const parsed = JSON.parse(import_fs.default.readFileSync(configPath, "utf8"));
|
|
4359
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
4360
|
+
return {
|
|
4361
|
+
...defaults,
|
|
4362
|
+
source: "project-file",
|
|
4363
|
+
warnings: ["Semantic rule config must be a JSON object; defaults were retained."]
|
|
4364
|
+
};
|
|
4365
|
+
}
|
|
4366
|
+
const raw = parsed;
|
|
4367
|
+
const warnings = [];
|
|
4368
|
+
const rawRoles = raw.architectureRoleTerms ?? raw.architecture_role_terms ?? {};
|
|
4369
|
+
const architectureRoleTerms = {};
|
|
4370
|
+
if (rawRoles && typeof rawRoles === "object" && !Array.isArray(rawRoles)) {
|
|
4371
|
+
for (const [rawRole, rawTerms] of Object.entries(rawRoles).slice(
|
|
4372
|
+
0,
|
|
4373
|
+
LOCAL_SEMANTIC_MAX_ROLES
|
|
4374
|
+
)) {
|
|
4375
|
+
const role = rawRole.trim().toLowerCase().replace(/[^a-z0-9_]+/g, "_").replace(/^_+|_+$/g, "");
|
|
4376
|
+
if (!role) {
|
|
4377
|
+
warnings.push("Ignored an empty or unsupported architecture role name.");
|
|
4378
|
+
continue;
|
|
4379
|
+
}
|
|
4380
|
+
architectureRoleTerms[role] = localSemanticTerms(
|
|
4381
|
+
rawTerms,
|
|
4382
|
+
`architecture role ${role}`,
|
|
4383
|
+
warnings
|
|
4384
|
+
);
|
|
4385
|
+
}
|
|
4386
|
+
} else if (rawRoles) {
|
|
4387
|
+
warnings.push("architectureRoleTerms must be an object of role-to-term arrays.");
|
|
4388
|
+
}
|
|
4389
|
+
return {
|
|
4390
|
+
replaceDefaults: Boolean(raw.replaceDefaults ?? raw.replace_defaults ?? false),
|
|
4391
|
+
sensitivePathTerms: localSemanticTerms(
|
|
4392
|
+
raw.sensitivePathTerms ?? raw.sensitive_path_terms,
|
|
4393
|
+
"sensitive path",
|
|
4394
|
+
warnings
|
|
4395
|
+
),
|
|
4396
|
+
contractPathTerms: localSemanticTerms(
|
|
4397
|
+
raw.contractPathTerms ?? raw.contract_path_terms,
|
|
4398
|
+
"contract path",
|
|
4399
|
+
warnings
|
|
4400
|
+
),
|
|
4401
|
+
testPathTerms: localSemanticTerms(
|
|
4402
|
+
raw.testPathTerms ?? raw.test_path_terms,
|
|
4403
|
+
"test path",
|
|
4404
|
+
warnings
|
|
4405
|
+
),
|
|
4406
|
+
architectureRoleTerms,
|
|
4407
|
+
source: "project-file",
|
|
4408
|
+
warnings
|
|
4409
|
+
};
|
|
4410
|
+
} catch (error) {
|
|
4411
|
+
return {
|
|
4412
|
+
...defaults,
|
|
4413
|
+
source: "project-file",
|
|
4414
|
+
warnings: [
|
|
4415
|
+
`Could not parse ${LOCAL_SEMANTIC_RULE_CONFIG_PATH}: ${error instanceof Error ? error.message : "invalid JSON"}`
|
|
4416
|
+
]
|
|
4417
|
+
};
|
|
4418
|
+
}
|
|
4419
|
+
}
|
|
4420
|
+
function localSemanticMatchesTerms(value, terms) {
|
|
4421
|
+
const normalized = value.replace(/\\/g, "/").toLowerCase();
|
|
4422
|
+
return terms.some((term) => normalized.includes(term));
|
|
4423
|
+
}
|
|
4424
|
+
function localSemanticIsTestPath(filePath, rules) {
|
|
4425
|
+
return !rules.replaceDefaults && LOCAL_SEMANTIC_TEST_PATH.test(filePath) || localSemanticMatchesTerms(filePath, rules.testPathTerms);
|
|
4426
|
+
}
|
|
4427
|
+
function localSemanticIsSensitivePath(filePath, rules) {
|
|
4428
|
+
return !rules.replaceDefaults && LOCAL_SEMANTIC_SENSITIVE_PATH.test(filePath) || localSemanticMatchesTerms(filePath, rules.sensitivePathTerms);
|
|
4429
|
+
}
|
|
4430
|
+
function localSemanticIsContractPath(filePath, rules) {
|
|
4431
|
+
return !rules.replaceDefaults && LOCAL_SEMANTIC_CONTRACT_PATH.test(filePath) || localSemanticMatchesTerms(filePath, rules.contractPathTerms);
|
|
4432
|
+
}
|
|
4314
4433
|
function localSemanticEvidence(kind, detail, metadata = {}) {
|
|
4315
4434
|
return { kind, detail, ...metadata };
|
|
4316
4435
|
}
|
|
@@ -4322,14 +4441,16 @@ function localSemanticAssertion(subject, predicate, value, confidence, source2,
|
|
|
4322
4441
|
predicate,
|
|
4323
4442
|
value,
|
|
4324
4443
|
confidence: Math.round(Math.max(0, Math.min(1, confidence)) * 1e3) / 1e3,
|
|
4444
|
+
scoreKind: "heuristic_prior",
|
|
4445
|
+
calibrated: false,
|
|
4325
4446
|
source: source2,
|
|
4326
4447
|
extractorVersion: 1,
|
|
4327
4448
|
evidence
|
|
4328
4449
|
};
|
|
4329
4450
|
}
|
|
4330
|
-
function localArchitectureRoles(symbol) {
|
|
4451
|
+
function localArchitectureRoles(symbol, rules) {
|
|
4331
4452
|
const haystack = `${symbol.filePath} ${symbol.name}`;
|
|
4332
|
-
const
|
|
4453
|
+
const defaultCandidates = [
|
|
4333
4454
|
{ role: "repository", pattern: /repository|(^|[_.])repo($|[_.])/i, confidence: 0.9 },
|
|
4334
4455
|
{ role: "adapter", pattern: /adapter/i, confidence: 0.9 },
|
|
4335
4456
|
{ role: "facade", pattern: /facade/i, confidence: 0.9 },
|
|
@@ -4356,7 +4477,7 @@ function localArchitectureRoles(symbol) {
|
|
|
4356
4477
|
)
|
|
4357
4478
|
);
|
|
4358
4479
|
}
|
|
4359
|
-
if (
|
|
4480
|
+
if (localSemanticIsTestPath(symbol.filePath, rules)) {
|
|
4360
4481
|
roles.push(
|
|
4361
4482
|
localSemanticAssertion(
|
|
4362
4483
|
symbol.localKey,
|
|
@@ -4368,7 +4489,7 @@ function localArchitectureRoles(symbol) {
|
|
|
4368
4489
|
)
|
|
4369
4490
|
);
|
|
4370
4491
|
}
|
|
4371
|
-
for (const candidate of
|
|
4492
|
+
for (const candidate of rules.replaceDefaults ? [] : defaultCandidates) {
|
|
4372
4493
|
if (!candidate.pattern.test(haystack)) continue;
|
|
4373
4494
|
roles.push(
|
|
4374
4495
|
localSemanticAssertion(
|
|
@@ -4387,9 +4508,29 @@ function localArchitectureRoles(symbol) {
|
|
|
4387
4508
|
)
|
|
4388
4509
|
);
|
|
4389
4510
|
}
|
|
4511
|
+
const existingRoles = new Set(roles.map((assertion) => String(assertion.value)));
|
|
4512
|
+
for (const [role, terms] of Object.entries(rules.architectureRoleTerms)) {
|
|
4513
|
+
if (existingRoles.has(role) || !localSemanticMatchesTerms(haystack, terms)) continue;
|
|
4514
|
+
roles.push(
|
|
4515
|
+
localSemanticAssertion(
|
|
4516
|
+
symbol.localKey,
|
|
4517
|
+
"architecture_role",
|
|
4518
|
+
role,
|
|
4519
|
+
0.7,
|
|
4520
|
+
"architecture-pattern-rules",
|
|
4521
|
+
[
|
|
4522
|
+
localSemanticEvidence(
|
|
4523
|
+
"project_role_term",
|
|
4524
|
+
`Name or path matches a configured ${role} project term.`,
|
|
4525
|
+
{ filePath: symbol.filePath, line: symbol.line }
|
|
4526
|
+
)
|
|
4527
|
+
]
|
|
4528
|
+
)
|
|
4529
|
+
);
|
|
4530
|
+
}
|
|
4390
4531
|
return roles;
|
|
4391
4532
|
}
|
|
4392
|
-
function localSymbolSemanticAssertions(symbol) {
|
|
4533
|
+
function localSymbolSemanticAssertions(symbol, rules) {
|
|
4393
4534
|
const assertions = [];
|
|
4394
4535
|
const routeSurface = /\/app\/api\//i.test(symbol.filePath) || /\/route\.(ts|tsx|py)$/i.test(symbol.filePath);
|
|
4395
4536
|
const toolSurface = /(^|\/)(mcp|tool_defs)(\/|\.|$)/i.test(symbol.filePath);
|
|
@@ -4445,7 +4586,7 @@ function localSymbolSemanticAssertions(symbol) {
|
|
|
4445
4586
|
contractEvidence.push(
|
|
4446
4587
|
localSemanticEvidence("symbol_kind", `Exported ${symbol.kind} defines a structural contract.`)
|
|
4447
4588
|
);
|
|
4448
|
-
} else if (
|
|
4589
|
+
} else if (localSemanticIsContractPath(symbol.filePath, rules)) {
|
|
4449
4590
|
contractKind = "repository_boundary_contract";
|
|
4450
4591
|
contractEvidence.push(
|
|
4451
4592
|
localSemanticEvidence(
|
|
@@ -4469,17 +4610,17 @@ function localSymbolSemanticAssertions(symbol) {
|
|
|
4469
4610
|
)
|
|
4470
4611
|
);
|
|
4471
4612
|
}
|
|
4472
|
-
assertions.push(...localArchitectureRoles(symbol));
|
|
4613
|
+
assertions.push(...localArchitectureRoles(symbol, rules));
|
|
4473
4614
|
let criticality = "ordinary";
|
|
4474
4615
|
let criticalityConfidence = 0.58;
|
|
4475
4616
|
let criticalityEvidence = [
|
|
4476
4617
|
localSemanticEvidence("default", "No critical or incidental evidence matched.")
|
|
4477
4618
|
];
|
|
4478
|
-
if (
|
|
4619
|
+
if (localSemanticIsTestPath(symbol.filePath, rules)) {
|
|
4479
4620
|
criticality = "incidental";
|
|
4480
4621
|
criticalityConfidence = 0.95;
|
|
4481
4622
|
criticalityEvidence = [localSemanticEvidence("test_path", "Test-only dependency.")];
|
|
4482
|
-
} else if (
|
|
4623
|
+
} else if (localSemanticIsSensitivePath(symbol.filePath, rules) || routeSurface || toolSurface) {
|
|
4483
4624
|
criticality = "critical";
|
|
4484
4625
|
criticalityConfidence = 0.92;
|
|
4485
4626
|
criticalityEvidence = [
|
|
@@ -4517,8 +4658,9 @@ function localSymbolSemanticAssertions(symbol) {
|
|
|
4517
4658
|
return assertions;
|
|
4518
4659
|
}
|
|
4519
4660
|
function buildLocalSemanticModel(manifest, options = {}) {
|
|
4661
|
+
const rules = options.semanticRules ?? loadLocalSemanticRuleConfig(process.cwd());
|
|
4520
4662
|
const symbols = options.symbolKeys ? manifest.symbols.filter((symbol) => options.symbolKeys?.has(symbol.localKey)) : manifest.symbols;
|
|
4521
|
-
const assertions = symbols.flatMap(localSymbolSemanticAssertions);
|
|
4663
|
+
const assertions = symbols.flatMap((symbol) => localSymbolSemanticAssertions(symbol, rules));
|
|
4522
4664
|
const symbolByKey = new Map(manifest.symbols.map((symbol) => [symbol.localKey, symbol]));
|
|
4523
4665
|
const criticalityBySymbol = new Map(
|
|
4524
4666
|
assertions.filter((assertion) => assertion.predicate === "dependency_criticality").map((assertion) => [assertion.subject, String(assertion.value)])
|
|
@@ -4555,7 +4697,7 @@ function buildLocalSemanticModel(manifest, options = {}) {
|
|
|
4555
4697
|
];
|
|
4556
4698
|
let value = "ordinary";
|
|
4557
4699
|
let confidence = 0.62;
|
|
4558
|
-
if (
|
|
4700
|
+
if (localSemanticIsTestPath(fromFile, rules) || localSemanticIsTestPath(toFile, rules)) {
|
|
4559
4701
|
value = "incidental";
|
|
4560
4702
|
confidence = 0.92;
|
|
4561
4703
|
evidence.push(localSemanticEvidence("test_path", "At least one edge endpoint is test-only."));
|
|
@@ -4626,6 +4768,40 @@ function buildLocalSemanticModel(manifest, options = {}) {
|
|
|
4626
4768
|
version: "snipara.semantic.v1",
|
|
4627
4769
|
extractorVersion: 1,
|
|
4628
4770
|
source: "deterministic-graph-inference",
|
|
4771
|
+
modelType: "rule-based-heuristic",
|
|
4772
|
+
scoreContract: {
|
|
4773
|
+
kind: "heuristic_prior",
|
|
4774
|
+
calibrated: false,
|
|
4775
|
+
probability: false,
|
|
4776
|
+
comparableAcrossProjects: false,
|
|
4777
|
+
basis: "hand-tuned-v1",
|
|
4778
|
+
rulesetVersion: 1,
|
|
4779
|
+
interpretation: "Relative rule strength for ranking and explanation; not an observed probability."
|
|
4780
|
+
},
|
|
4781
|
+
ruleConfig: {
|
|
4782
|
+
version: LOCAL_SEMANTIC_RULE_CONFIG_VERSION,
|
|
4783
|
+
source: rules.source,
|
|
4784
|
+
path: ".snipara/semantic-rules.json",
|
|
4785
|
+
replaceDefaults: rules.replaceDefaults,
|
|
4786
|
+
sensitivePathTermCount: rules.sensitivePathTerms.length,
|
|
4787
|
+
contractPathTermCount: rules.contractPathTerms.length,
|
|
4788
|
+
testPathTermCount: rules.testPathTerms.length,
|
|
4789
|
+
architectureRoleTermCount: Object.values(rules.architectureRoleTerms).reduce(
|
|
4790
|
+
(total, terms) => total + terms.length,
|
|
4791
|
+
0
|
|
4792
|
+
),
|
|
4793
|
+
configuredRoles: Object.keys(rules.architectureRoleTerms).sort(),
|
|
4794
|
+
configHash: sha2563(
|
|
4795
|
+
JSON.stringify({
|
|
4796
|
+
replaceDefaults: rules.replaceDefaults,
|
|
4797
|
+
sensitivePathTerms: rules.sensitivePathTerms,
|
|
4798
|
+
contractPathTerms: rules.contractPathTerms,
|
|
4799
|
+
testPathTerms: rules.testPathTerms,
|
|
4800
|
+
architectureRoleTerms: rules.architectureRoleTerms
|
|
4801
|
+
})
|
|
4802
|
+
).slice(0, 16),
|
|
4803
|
+
warnings: rules.warnings
|
|
4804
|
+
},
|
|
4629
4805
|
scope: options.scope ?? "repository",
|
|
4630
4806
|
assertions: returnedAssertions,
|
|
4631
4807
|
publicContracts,
|
|
@@ -4663,7 +4839,9 @@ function buildLocalSemanticModel(manifest, options = {}) {
|
|
|
4663
4839
|
},
|
|
4664
4840
|
caveats: [
|
|
4665
4841
|
"Semantic assertions are deterministic inferences, not declarations of author intent.",
|
|
4666
|
-
"
|
|
4842
|
+
"Confidence is an uncalibrated rule-based prior, not a probability or measured accuracy.",
|
|
4843
|
+
"Priors are not comparable across projects with different semantic rule configuration.",
|
|
4844
|
+
"Name-only architecture patterns use a lower prior than explicit export or path evidence.",
|
|
4667
4845
|
"Historical regression learning requires hosted outcome evidence and remains shadow-only."
|
|
4668
4846
|
]
|
|
4669
4847
|
};
|
|
@@ -4735,7 +4913,8 @@ function buildLocalRisk(manifest, changedFiles, traversal, depth, semantic) {
|
|
|
4735
4913
|
const changedSymbolKeys = new Set(
|
|
4736
4914
|
manifest.symbols.filter((symbol) => changedFiles.includes(symbol.filePath)).map((symbol) => symbol.localKey)
|
|
4737
4915
|
);
|
|
4738
|
-
const
|
|
4916
|
+
const semanticRules = loadLocalSemanticRuleConfig(manifest.repoRoot);
|
|
4917
|
+
const changedContracts = manifest.symbols.filter((symbol) => changedSymbolKeys.has(symbol.localKey)).flatMap((symbol) => localSymbolSemanticAssertions(symbol, semanticRules)).filter(
|
|
4739
4918
|
(assertion) => assertion.predicate === "public_api" || assertion.predicate === "implicit_contract"
|
|
4740
4919
|
).length;
|
|
4741
4920
|
const semanticRiskPoints = Math.min(20, criticalSemanticDependencies * 3) + Math.min(10, changedContracts * 2);
|
|
@@ -5800,7 +5979,8 @@ function buildLocalImpactResult(options) {
|
|
|
5800
5979
|
const semantic = buildLocalSemanticModel(manifest, {
|
|
5801
5980
|
scope: "impact",
|
|
5802
5981
|
symbolKeys: semanticSymbolKeys,
|
|
5803
|
-
edges: traversalEdges
|
|
5982
|
+
edges: traversalEdges,
|
|
5983
|
+
semanticRules: loadLocalSemanticRuleConfig(manifest.repoRoot)
|
|
5804
5984
|
});
|
|
5805
5985
|
const transitiveFiles = uniqueTraversalFiles(traversal.nodes, selectedFiles);
|
|
5806
5986
|
const impactedFiles = [.../* @__PURE__ */ new Set([...directImpactedFiles, ...transitiveFiles])].sort();
|
|
@@ -13698,6 +13878,9 @@ var why_capture_confidence_v1_default = {
|
|
|
13698
13878
|
var WHY_CAPTURE_CONFIDENCE_VERSION = why_capture_confidence_v1_default.version;
|
|
13699
13879
|
var WHY_CAPTURE_CONFIDENCE_TEST_VECTORS = why_capture_confidence_v1_default.vectors;
|
|
13700
13880
|
|
|
13881
|
+
// ../project-intelligence-contracts/src/judgment-integrity.ts
|
|
13882
|
+
var import_node_crypto4 = require("crypto");
|
|
13883
|
+
|
|
13701
13884
|
// src/commands/decision-requests.ts
|
|
13702
13885
|
var fs12 = __toESM(require("fs"));
|
|
13703
13886
|
var path11 = __toESM(require("path"));
|
|
@@ -15648,7 +15831,7 @@ var import_chalk10 = __toESM(require("chalk"));
|
|
|
15648
15831
|
var fs27 = __toESM(require("fs"));
|
|
15649
15832
|
var path26 = __toESM(require("path"));
|
|
15650
15833
|
var import_node_child_process13 = require("child_process");
|
|
15651
|
-
var
|
|
15834
|
+
var import_node_crypto11 = require("crypto");
|
|
15652
15835
|
var import_chalk9 = __toESM(require("chalk"));
|
|
15653
15836
|
|
|
15654
15837
|
// src/runtime/orchestrator-handoff.ts
|
|
@@ -16126,7 +16309,7 @@ function normalizeStringList2(values) {
|
|
|
16126
16309
|
// src/commands/activity.ts
|
|
16127
16310
|
var fs17 = __toESM(require("fs"));
|
|
16128
16311
|
var path16 = __toESM(require("path"));
|
|
16129
|
-
var
|
|
16312
|
+
var import_node_crypto5 = require("crypto");
|
|
16130
16313
|
var ACTIVITY_TIMELINE_VERSION = "snipara.activity_timeline.v0";
|
|
16131
16314
|
var SESSION_SNAPSHOT_VERSION = "snipara.session_snapshot.v0";
|
|
16132
16315
|
var ACTIVITY_RELATIVE_DIR = path16.join(".snipara", "activity");
|
|
@@ -16150,7 +16333,7 @@ function sortJsonValue3(value) {
|
|
|
16150
16333
|
return value;
|
|
16151
16334
|
}
|
|
16152
16335
|
function hashEvent(input) {
|
|
16153
|
-
return (0,
|
|
16336
|
+
return (0, import_node_crypto5.createHash)("sha256").update(stableJson(input)).digest("hex").slice(0, 16);
|
|
16154
16337
|
}
|
|
16155
16338
|
function safeReadJson(filePath) {
|
|
16156
16339
|
try {
|
|
@@ -16457,7 +16640,7 @@ async function appendJournalCheckpoint(payload) {
|
|
|
16457
16640
|
// src/commands/coding-ledger.ts
|
|
16458
16641
|
var fs18 = __toESM(require("fs"));
|
|
16459
16642
|
var path17 = __toESM(require("path"));
|
|
16460
|
-
var
|
|
16643
|
+
var import_node_crypto6 = require("crypto");
|
|
16461
16644
|
var import_node_child_process5 = require("child_process");
|
|
16462
16645
|
var CODING_INTELLIGENCE_LEDGER_VERSION = "snipara.coding_intelligence_ledger.v0";
|
|
16463
16646
|
var MAX_SECTION_ITEMS = 24;
|
|
@@ -16913,7 +17096,7 @@ function itemId(section, index, value) {
|
|
|
16913
17096
|
return `${section}:${stableHash([section, String(index), value]).slice(0, 16)}`;
|
|
16914
17097
|
}
|
|
16915
17098
|
function stableHash(parts) {
|
|
16916
|
-
return (0,
|
|
17099
|
+
return (0, import_node_crypto6.createHash)("sha256").update(parts.join("\0")).digest("hex");
|
|
16917
17100
|
}
|
|
16918
17101
|
function stringValue5(value) {
|
|
16919
17102
|
if (typeof value === "string") {
|
|
@@ -17244,7 +17427,7 @@ function toProjectRelativePath2(absolutePath, cwd) {
|
|
|
17244
17427
|
|
|
17245
17428
|
// src/commands/collaboration.ts
|
|
17246
17429
|
var import_node_child_process6 = require("child_process");
|
|
17247
|
-
var
|
|
17430
|
+
var import_node_crypto7 = require("crypto");
|
|
17248
17431
|
var fs20 = __toESM(require("fs"));
|
|
17249
17432
|
var os6 = __toESM(require("os"));
|
|
17250
17433
|
var path19 = __toESM(require("path"));
|
|
@@ -18973,7 +19156,7 @@ function printGuardActionCards(cards) {
|
|
|
18973
19156
|
}
|
|
18974
19157
|
}
|
|
18975
19158
|
function buildLocalSessionId(context, task, files) {
|
|
18976
|
-
const hash = (0,
|
|
19159
|
+
const hash = (0, import_node_crypto7.createHash)("sha1").update([context.actor.actorId, context.branch ?? "", task ?? "", files.join(",")].join("\n")).digest("hex").slice(0, 12);
|
|
18977
19160
|
return `local_${hash}`;
|
|
18978
19161
|
}
|
|
18979
19162
|
function normalizeFiles(files) {
|
|
@@ -19078,7 +19261,7 @@ function fingerprintReviewOnlyGuardEvaluation(evaluation) {
|
|
|
19078
19261
|
workSessionId: conflict.workSessionId ?? null,
|
|
19079
19262
|
reason: conflict.reason
|
|
19080
19263
|
})).sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b)));
|
|
19081
|
-
return (0,
|
|
19264
|
+
return (0, import_node_crypto7.createHash)("sha256").update(JSON.stringify(findings)).digest("hex");
|
|
19082
19265
|
}
|
|
19083
19266
|
function persistReviewOnlyAcknowledgement(state, profile, action, findingFingerprint, now = /* @__PURE__ */ new Date()) {
|
|
19084
19267
|
invalidateReviewOnlyAcknowledgements(state, profile, action);
|
|
@@ -19211,7 +19394,7 @@ function sleep2(ms) {
|
|
|
19211
19394
|
var fs22 = __toESM(require("fs"));
|
|
19212
19395
|
var path21 = __toESM(require("path"));
|
|
19213
19396
|
var import_node_child_process8 = require("child_process");
|
|
19214
|
-
var
|
|
19397
|
+
var import_node_crypto8 = require("crypto");
|
|
19215
19398
|
|
|
19216
19399
|
// src/commands/why-capture.ts
|
|
19217
19400
|
var import_node_child_process7 = require("child_process");
|
|
@@ -21179,7 +21362,7 @@ function formatError2(error) {
|
|
|
21179
21362
|
return error instanceof Error ? error.message : String(error);
|
|
21180
21363
|
}
|
|
21181
21364
|
function buildRecordId(prefix, createdAt, summary, files) {
|
|
21182
|
-
const hash = (0,
|
|
21365
|
+
const hash = (0, import_node_crypto8.createHash)("sha1").update([createdAt, summary, files.join(",")].join("\n")).digest("hex").slice(0, 10);
|
|
21183
21366
|
return `${prefix}_${hash}`;
|
|
21184
21367
|
}
|
|
21185
21368
|
|
|
@@ -22084,7 +22267,7 @@ function printKeyValue(label, value) {
|
|
|
22084
22267
|
}
|
|
22085
22268
|
|
|
22086
22269
|
// src/commands/final-commit-report.ts
|
|
22087
|
-
var
|
|
22270
|
+
var import_node_crypto9 = require("crypto");
|
|
22088
22271
|
var import_node_child_process10 = require("child_process");
|
|
22089
22272
|
var fs24 = __toESM(require("fs"));
|
|
22090
22273
|
var path23 = __toESM(require("path"));
|
|
@@ -22365,7 +22548,7 @@ function writeFinalCommitReport(report, cwd = process.cwd()) {
|
|
|
22365
22548
|
version: FINAL_COMMIT_REPORT_VERSION,
|
|
22366
22549
|
path: outputPath,
|
|
22367
22550
|
relativePath: FINAL_COMMIT_REPORT_RELATIVE_PATH,
|
|
22368
|
-
hash: `sha256:${(0,
|
|
22551
|
+
hash: `sha256:${(0, import_node_crypto9.createHash)("sha256").update(content).digest("hex")}`
|
|
22369
22552
|
};
|
|
22370
22553
|
} catch (error) {
|
|
22371
22554
|
return {
|
|
@@ -22437,7 +22620,7 @@ function formatFinalCommitReport(report) {
|
|
|
22437
22620
|
|
|
22438
22621
|
// src/commands/run.ts
|
|
22439
22622
|
var import_node_child_process12 = require("child_process");
|
|
22440
|
-
var
|
|
22623
|
+
var import_node_crypto10 = require("crypto");
|
|
22441
22624
|
var fs26 = __toESM(require("fs"));
|
|
22442
22625
|
var path25 = __toESM(require("path"));
|
|
22443
22626
|
var import_chalk8 = __toESM(require("chalk"));
|
|
@@ -24537,7 +24720,7 @@ function buildProjectIntelligenceRunEnvelope(startedAt = /* @__PURE__ */ new Dat
|
|
|
24537
24720
|
const codexSessionId = stringValue10(process.env.CODEX_SESSION_ID)?.slice(0, 200);
|
|
24538
24721
|
return {
|
|
24539
24722
|
version: "project-intelligence.judgment-run-envelope.v1",
|
|
24540
|
-
runId: sniparaSessionId ?? codexSessionId ?? `judgment-run:${(0,
|
|
24723
|
+
runId: sniparaSessionId ?? codexSessionId ?? `judgment-run:${(0, import_node_crypto10.randomUUID)()}`,
|
|
24541
24724
|
identitySource: sniparaSessionId ? "snipara_session" : codexSessionId ? "codex_session" : "generated",
|
|
24542
24725
|
startedAt: startedAt.toISOString()
|
|
24543
24726
|
};
|
|
@@ -24545,6 +24728,24 @@ function buildProjectIntelligenceRunEnvelope(startedAt = /* @__PURE__ */ new Dat
|
|
|
24545
24728
|
function normalizeStringList5(values) {
|
|
24546
24729
|
return [...new Set((values ?? []).map((value) => value.trim()).filter(Boolean))];
|
|
24547
24730
|
}
|
|
24731
|
+
function localCodeContext(branch) {
|
|
24732
|
+
const context = {};
|
|
24733
|
+
if (branch?.trim()) context.branch = branch.trim();
|
|
24734
|
+
try {
|
|
24735
|
+
const localHeadSha = (0, import_node_child_process12.execFileSync)("git", ["rev-parse", "--verify", "HEAD"], {
|
|
24736
|
+
encoding: "utf8",
|
|
24737
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
24738
|
+
}).trim();
|
|
24739
|
+
if (localHeadSha) context.localHeadSha = localHeadSha;
|
|
24740
|
+
const status = (0, import_node_child_process12.execFileSync)("git", ["status", "--porcelain"], {
|
|
24741
|
+
encoding: "utf8",
|
|
24742
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
24743
|
+
}).trim();
|
|
24744
|
+
context.workingTreeDirty = status.length > 0;
|
|
24745
|
+
} catch {
|
|
24746
|
+
}
|
|
24747
|
+
return context;
|
|
24748
|
+
}
|
|
24548
24749
|
function uniqueStrings20(values) {
|
|
24549
24750
|
return [...new Set(values.map((value) => value.trim()).filter(Boolean))];
|
|
24550
24751
|
}
|
|
@@ -24778,6 +24979,9 @@ function advisorReceiptMetadata(args) {
|
|
|
24778
24979
|
firstParty: true,
|
|
24779
24980
|
runVersion: "project-intelligence.production-run.v1",
|
|
24780
24981
|
runId: args.runEnvelope.runId,
|
|
24982
|
+
servedJudgmentId: args.hostedJudgment?.servedJudgmentId ?? null,
|
|
24983
|
+
judgmentSnapshotId: args.hostedJudgment?.judgmentSnapshotId ?? null,
|
|
24984
|
+
judgmentExposureId: args.hostedJudgment?.judgmentExposureId ?? null,
|
|
24781
24985
|
runEnvelope: args.runEnvelope,
|
|
24782
24986
|
generatedAt: args.judgmentCard.generatedAt,
|
|
24783
24987
|
release: Boolean(args.options.release),
|
|
@@ -25039,6 +25243,9 @@ async function recordFirstPartyAdvisorReceipts(args) {
|
|
|
25039
25243
|
});
|
|
25040
25244
|
const result = await client.recordAdvisorInfluenceReceipt({
|
|
25041
25245
|
servedJudgmentId,
|
|
25246
|
+
...args.hostedJudgment?.judgmentSnapshotId ? { judgmentSnapshotId: args.hostedJudgment.judgmentSnapshotId } : {},
|
|
25247
|
+
...args.hostedJudgment?.judgmentExposureId ? { judgmentExposureId: args.hostedJudgment.judgmentExposureId } : {},
|
|
25248
|
+
...args.hostedJudgment?.status === "linked" ? { runId: args.runEnvelope.runId } : {},
|
|
25042
25249
|
recommendation: advisorReceiptRecommendation(recommendation),
|
|
25043
25250
|
agentDecision,
|
|
25044
25251
|
behaviorChange,
|
|
@@ -25057,7 +25264,8 @@ async function recordFirstPartyAdvisorReceipts(args) {
|
|
|
25057
25264
|
lifecycle,
|
|
25058
25265
|
planScope,
|
|
25059
25266
|
measurementState,
|
|
25060
|
-
runEnvelope: args.runEnvelope
|
|
25267
|
+
runEnvelope: args.runEnvelope,
|
|
25268
|
+
hostedJudgment: args.hostedJudgment
|
|
25061
25269
|
})
|
|
25062
25270
|
});
|
|
25063
25271
|
return {
|
|
@@ -25207,7 +25415,12 @@ async function buildProjectIntelligenceRun(options) {
|
|
|
25207
25415
|
).createProjectIntelligenceBrief({
|
|
25208
25416
|
...options.task ? { task: options.task } : {},
|
|
25209
25417
|
...options.diffSummary ? { diffSummary: options.diffSummary } : {},
|
|
25210
|
-
...changedFiles.length > 0 ? { changedFiles: changedFiles.slice(0, 120) } : {}
|
|
25418
|
+
...changedFiles.length > 0 ? { changedFiles: changedFiles.slice(0, 120) } : {},
|
|
25419
|
+
codeContext: localCodeContext(options.branch),
|
|
25420
|
+
correlation: {
|
|
25421
|
+
surface: "companion",
|
|
25422
|
+
runId: runEnvelope.runId
|
|
25423
|
+
}
|
|
25211
25424
|
});
|
|
25212
25425
|
if (hostedProjectIntelligenceBrief.servedJudgmentId) {
|
|
25213
25426
|
brief.servedJudgmentId = hostedProjectIntelligenceBrief.servedJudgmentId;
|
|
@@ -25215,7 +25428,9 @@ async function buildProjectIntelligenceRun(options) {
|
|
|
25215
25428
|
version: "project-intelligence.hosted-judgment-link.v1",
|
|
25216
25429
|
status: "linked",
|
|
25217
25430
|
timeoutMs: HOSTED_PROJECT_INTELLIGENCE_BRIEF_TIMEOUT_MS,
|
|
25218
|
-
servedJudgmentId: hostedProjectIntelligenceBrief.servedJudgmentId
|
|
25431
|
+
servedJudgmentId: hostedProjectIntelligenceBrief.servedJudgmentId,
|
|
25432
|
+
...hostedProjectIntelligenceBrief.judgmentSnapshotId ? { judgmentSnapshotId: hostedProjectIntelligenceBrief.judgmentSnapshotId } : {},
|
|
25433
|
+
...hostedProjectIntelligenceBrief.judgmentExposureId ? { judgmentExposureId: hostedProjectIntelligenceBrief.judgmentExposureId } : {}
|
|
25219
25434
|
};
|
|
25220
25435
|
} else {
|
|
25221
25436
|
hostedJudgment = {
|
|
@@ -25305,7 +25520,8 @@ async function buildProjectIntelligenceRun(options) {
|
|
|
25305
25520
|
judgmentCard,
|
|
25306
25521
|
verificationEvidence: verificationEvidence2,
|
|
25307
25522
|
outcomeReceipts,
|
|
25308
|
-
runEnvelope
|
|
25523
|
+
runEnvelope,
|
|
25524
|
+
hostedJudgment
|
|
25309
25525
|
});
|
|
25310
25526
|
const suggestedCommands3 = [
|
|
25311
25527
|
...brief.suggestedCommands,
|
|
@@ -25706,7 +25922,7 @@ function contentBufferForHash(content) {
|
|
|
25706
25922
|
return Buffer.from(content, "utf8");
|
|
25707
25923
|
}
|
|
25708
25924
|
function hashContent(content) {
|
|
25709
|
-
return (0,
|
|
25925
|
+
return (0, import_node_crypto11.createHash)("sha256").update(contentBufferForHash(content)).digest("hex");
|
|
25710
25926
|
}
|
|
25711
25927
|
function toPreview(value, maxLength = 160) {
|
|
25712
25928
|
if (typeof value === "string") {
|
|
@@ -28377,7 +28593,7 @@ function findSandboxRuntimeBinding(state, phaseId) {
|
|
|
28377
28593
|
function defaultSandboxSessionId(state, phase) {
|
|
28378
28594
|
const workflowSlug = sanitizeWorkflowId(state.workflowId, "workflow").slice(0, 24);
|
|
28379
28595
|
const phaseSlug = sanitizeWorkflowId(phase.id, "phase").slice(0, 24);
|
|
28380
|
-
const digest = (0,
|
|
28596
|
+
const digest = (0, import_node_crypto11.createHash)("sha1").update(`${state.workflowId}:${phase.id}`).digest("hex").slice(0, 10);
|
|
28381
28597
|
return `sandbox-${workflowSlug}-${phaseSlug}-${digest}`.slice(0, 96);
|
|
28382
28598
|
}
|
|
28383
28599
|
function ensureSandboxRuntimeBinding(state, phase, now) {
|
|
@@ -35082,7 +35298,7 @@ async function sourceWatchCommand(options = {}) {
|
|
|
35082
35298
|
var import_fs5 = __toESM(require("fs"));
|
|
35083
35299
|
var import_path5 = __toESM(require("path"));
|
|
35084
35300
|
var import_node_child_process14 = require("child_process");
|
|
35085
|
-
var
|
|
35301
|
+
var import_node_crypto12 = require("crypto");
|
|
35086
35302
|
var import_chalk11 = __toESM(require("chalk"));
|
|
35087
35303
|
var CONTROLLED_WORKER_EXECUTIONS_DIR = import_path5.default.join(".snipara", "worker-executions");
|
|
35088
35304
|
var UNIFIED_RECEIPTS_DIR = import_path5.default.join(".snipara", "unified-receipts");
|
|
@@ -35350,7 +35566,7 @@ function pathFingerprint(workspaceRoot2, relativePath2) {
|
|
|
35350
35566
|
const stat = import_fs5.default.lstatSync(candidate);
|
|
35351
35567
|
if (stat.isSymbolicLink()) return `symlink:${import_fs5.default.readlinkSync(candidate)}`;
|
|
35352
35568
|
if (!stat.isFile()) return `mode:${stat.mode}:size:${stat.size}`;
|
|
35353
|
-
return `file:${stat.mode}:${(0,
|
|
35569
|
+
return `file:${stat.mode}:${(0, import_node_crypto12.createHash)("sha256").update(import_fs5.default.readFileSync(candidate)).digest("hex")}`;
|
|
35354
35570
|
} catch {
|
|
35355
35571
|
return "missing";
|
|
35356
35572
|
}
|
|
@@ -37649,7 +37865,7 @@ async function leadPlanCommand(options) {
|
|
|
37649
37865
|
// src/commands/outcome-capture.ts
|
|
37650
37866
|
var fs33 = __toESM(require("fs"));
|
|
37651
37867
|
var path32 = __toESM(require("path"));
|
|
37652
|
-
var
|
|
37868
|
+
var import_node_crypto13 = require("crypto");
|
|
37653
37869
|
var WHY_OUTCOME_CAPTURE_VERSION = "snipara.why_outcome_capture.v1";
|
|
37654
37870
|
var DEFAULT_MAX_CANDIDATES = 20;
|
|
37655
37871
|
var MAX_EVENTS = 50;
|
|
@@ -38178,7 +38394,7 @@ function readEventsFromFile(filePath) {
|
|
|
38178
38394
|
return [];
|
|
38179
38395
|
}
|
|
38180
38396
|
function stableHash2(parts) {
|
|
38181
|
-
return (0,
|
|
38397
|
+
return (0, import_node_crypto13.createHash)("sha256").update(parts.join("\0")).digest("hex");
|
|
38182
38398
|
}
|
|
38183
38399
|
function uniqueStrings22(values) {
|
|
38184
38400
|
return Array.from(new Set(values.filter(Boolean)));
|
package/docs/CODE_GRAPH.md
CHANGED
|
@@ -14,7 +14,9 @@ contains:
|
|
|
14
14
|
- `predicate`: `public_api`, `implicit_contract`, `architecture_role`, or
|
|
15
15
|
`dependency_criticality`;
|
|
16
16
|
- `value`: the inferred classification;
|
|
17
|
-
- `confidence`: a bounded
|
|
17
|
+
- `confidence`: a backward-compatible bounded rule-strength prior from `0` to
|
|
18
|
+
`1`, explicitly qualified by `scoreKind: "heuristic_prior"` and
|
|
19
|
+
`calibrated: false`;
|
|
18
20
|
- `source` and `extractorVersion`;
|
|
19
21
|
- `evidence`: the export modifier, symbol kind, file/path pattern, or graph edge
|
|
20
22
|
that produced the assertion.
|
|
@@ -22,8 +24,37 @@ contains:
|
|
|
22
24
|
The extractor recognizes explicit TypeScript and Go exports, route and MCP
|
|
23
25
|
surfaces, exported type contracts, and common Repository, Adapter, Facade,
|
|
24
26
|
Controller, Service, Worker, Factory, schema, route-handler, and test roles.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
`confidence` is not a probability, measured accuracy, or cross-project metric.
|
|
28
|
+
It is a deterministic prior used for relative ranking and explanation inside
|
|
29
|
+
one rule configuration. `semantic.scoreContract.basis` is
|
|
30
|
+
`hand-tuned-v1`; the values must be calibrated against measured outcomes before
|
|
31
|
+
that status can change. Name-only patterns have a lower prior than explicit
|
|
32
|
+
export, route, or graph evidence.
|
|
33
|
+
|
|
34
|
+
### Project naming rules
|
|
35
|
+
|
|
36
|
+
Projects can extend or replace built-in English naming conventions with
|
|
37
|
+
`.snipara/semantic-rules.json`:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"replaceDefaults": false,
|
|
42
|
+
"sensitivePathTerms": ["securite", "facturation"],
|
|
43
|
+
"contractPathTerms": ["contrats"],
|
|
44
|
+
"testPathTerms": ["essais"],
|
|
45
|
+
"architectureRoleTerms": {
|
|
46
|
+
"repository": ["depot"],
|
|
47
|
+
"service": ["metier"]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Terms are case-insensitive literal strings, not regular expressions. Each group
|
|
53
|
+
is limited to 64 terms of at most 80 characters and role names are normalized.
|
|
54
|
+
Invalid config is reported in `semantic.ruleConfig.warnings`; it never aborts
|
|
55
|
+
overlay construction. Set `replaceDefaults: true` only when the project wants
|
|
56
|
+
configured naming terms to replace built-in naming conventions. Explicit
|
|
57
|
+
exports, route surfaces, and graph evidence continue to apply.
|
|
27
58
|
|
|
28
59
|
## Dependency criticality
|
|
29
60
|
|
|
@@ -51,8 +82,9 @@ does not manufacture cross-source edges or assertions.
|
|
|
51
82
|
## Historical regression paths
|
|
52
83
|
|
|
53
84
|
Hosted impact can associate sanitized warning/error execution traces with
|
|
54
|
-
graph paths by their tracked files. Version 1 reports sample count,
|
|
55
|
-
event IDs, and a suggested risk
|
|
85
|
+
graph paths by their tracked files. Version 1 reports sample count, an
|
|
86
|
+
uncalibrated shadow association strength, event IDs, and a suggested risk
|
|
87
|
+
delta. This surface is intentionally
|
|
56
88
|
`mode: shadow` and `riskContributionEnabled: false`: temporal association is
|
|
57
89
|
not causal proof, and it cannot affect risk until separately calibrated and
|
|
58
90
|
promoted.
|