persona-harness 0.8.33 → 0.8.34

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.
@@ -0,0 +1,2 @@
1
+ import { type ContextComparisonResult } from "./context-comparison-types.js";
2
+ export declare function evaluateContextComparison(manifestInput: unknown, candidateInput: unknown): ContextComparisonResult;
@@ -0,0 +1,190 @@
1
+ import { buildContextEnvelope, canonicalContextDigest, resolveEffectiveContext } from "../context-core/index.js";
2
+ import { matchesContextRelevance } from "../context-core/effective-context-v2-input.js";
3
+ import { contextComparisonRules, parseContextComparisonCandidate, parseContextComparisonManifest, } from "./context-comparison-manifest.js";
4
+ import { CONTEXT_COMPARISON_ARMS, CONTEXT_COMPARISON_PROTOCOL, CONTEXT_COMPARISON_RESULT_SCHEMA, } from "./context-comparison-types.js";
5
+ export function evaluateContextComparison(manifestInput, candidateInput) {
6
+ const manifest = parseContextComparisonManifest(manifestInput);
7
+ if (manifest === undefined)
8
+ return blocked("context-comparison-manifest-invalid");
9
+ const candidate = parseContextComparisonCandidate(candidateInput);
10
+ if (candidate === undefined)
11
+ return blocked("context-comparison-candidate-invalid");
12
+ const manifestDigest = canonicalContextDigest(manifestInput);
13
+ const records = manifest.fixtures.flatMap((fixture) => CONTEXT_COMPARISON_ARMS.map((arm) => evaluateArm(fixture, candidate, arm)));
14
+ return {
15
+ candidate,
16
+ manifestDigest,
17
+ productVerdict: "INCONCLUSIVE",
18
+ protocolVersion: CONTEXT_COMPARISON_PROTOCOL,
19
+ records,
20
+ schemaVersion: CONTEXT_COMPARISON_RESULT_SCHEMA,
21
+ status: "ready",
22
+ };
23
+ }
24
+ function evaluateArm(fixture, candidate, arm) {
25
+ if (arm === "off")
26
+ return offRecord(fixture, candidate);
27
+ if (arm === "legacy-broad")
28
+ return legacyBroadRecord(fixture, candidate);
29
+ return targetedRecord(fixture, candidate);
30
+ }
31
+ function offRecord(fixture, candidate) {
32
+ return recordBase(fixture, candidate, "off", {
33
+ capsules: { chars: 0, count: 0 },
34
+ conflicts: [],
35
+ context: { blockReason: null, digest: null, mode: "disabled", status: "disabled" },
36
+ selected: [],
37
+ shadowed: [],
38
+ structural: { activeRuleCount: activeRules(fixture).length, applicableRuleCount: applicableRules(fixture).length, contradictionCount: 0, overreachCount: 0 },
39
+ technicalVerdict: "TECHNICAL_PASS",
40
+ warnings: ["context-disabled"],
41
+ });
42
+ }
43
+ function legacyBroadRecord(fixture, candidate) {
44
+ const active = activeRules(fixture);
45
+ const selected = active.map(toReference);
46
+ const applicable = applicableRules(fixture);
47
+ const chars = active.reduce((total, entry) => total + entry.rule.rule.length, 0);
48
+ const contradictoryTopics = duplicateTopicCount(active);
49
+ return recordBase(fixture, candidate, "legacy-broad", {
50
+ capsules: { chars, count: active.length },
51
+ conflicts: [],
52
+ context: {
53
+ blockReason: null,
54
+ digest: canonicalContextDigest(active.map(({ layer, rule }) => ({ id: rule.id, layer, rule: rule.rule, topic: rule.topic }))),
55
+ mode: "legacy-broad-compatibility",
56
+ status: "resolved",
57
+ },
58
+ selected,
59
+ shadowed: [],
60
+ structural: {
61
+ activeRuleCount: active.length,
62
+ applicableRuleCount: applicable.length,
63
+ contradictionCount: contradictoryTopics,
64
+ overreachCount: active.length - applicable.length,
65
+ },
66
+ technicalVerdict: "TECHNICAL_PASS",
67
+ warnings: ["legacy-broad-compatibility-only"],
68
+ });
69
+ }
70
+ function targetedRecord(fixture, candidate) {
71
+ const resolution = resolveEffectiveContext(fixture.context);
72
+ const envelope = buildContextEnvelope({
73
+ budget: {
74
+ maxCapsules: fixture.budget.maxCapsules,
75
+ maxChars: fixture.budget.maxChars,
76
+ },
77
+ resolution,
78
+ target: fixture.target,
79
+ });
80
+ const selected = envelope.selected.map((capsule) => ({ id: capsule.id, layer: capsule.layer }));
81
+ const layerByRuleId = new Map(activeRules(fixture).map(({ layer, rule }) => [rule.id, layer]));
82
+ const shadowed = envelope.shadowed.flatMap((entry) => {
83
+ const layer = layerByRuleId.get(entry.id);
84
+ return layer === undefined ? [] : [{ id: entry.id, layer }];
85
+ });
86
+ const conflicts = envelope.conflicts.map((conflict) => ({
87
+ reason: "same-layer-conflict",
88
+ ruleIds: conflict.ruleIds,
89
+ topic: conflict.topic,
90
+ }));
91
+ const matchesExpectation = matchesTargetedExpectation(fixture, resolution.status, envelope.status, envelope.status === "blocked" ? envelope.blockReason : undefined, selected, shadowed, conflicts);
92
+ return recordBase(fixture, candidate, "targeted-layered", {
93
+ capsules: { chars: envelope.budget.usedChars, count: envelope.budget.usedCapsules },
94
+ conflicts,
95
+ context: {
96
+ blockReason: envelope.status === "blocked" ? envelope.blockReason : null,
97
+ digest: envelope.digest,
98
+ mode: "targeted-layered",
99
+ status: envelope.status,
100
+ },
101
+ selected,
102
+ shadowed,
103
+ structural: {
104
+ activeRuleCount: activeRules(fixture).length,
105
+ applicableRuleCount: applicableRules(fixture).length,
106
+ contradictionCount: duplicateTopicCount(envelope.selected.map((capsule) => ({ layer: capsule.layer, rule: { ...capsule, rule: capsule.content } }))),
107
+ overreachCount: 0,
108
+ },
109
+ technicalVerdict: matchesExpectation ? "TECHNICAL_PASS" : "TECHNICAL_FAIL",
110
+ warnings: envelope.warnings.map((warning) => warning.code),
111
+ });
112
+ }
113
+ function recordBase(fixture, candidate, arm, values) {
114
+ const digest = values.context.digest;
115
+ return {
116
+ arm,
117
+ candidate,
118
+ capsules: values.capsules,
119
+ claimScope: fixture.claimScope,
120
+ conflicts: values.conflicts,
121
+ context: values.context,
122
+ delivery: { attempts: fixture.deliveryAttempts, uniqueDigestCount: digest === null ? 0 : 1 },
123
+ fixtureId: fixture.id,
124
+ hostAdapter: null,
125
+ measurements: unavailableMeasurements(),
126
+ model: { provider: null, version: null },
127
+ productVerdict: "INCONCLUSIVE",
128
+ selected: values.selected,
129
+ shadowed: values.shadowed,
130
+ sourceDigest: canonicalContextDigest(fixture.target),
131
+ structural: values.structural,
132
+ taskDigest: canonicalContextDigest(fixture.task),
133
+ technicalVerdict: values.technicalVerdict,
134
+ warnings: values.warnings,
135
+ };
136
+ }
137
+ function matchesTargetedExpectation(fixture, resolutionStatus, envelopeStatus, blockReason, selected, shadowed, conflicts) {
138
+ const expected = fixture.expectation;
139
+ return resolutionStatus === expected.resolutionStatus
140
+ && envelopeStatus === expected.envelopeStatus
141
+ && blockReason === expected.blockReason
142
+ && equalJson(selected, expected.selected)
143
+ && equalJson(shadowed, expected.shadowed)
144
+ && equalJson(conflicts, expected.conflicts);
145
+ }
146
+ function activeRules(fixture) {
147
+ return contextComparisonRules(fixture.context)
148
+ .filter(({ rule }) => rule.status === undefined || rule.status === "active")
149
+ .sort(compareLayeredRules);
150
+ }
151
+ function applicableRules(fixture) {
152
+ return activeRules(fixture).filter(({ rule }) => matchesContextRelevance(rule, fixture.context.relevance));
153
+ }
154
+ function toReference(entry) {
155
+ return { id: entry.rule.id, layer: entry.layer };
156
+ }
157
+ function compareLayeredRules(left, right) {
158
+ return layerPriority(right.layer) - layerPriority(left.layer)
159
+ || left.rule.topic.localeCompare(right.rule.topic)
160
+ || left.rule.id.localeCompare(right.rule.id);
161
+ }
162
+ function layerPriority(layer) {
163
+ return ["common", "language", "personal", "team", "project", "task", "invariant"].indexOf(layer);
164
+ }
165
+ function duplicateTopicCount(entries) {
166
+ const counts = new Map();
167
+ for (const { rule } of entries)
168
+ counts.set(rule.topic, (counts.get(rule.topic) ?? 0) + 1);
169
+ return [...counts.values()].reduce((total, count) => total + Math.max(0, count - 1), 0);
170
+ }
171
+ function unavailableMeasurements() {
172
+ return {
173
+ conflictResolutionAccuracy: null,
174
+ correctionCount: null,
175
+ correctionRate: null,
176
+ latencyMs: null,
177
+ maintainerIntervention: null,
178
+ policySurvival: null,
179
+ taskSuccess: null,
180
+ tokenOverhead: null,
181
+ toolCallCount: null,
182
+ };
183
+ }
184
+ function blocked(code) {
185
+ return { code, schemaVersion: CONTEXT_COMPARISON_RESULT_SCHEMA, status: "blocked" };
186
+ }
187
+ function equalJson(left, right) {
188
+ return JSON.stringify(left) === JSON.stringify(right);
189
+ }
190
+ //# sourceMappingURL=context-comparison-evaluator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-comparison-evaluator.js","sourceRoot":"","sources":["../../src/context-comparison/context-comparison-evaluator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { ContextLayer, ContextRule, EffectiveContextInput } from "../context-core/rule-types.js";
2
+ import { type ContextComparisonCandidate, type ContextComparisonManifest } from "./context-comparison-types.js";
3
+ export declare function parseContextComparisonManifest(value: unknown): ContextComparisonManifest | undefined;
4
+ export declare function parseContextComparisonCandidate(value: unknown): ContextComparisonCandidate | undefined;
5
+ export declare function contextComparisonRules(input: EffectiveContextInput): readonly {
6
+ readonly layer: ContextLayer;
7
+ readonly rule: ContextRule;
8
+ }[];
@@ -0,0 +1,190 @@
1
+ import { parseEffectiveContextInput } from "../context-core/effective-context-v2-input.js";
2
+ import { CONTEXT_COMPARISON_FIXTURE_SET, CONTEXT_COMPARISON_LAYERS, CONTEXT_COMPARISON_MANIFEST_SCHEMA, REQUIRED_CONTEXT_COMPARISON_FIXTURE_IDS, } from "./context-comparison-types.js";
3
+ const FIXTURE_KEYS = ["budget", "claimScope", "context", "deliveryAttempts", "expectation", "id", "target", "task"];
4
+ const MANIFEST_KEYS = ["fixtureSet", "fixtures", "schemaVersion"];
5
+ const TARGET_KEYS = ["fileRole", "language", "path"];
6
+ const EXPECTATION_KEYS = ["blockReason", "conflicts", "envelopeStatus", "resolutionStatus", "selected", "shadowed"];
7
+ const RULE_REFERENCE_KEYS = ["id", "layer"];
8
+ const CONFLICT_KEYS = ["reason", "ruleIds", "topic"];
9
+ const BUDGET_KEYS = ["maxCapsules", "maxChars"];
10
+ const BLOCK_REASONS = ["malformed-input", "resolution-blocked", "budget-exceeded", "unsafe-content"];
11
+ const CONTEXT_INPUT_KEYS = [
12
+ "productInvariants",
13
+ "taskDecisions",
14
+ "projectContracts",
15
+ "teamContracts",
16
+ "personalRules",
17
+ "languageDefaults",
18
+ "commonDefaults",
19
+ ];
20
+ export function parseContextComparisonManifest(value) {
21
+ if (!isRecord(value) || !hasOnlyKeys(value, MANIFEST_KEYS) || value.schemaVersion !== CONTEXT_COMPARISON_MANIFEST_SCHEMA)
22
+ return undefined;
23
+ if (value.fixtureSet !== CONTEXT_COMPARISON_FIXTURE_SET || !Array.isArray(value.fixtures))
24
+ return undefined;
25
+ const fixtures = value.fixtures.map(parseFixture);
26
+ if (fixtures.some((fixture) => fixture === undefined))
27
+ return undefined;
28
+ const parsed = fixtures;
29
+ return hasRequiredFixtureSet(parsed)
30
+ ? { fixtureSet: value.fixtureSet, fixtures: parsed, schemaVersion: CONTEXT_COMPARISON_MANIFEST_SCHEMA }
31
+ : undefined;
32
+ }
33
+ export function parseContextComparisonCandidate(value) {
34
+ if (!isRecord(value) || !hasOnlyKeys(value, ["commit", "packageVersion"]))
35
+ return undefined;
36
+ if (typeof value.commit !== "string" || !/^[0-9a-f]{7,64}$/u.test(value.commit))
37
+ return undefined;
38
+ if (typeof value.packageVersion !== "string" || !/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u.test(value.packageVersion))
39
+ return undefined;
40
+ return { commit: value.commit, packageVersion: value.packageVersion };
41
+ }
42
+ export function contextComparisonRules(input) {
43
+ return CONTEXT_INPUT_KEYS.flatMap((key) => input[key].map((rule) => ({ layer: layerFor(key), rule })));
44
+ }
45
+ function parseFixture(value) {
46
+ if (!isRecord(value) || !hasOnlyKeys(value, FIXTURE_KEYS))
47
+ return undefined;
48
+ const id = parseFixtureId(value.id);
49
+ const target = parseTarget(value.target);
50
+ const context = parseEffectiveContextInput(value.context);
51
+ const expectation = parseExpectation(value.expectation);
52
+ const budget = parseBudget(value.budget);
53
+ if (id === undefined || target === undefined || context === undefined || expectation === undefined || budget === undefined)
54
+ return undefined;
55
+ if (!isSafeText(value.task, 500) || (value.claimScope !== "context-resolution" && value.claimScope !== "core-portability-only"))
56
+ return undefined;
57
+ if (value.deliveryAttempts !== 1 && value.deliveryAttempts !== 2)
58
+ return undefined;
59
+ if (!hasUniqueRuleIds(context))
60
+ return undefined;
61
+ return { budget, claimScope: value.claimScope, context, deliveryAttempts: value.deliveryAttempts, expectation, id, target, task: value.task };
62
+ }
63
+ function parseBudget(value) {
64
+ if (value === undefined)
65
+ return { maxCapsules: 8, maxChars: 1_600 };
66
+ if (!isRecord(value) || !hasOnlyKeys(value, BUDGET_KEYS))
67
+ return undefined;
68
+ const maxCapsules = value.maxCapsules;
69
+ const maxChars = value.maxChars;
70
+ if (typeof maxCapsules !== "number" || !Number.isInteger(maxCapsules) || maxCapsules < 1 || maxCapsules > 8)
71
+ return undefined;
72
+ if (typeof maxChars !== "number" || !Number.isInteger(maxChars) || maxChars < 1 || maxChars > 1_600)
73
+ return undefined;
74
+ return { maxCapsules, maxChars };
75
+ }
76
+ function parseFixtureId(value) {
77
+ return REQUIRED_CONTEXT_COMPARISON_FIXTURE_IDS.includes(value) ? value : undefined;
78
+ }
79
+ function parseTarget(value) {
80
+ if (!isRecord(value) || !hasOnlyKeys(value, TARGET_KEYS))
81
+ return undefined;
82
+ if (!isSafeIdentifier(value.fileRole) || !isSafeIdentifier(value.language) || !isSafeRelativePath(value.path))
83
+ return undefined;
84
+ return { fileRole: value.fileRole, language: value.language, path: value.path };
85
+ }
86
+ function parseExpectation(value) {
87
+ if (!isRecord(value) || !hasOnlyKeys(value, EXPECTATION_KEYS))
88
+ return undefined;
89
+ const selected = parseRuleReferences(value.selected);
90
+ const shadowed = parseRuleReferences(value.shadowed);
91
+ const conflicts = parseConflicts(value.conflicts);
92
+ if (selected === undefined || shadowed === undefined || conflicts === undefined)
93
+ return undefined;
94
+ if (value.resolutionStatus !== "blocked" && value.resolutionStatus !== "resolved")
95
+ return undefined;
96
+ if (value.envelopeStatus !== "blocked" && value.envelopeStatus !== "resolved")
97
+ return undefined;
98
+ const blockReason = parseBlockReason(value.blockReason);
99
+ if ((value.envelopeStatus === "blocked" && blockReason === undefined) || (value.envelopeStatus === "resolved" && value.blockReason !== undefined))
100
+ return undefined;
101
+ return {
102
+ ...(blockReason === undefined ? {} : { blockReason }),
103
+ conflicts,
104
+ envelopeStatus: value.envelopeStatus,
105
+ resolutionStatus: value.resolutionStatus,
106
+ selected,
107
+ shadowed,
108
+ };
109
+ }
110
+ function parseRuleReferences(value) {
111
+ if (!Array.isArray(value))
112
+ return undefined;
113
+ const references = value.map((entry) => {
114
+ if (!isRecord(entry) || !hasOnlyKeys(entry, RULE_REFERENCE_KEYS))
115
+ return undefined;
116
+ if (!isSafeIdentifier(entry.id) || !isContextLayer(entry.layer))
117
+ return undefined;
118
+ return { id: entry.id, layer: entry.layer };
119
+ });
120
+ return references.some((entry) => entry === undefined) ? undefined : references;
121
+ }
122
+ function parseConflicts(value) {
123
+ if (!Array.isArray(value))
124
+ return undefined;
125
+ const conflicts = value.map((entry) => {
126
+ if (!isRecord(entry) || !hasOnlyKeys(entry, CONFLICT_KEYS) || entry.reason !== "same-layer-conflict")
127
+ return undefined;
128
+ if (!isSafeIdentifier(entry.topic) || !Array.isArray(entry.ruleIds) || entry.ruleIds.length < 2 || entry.ruleIds.some((id) => !isSafeIdentifier(id)))
129
+ return undefined;
130
+ const ruleIds = [...entry.ruleIds].sort();
131
+ if (ruleIds.join("\u0000") !== entry.ruleIds.join("\u0000"))
132
+ return undefined;
133
+ return { reason: "same-layer-conflict", ruleIds, topic: entry.topic };
134
+ });
135
+ return conflicts.some((entry) => entry === undefined) ? undefined : conflicts;
136
+ }
137
+ function parseBlockReason(value) {
138
+ return BLOCK_REASONS.includes(value) ? value : undefined;
139
+ }
140
+ function hasRequiredFixtureSet(fixtures) {
141
+ const ids = fixtures.map((fixture) => fixture.id).sort();
142
+ const required = [...REQUIRED_CONTEXT_COMPARISON_FIXTURE_IDS].sort();
143
+ return ids.length === required.length && ids.every((id, index) => id === required[index]);
144
+ }
145
+ function hasUniqueRuleIds(input) {
146
+ const seen = new Set();
147
+ for (const { rule } of contextComparisonRules(input)) {
148
+ if (seen.has(rule.id))
149
+ return false;
150
+ seen.add(rule.id);
151
+ }
152
+ return true;
153
+ }
154
+ function layerFor(key) {
155
+ if (key === "productInvariants")
156
+ return "invariant";
157
+ if (key === "taskDecisions")
158
+ return "task";
159
+ if (key === "projectContracts")
160
+ return "project";
161
+ if (key === "teamContracts")
162
+ return "team";
163
+ if (key === "personalRules")
164
+ return "personal";
165
+ if (key === "languageDefaults")
166
+ return "language";
167
+ return "common";
168
+ }
169
+ function hasOnlyKeys(value, keys) {
170
+ const allowed = new Set(keys);
171
+ return Object.keys(value).every((key) => allowed.has(key));
172
+ }
173
+ function isContextLayer(value) {
174
+ return CONTEXT_COMPARISON_LAYERS.includes(value);
175
+ }
176
+ function isRecord(value) {
177
+ return typeof value === "object" && value !== null && !Array.isArray(value);
178
+ }
179
+ function isSafeIdentifier(value) {
180
+ return typeof value === "string" && /^[a-z][a-z0-9-]{0,119}$/u.test(value);
181
+ }
182
+ function isSafeRelativePath(value) {
183
+ return typeof value === "string" && value.length > 0 && value.length <= 240
184
+ && !value.startsWith("/") && !value.includes("\\") && !value.split("/").includes("..")
185
+ && !/[\u0000-\u001f\u007f]/u.test(value);
186
+ }
187
+ function isSafeText(value, maxLength) {
188
+ return typeof value === "string" && value.length > 0 && value.length <= maxLength && !/[\u0000-\u001f\u007f]/u.test(value);
189
+ }
190
+ //# sourceMappingURL=context-comparison-manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-comparison-manifest.js","sourceRoot":"","sources":["../../src/context-comparison/context-comparison-manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ import type { ContextEnvelopeBlockReason } from "../context-core/context-envelope.js";
2
+ import type { ContextLayer, EffectiveContextInput } from "../context-core/rule-types.js";
3
+ export declare const CONTEXT_COMPARISON_MANIFEST_SCHEMA: "persona-context-comparison-manifest.1";
4
+ export declare const CONTEXT_COMPARISON_PROTOCOL: "persona-context-comparison-protocol.1";
5
+ export declare const CONTEXT_COMPARISON_RESULT_SCHEMA: "persona-context-comparison-result.1";
6
+ export declare const CONTEXT_COMPARISON_FIXTURE_SET: "p0-context-three-arm";
7
+ export declare const CONTEXT_COMPARISON_ARMS: readonly ["off", "legacy-broad", "targeted-layered"];
8
+ export declare const CONTEXT_COMPARISON_LAYERS: readonly ["invariant", "task", "project", "team", "personal", "language", "common"];
9
+ export declare const REQUIRED_CONTEXT_COMPARISON_FIXTURE_IDS: readonly ["personal-vs-team", "team-vs-project", "project-vs-task", "invariant-vs-project-team", "same-layer-ambiguity", "java-controller", "java-service", "typescript-core-reference", "duplicate-delivery", "context-budget-overflow"];
10
+ export type ContextComparisonArm = (typeof CONTEXT_COMPARISON_ARMS)[number];
11
+ export type ContextComparisonLayer = (typeof CONTEXT_COMPARISON_LAYERS)[number];
12
+ export type ContextComparisonFixtureId = (typeof REQUIRED_CONTEXT_COMPARISON_FIXTURE_IDS)[number];
13
+ export type ContextComparisonCandidate = {
14
+ readonly commit: string;
15
+ readonly packageVersion: string;
16
+ };
17
+ export type ContextComparisonTarget = {
18
+ readonly fileRole: string;
19
+ readonly language: string;
20
+ readonly path: string;
21
+ };
22
+ export type ContextComparisonBudget = {
23
+ readonly maxCapsules: number;
24
+ readonly maxChars: number;
25
+ };
26
+ export type ContextComparisonRuleReference = {
27
+ readonly id: string;
28
+ readonly layer: ContextLayer;
29
+ };
30
+ export type ContextComparisonConflict = {
31
+ readonly reason: "same-layer-conflict";
32
+ readonly ruleIds: readonly string[];
33
+ readonly topic: string;
34
+ };
35
+ export type ContextComparisonExpectation = {
36
+ readonly blockReason?: ContextEnvelopeBlockReason;
37
+ readonly conflicts: readonly ContextComparisonConflict[];
38
+ readonly envelopeStatus: "blocked" | "resolved";
39
+ readonly resolutionStatus: "blocked" | "resolved";
40
+ readonly selected: readonly ContextComparisonRuleReference[];
41
+ readonly shadowed: readonly ContextComparisonRuleReference[];
42
+ };
43
+ export type ContextComparisonFixture = {
44
+ readonly budget: ContextComparisonBudget;
45
+ readonly claimScope: "context-resolution" | "core-portability-only";
46
+ readonly context: EffectiveContextInput;
47
+ readonly deliveryAttempts: 1 | 2;
48
+ readonly expectation: ContextComparisonExpectation;
49
+ readonly id: ContextComparisonFixtureId;
50
+ readonly target: ContextComparisonTarget;
51
+ readonly task: string;
52
+ };
53
+ export type ContextComparisonManifest = {
54
+ readonly fixtureSet: typeof CONTEXT_COMPARISON_FIXTURE_SET;
55
+ readonly fixtures: readonly ContextComparisonFixture[];
56
+ readonly schemaVersion: typeof CONTEXT_COMPARISON_MANIFEST_SCHEMA;
57
+ };
58
+ export type ContextComparisonMeasurements = {
59
+ readonly conflictResolutionAccuracy: number | null;
60
+ readonly correctionCount: number | null;
61
+ readonly correctionRate: number | null;
62
+ readonly latencyMs: number | null;
63
+ readonly maintainerIntervention: boolean | null;
64
+ readonly policySurvival: boolean | null;
65
+ readonly taskSuccess: boolean | null;
66
+ readonly tokenOverhead: number | null;
67
+ readonly toolCallCount: number | null;
68
+ };
69
+ export type ContextComparisonProductVerdict = "INCONCLUSIVE" | "PRODUCT_GO" | "PRODUCT_NO_GO";
70
+ export type ContextComparisonStructuralMetrics = {
71
+ readonly activeRuleCount: number;
72
+ readonly applicableRuleCount: number;
73
+ readonly contradictionCount: number;
74
+ readonly overreachCount: number;
75
+ };
76
+ export type ContextComparisonRecord = {
77
+ readonly arm: ContextComparisonArm;
78
+ readonly candidate: ContextComparisonCandidate;
79
+ readonly capsules: {
80
+ readonly chars: number;
81
+ readonly count: number;
82
+ };
83
+ readonly claimScope: ContextComparisonFixture["claimScope"];
84
+ readonly conflicts: readonly ContextComparisonConflict[];
85
+ readonly context: {
86
+ readonly blockReason: ContextEnvelopeBlockReason | null;
87
+ readonly digest: string | null;
88
+ readonly mode: "disabled" | "legacy-broad-compatibility" | "targeted-layered";
89
+ readonly status: "blocked" | "disabled" | "resolved";
90
+ };
91
+ readonly delivery: {
92
+ readonly attempts: 1 | 2;
93
+ readonly uniqueDigestCount: number;
94
+ };
95
+ readonly fixtureId: ContextComparisonFixtureId;
96
+ readonly hostAdapter: string | null;
97
+ readonly measurements: ContextComparisonMeasurements;
98
+ readonly model: {
99
+ readonly provider: string | null;
100
+ readonly version: string | null;
101
+ };
102
+ readonly productVerdict: ContextComparisonProductVerdict;
103
+ readonly selected: readonly ContextComparisonRuleReference[];
104
+ readonly shadowed: readonly ContextComparisonRuleReference[];
105
+ readonly sourceDigest: string;
106
+ readonly structural: ContextComparisonStructuralMetrics;
107
+ readonly taskDigest: string;
108
+ readonly technicalVerdict: "TECHNICAL_FAIL" | "TECHNICAL_PASS";
109
+ readonly warnings: readonly string[];
110
+ };
111
+ export type ContextComparisonResult = {
112
+ readonly code: "context-comparison-candidate-invalid" | "context-comparison-manifest-invalid";
113
+ readonly schemaVersion: typeof CONTEXT_COMPARISON_RESULT_SCHEMA;
114
+ readonly status: "blocked";
115
+ } | {
116
+ readonly candidate: ContextComparisonCandidate;
117
+ readonly manifestDigest: string;
118
+ readonly productVerdict: ContextComparisonProductVerdict;
119
+ readonly protocolVersion: typeof CONTEXT_COMPARISON_PROTOCOL;
120
+ readonly records: readonly ContextComparisonRecord[];
121
+ readonly schemaVersion: typeof CONTEXT_COMPARISON_RESULT_SCHEMA;
122
+ readonly status: "ready";
123
+ };
@@ -0,0 +1,19 @@
1
+ export const CONTEXT_COMPARISON_MANIFEST_SCHEMA = "persona-context-comparison-manifest.1";
2
+ export const CONTEXT_COMPARISON_PROTOCOL = "persona-context-comparison-protocol.1";
3
+ export const CONTEXT_COMPARISON_RESULT_SCHEMA = "persona-context-comparison-result.1";
4
+ export const CONTEXT_COMPARISON_FIXTURE_SET = "p0-context-three-arm";
5
+ export const CONTEXT_COMPARISON_ARMS = ["off", "legacy-broad", "targeted-layered"];
6
+ export const CONTEXT_COMPARISON_LAYERS = ["invariant", "task", "project", "team", "personal", "language", "common"];
7
+ export const REQUIRED_CONTEXT_COMPARISON_FIXTURE_IDS = [
8
+ "personal-vs-team",
9
+ "team-vs-project",
10
+ "project-vs-task",
11
+ "invariant-vs-project-team",
12
+ "same-layer-ambiguity",
13
+ "java-controller",
14
+ "java-service",
15
+ "typescript-core-reference",
16
+ "duplicate-delivery",
17
+ "context-budget-overflow",
18
+ ];
19
+ //# sourceMappingURL=context-comparison-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-comparison-types.js","sourceRoot":"","sources":["../../src/context-comparison/context-comparison-types.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,kCAAkC,GAAG,uCAAgD,CAAA;AAClG,MAAM,CAAC,MAAM,2BAA2B,GAAG,uCAAgD,CAAA;AAC3F,MAAM,CAAC,MAAM,gCAAgC,GAAG,qCAA8C,CAAA;AAC9F,MAAM,CAAC,MAAM,8BAA8B,GAAG,sBAA+B,CAAA;AAC7E,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,KAAK,EAAE,cAAc,EAAE,kBAAkB,CAAU,CAAA;AAC3F,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAU,CAAA;AAC5H,MAAM,CAAC,MAAM,uCAAuC,GAAG;IACrD,kBAAkB;IAClB,iBAAiB;IACjB,iBAAiB;IACjB,2BAA2B;IAC3B,sBAAsB;IACtB,iBAAiB;IACjB,cAAc;IACd,2BAA2B;IAC3B,oBAAoB;IACpB,yBAAyB;CACjB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from "./context-comparison-evaluator.js";
2
+ export * from "./context-comparison-types.js";
@@ -0,0 +1,3 @@
1
+ export * from "./context-comparison-evaluator.js";
2
+ export * from "./context-comparison-types.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/context-comparison/index.ts"],"names":[],"mappings":"AAAA,cAAc,mCAAmC,CAAA;AACjD,cAAc,+BAA+B,CAAA"}
@@ -2,10 +2,13 @@
2
2
 
3
3
  Status: current canonical program record.
4
4
 
5
- Last audited: 2026-08-28
6
- Audited source: `f677a635040ad55d8b7d25abab280c5703a153ea`
5
+ Last reconciled: 2026-08-29
6
+ Released Context package baseline: `9b80a45070be10659150095cf701a6f375bc6600`
7
+ Released package: [`persona-harness@0.8.33`](https://www.npmjs.com/package/persona-harness/v/0.8.33)
8
+ Release lineage: [#414](https://github.com/jyt6640/persona-harness/issues/414) delivered through [#437](https://github.com/jyt6640/persona-harness/pull/437)
9
+ Historical pre-integration audit source: `f677a635040ad55d8b7d25abab280c5703a153ea`
7
10
  Program issue: [#389](https://github.com/jyt6640/persona-harness/issues/389)
8
- Current bounded issue: [#403](https://github.com/jyt6640/persona-harness/issues/403)
11
+ Remaining bounded work: [#410](https://github.com/jyt6640/persona-harness/issues/410), [#412](https://github.com/jyt6640/persona-harness/issues/412), and [#421](https://github.com/jyt6640/persona-harness/issues/421)
9
12
 
10
13
  ## Purpose
11
14
 
@@ -22,10 +25,12 @@ The Context track may advise a coding host. It must not create workflow state,
22
25
  grant completion authority, execute project commands, contact GitHub, or turn
23
26
  local preferences into a product-efficacy claim.
24
27
 
25
- ## Pre-change Baseline
28
+ ## Historical Pre-integration Baseline
26
29
 
27
- The audit used a clean worktree based on the exact source above. The original
28
- developer worktree was not modified.
30
+ This audit predates #413 and is retained to explain the original gaps and their
31
+ deterministic closure. It is not the current source or next-action authority.
32
+ The audit used a clean worktree; the original developer worktree was not
33
+ modified.
29
34
 
30
35
  | Command | Result | What the result means |
31
36
  | --- | --- | --- |
@@ -41,7 +46,10 @@ developer worktree was not modified.
41
46
  These labels distinguish a code failure from an environment prerequisite. An
42
47
  environment-blocked command must not be reported as a product failure or PASS.
43
48
 
44
- ## Existing Product Boundaries
49
+ ## Historical Pre-integration Boundaries
50
+
51
+ The following observations describe the source before #413. Current delivered
52
+ behavior and remaining work are recorded below.
45
53
 
46
54
  ### CLI and public identity
47
55
 
@@ -98,21 +106,24 @@ environment-blocked command must not be reported as a product failure or PASS.
98
106
  4m03 on the measured run. This is existing verified work, not a new claim of
99
107
  this program.
100
108
 
101
- ## P0 Problem Matrix
109
+ ## Historical P0 Problem Matrix
110
+
111
+ This matrix captures the pre-#413 candidate state. It is retained as historical
112
+ evidence rather than a description of current protected main.
102
113
 
103
114
  | Item | Classification | Audited state | Required P0 boundary |
104
115
  | --- | --- | --- | --- |
105
- | M1 | locally complete, integration pending | Broad legacy `runtimeInjection` is default-off; a narrow project philosophy feature exists separately. A distinct `context` parser now defaults to off and is controlled only by `context.enabled`. | Preserve the separate enablement boundary. |
106
- | M2 | partially closed-local | Personal/project/task profile records, the exact v1 resolver, pure v2 precedence, read-only target-path inspection, and an explicit fresh-project Context enable path now live behind `src/context-core` and `ph context`. | Preserve the no-overwrite initialization boundary; inspection and enablement must not activate a host. |
107
- | M3 | locally complete, integration pending | A read-only `.persona/team-profile.json` loader validates shared Team rules, rejects unsafe/no-follow inputs, and converts valid rules to Core `teamContracts`. | Preserve its file boundary while later exposing it through explicit Context CLI inspection only. |
108
- | M4 | locally complete, integration pending | Pure Core now supports all seven precedence layers and builds a `persona-context-envelope.v1` with deterministic selected/shadowed/conflict metadata, budget, privacy filtering, and canonical digest. | Preserve the Core boundary while later adding only a thin adapter backed by a real host API. |
109
- | M5 | locally complete, hosted observation pending | Context Core has no OpenCode or Java runtime import. An isolated OpenCode 1.x adapter now reads the local preview boundary after a safe observed target and delivers one bounded block on the next same-session user message. | Keep Core host-neutral; validate the experimental host transform only through #410's separate bounded Hosted observation. |
110
- | M6 | locally complete, hosted observation pending | The effective-profile resolver and its parsing/types remain separated in `src/context-core`; the adapter has no legacy runtime/evidence/workflow/authority/process/network dependency. | Preserve the isolated adapter boundary while observing the actual host API. |
111
- | M7 | verified-existing / open | Version-specific acceptance files have accumulated. | Use a manifest plus generic runner for new Context compatibility cases. |
112
- | M8 | closed-local | The baseline help-only contract was replaced locally by focused source tests, explicit smoke/full commands, and a generic tarball/install package smoke. | Integrate only after the local candidate is reviewed; protected CI remains unchanged. |
113
- | M9 | locally complete, hosted observation pending | `ph context status` and `ph context doctor` report the bundled OpenCode 1.x adapter plus its target-triggered eligibility without claiming a session loaded it. Preview/explain remain read-only. Bare init creates no state; `ph context init --enable` creates a minimal config only when no harness config exists. | Confirm the packaged plugin against a real host only through #410's named Hosted observation. |
114
- | M10 | open | No Context OFF/broad/targeted benchmark. | #411 adds a reproducible benchmark that reports cost and task result separately. |
115
- | M11 | verified-existing / open | Historical version checks are mostly one-off scripts. | #412 adds a Context compatibility manifest and generic test runner. |
116
+ | M1 | delivered via #413 | Workflow Integrity and Context Personalization are named as distinct tracks in public help and README. | Preserve the separate product boundary. |
117
+ | M2 | delivered via #413 | `ph context` provides explicit, default-off local Context inspection and enablement. | Preserve no-overwrite initialization and non-activating inspection. |
118
+ | M3 | delivered via #413; v2 follow-up open | A safe Team Profile v1 is resolved as a separate, local Context layer. | Preserve the no-follow, bounded profile boundary; #421 separately owns a semantic v2 schema and explicit resolver bridge without silently upgrading v1 files. |
119
+ | M4 | delivered via #413 | Pure Core resolves the seven precedence layers and produces a deterministic `persona-context-envelope.v1`. | Keep Core host-neutral. |
120
+ | M5 | implementation delivered; hosted residual | Core has no OpenCode or Java runtime import; the isolated OpenCode adapter is locally covered. | #410 may observe the real transform only after its own named Delivery Control predicate. |
121
+ | M6 | implementation delivered; hosted residual | Context resolution, rendering, and delivery are separated from legacy workflow/authority behavior. | Preserve the isolated adapter boundary during #410. |
122
+ | M7 | open | Historical version checks remain a maintenance concern. | #412 owns the generic Context compatibility manifest and runner. |
123
+ | M8 | delivered via #413 | `npm test` now selects focused source evidence and installed packages receive a separate smoke. | Keep full protected verification separate. |
124
+ | M9 | implementation delivered; hosted residual | Context CLI and doctor report bounded local state without claiming host delivery. | #410 remains the sole real-host observation route after #414. |
125
+ | M10 | delivered by #411 source boundary | #411 provides a versioned three-arm protocol, strict ten-fixture manifest, and deterministic evaluator for Context OFF, legacy broad compatibility, and targeted layered envelopes. | Keep model, host, and operational measurements unavailable until a separately authorized observation; every local product verdict remains `INCONCLUSIVE`. |
126
+ | M11 | open | Historical version-specific checks still need a version-neutral Context compatibility boundary. | #412 owns the manifest/runner work. |
116
127
  | M12 | verified-existing | CI critical-path optimization is already measured and active. | Preserve it and add only bounded Context checks to the correct lane. |
117
128
 
118
129
  ## Invariants
@@ -131,68 +142,121 @@ environment-blocked command must not be reported as a product failure or PASS.
131
142
  - No external value or adoption claim is made without independent users and
132
143
  repositories. Current product-value verdict: **INCONCLUSIVE**.
133
144
 
134
- ## Bounded Delivery Order
145
+ ## Current Delivery Order
135
146
 
136
- 1. **#390 P0 baseline and status:** this audit and canonical record.
137
- 2. **Contributor test contract:** make default test names match what they
138
- actually prove while preserving full protected verification.
139
- 3. **Context Core:** versioned input, safe Team Profile, precedence, relevance,
140
- character budget, shadowing, warnings, and digest.
141
- 4. **Context CLI and OpenCode adapter:** explicit opt-in, read-only inspection,
142
- thin host rendering, deduplication, and session cleanup.
143
- 5. **Hosted, benchmark, and compatibility:** #410 observes the real OpenCode
144
- boundary once; #411 measures OFF/targeted behavior; #412 adds a generic
145
- compatibility manifest and runner.
147
+ 1. **Merged P0 implementation:** #390 through #403 merged and closed through
148
+ #413 on `a562331f9db321845b05da1e16edc4b83bf78ece`.
149
+ 2. **Release lineage:** #414 is delivered as stable `v0.8.33` through #437;
150
+ its immutable package/source binding remains historical release evidence.
151
+ 3. **Deterministic comparison:** #411 provides the fixture-only three-arm
152
+ protocol below. It does not initiate a host, model, workflow, or authority
153
+ action and cannot establish product value.
154
+ 4. **Remaining independent work:** #410 owns the sole real OpenCode-host
155
+ observation route; #421 owns Team Profile v2 and #412 owns the generic
156
+ installed-package compatibility boundary.
146
157
 
147
158
  Only one public command, schema, resolver, adapter, CI, script, or documentation
148
159
  boundary is changed per child issue. A child issue closes only when its stated
149
160
  observable and fail-closed cases are proven. Technical completion does not
150
161
  promote the Context track to a product-value claim.
151
162
 
152
- ## Local Candidate Progress
163
+ ## Historical Candidate Evidence
164
+
165
+ The table below captures the frozen pre-#413 candidate. All #390 through #403
166
+ are now observed closed after #413 merged; GitHub does not expose a direct
167
+ PR-closing reference from each individual issue to #413, so this document does
168
+ not assert direct closure causality.
153
169
 
154
170
  | Issue | State | Evidence |
155
171
  | --- | --- | --- |
156
- | #390 | locally complete, integration pending | Canonical status, current docs navigation, inventory, docs taxonomy, acceptance index, release notes, and release truth checks pass. |
157
- | #391 | locally complete, integration pending | `npm test` now owns a dual-surface contract: a source checkout runs the bounded fast suite, while an installed tarball runs a packaged CLI-help smoke through the same command. The generic runner is included in the tarball, and the package smoke proves the installed `npm test` contract rather than only calling help directly. Tests reject cycles, missing aliases/files, help-only source defaults, empty-test escape hatches, duplicate unit/integration files, and package-to-smoke collapse. The source suite, typecheck, scope/docs checks, isolated package smoke, and resource-sensitive repository contract pass locally. |
158
- | #392 | locally complete, integration pending | Root help and README name both product tracks. The independent import-free Context dispatcher exposes five commands, creates no files, keeps Context disabled, reports no shell/network use, and blocks preview/explain with `context-core-unavailable`. Routing, compatibility, fast test, typecheck, build, docs, and isolated package smoke checks pass. |
159
- | #393 | locally complete, integration pending | `src/context-core` now owns v1 rule types, strict input parsing, deterministic resolution, a frozen default budget, canonical SHA-256 digest, and envelope types. The legacy runtime module is a compatibility re-export. Import-boundary, resolver, profile store, runtime delivery, and public export checks pass (31 focused tests); fast tests, typecheck, build, docs, scope, diff, and isolated package smoke pass. |
160
- | #394 | locally complete, integration pending | The Core adds `invariant > task > project > team > personal > language > common` precedence, topic/file-role/language/skill/scope relevance, deterministic shadow explanations, winning-layer conflict blocking, and no-silent-truncation overflow handling. The v1 adapter maps starter defaults to common and preserves the public v1 output. Five focused files (26 tests), fast tests, typecheck, build, docs, scope, diff, and isolated package smoke pass. |
161
- | #395 | locally complete, integration pending | The Core constructs `persona-context-envelope.v1` from resolution-only input. It canonicalizes selected capsules, shadow/conflict metadata, budget use, and SHA-256 digest; it blocks malformed targets, untrusted/unsafe content, blocked resolution, and budget overflow without reflection or truncation. Envelope/Core focused tests, fast tests, typecheck, build, docs, scope, diff, and isolated package smoke pass. |
162
- | #396 | locally complete, integration pending | A read-only `.persona/team-profile.json` loader uses the existing no-follow project-file reader, exact schema validation, bounded rules/selectors, and finite diagnostics. It rejects unknown fields, duplicate ids/active topics, secret/shell/exfiltration/authority-shaped rules, and symlink paths. Valid rules become Core `teamContracts`, proven with project > team > personal fixture precedence. Fast tests, typecheck, build, docs, scope, diff, and isolated package smoke pass. |
163
- | #397 | locally complete, integration pending | `.persona/harness.jsonc` now has a separately typed `context` configuration with a frozen disabled `targeted` default and bounded capsule/character limits. Missing Context config stays off; explicit `context.enabled` is independent from legacy guidance switches; malformed, unknown, and out-of-range Context fields return a finite Context-only diagnostic and disabled effective Context config without rewriting files or disabling legacy harness behavior. `npm test` (8 files, 49 tests), typecheck, build, docs/scope/diff checks, and isolated `test:package` smoke pass locally. |
164
- | #398 | locally complete, integration pending | `ph context status` now uses only the existing config and safe Team Profile readers. It renders bounded configuration/enablement/budget/Team Profile state and diagnostics, never profile/rule content. It does not write files, activate an adapter, execute workflow/authority/evidence behavior, or call network/shell/process commands. Focused status/config/team tests, the built CLI invocation, and isolated tarball `context status` smoke pass locally. |
165
- | #399 | locally complete, integration pending | `ph context preview <target-file>` parses only a safe relative target path and optional explicit selectors, never opens the target, then combines product invariants, starter defaults, an optional Team Profile, and active personal rules through the pure Core. It emits either a deterministic `persona-context-envelope.v1` JSON envelope or bounded nonreflective diagnostics. The explicit default-off flag remains informational; preview does not activate any host. Focused CLI/Core/store tests, typecheck, and the isolated tarball smoke cover the public surface. |
166
- | #400 | locally complete, integration pending | `ph context explain <target-file>` reuses the preview read boundary and renders the deterministic envelope's selected and shadowed identifiers, finite selection reasons, resolution state, budget, and digest without rendering rule content. It accepts the same safe explicit selectors, keeps Context default-off, and does not read the target, write configuration, activate a host, or create workflow state. Focused CLI/Core/store tests and the isolated tarball smoke cover the public surface. |
167
- | #401 | locally complete, integration pending | Bare `ph context init` remains a no-write preview. Explicit `ph context init --enable` uses no-follow exclusive creation to write only a minimal `.persona/harness.jsonc` Context configuration in a fresh safe project. Existing regular config files, unsafe paths, and malformed arguments return finite errors without rewriting any configuration. It does not alter legacy feature flags, activate a host, or create completion state. Focused init/status/routing tests and the isolated tarball smoke cover the public surface. |
168
- | #402 | locally complete, integration pending | `ph context doctor` now reuses the safe status readers instead of emitting fixed placeholder state. It reports bounded config/enablement/mode/budget/Team Profile diagnostics and explicitly distinguishes available local Core/CLI inspection from unavailable host delivery. It does not load personal rule content, write state, activate a host, or use network/shell/process/completion behavior. Focused doctor/status/routing tests and the isolated tarball smoke cover the public surface. |
169
- | #403 | locally complete, integration pending | The isolated OpenCode adapter captures only safe observed targets, uses the local Context preview/envelope boundary, suppresses duplicate digests until session compaction/deletion, and mutates only the next matching user message. `context.enabled` is its sole feature switch; it does not inherit `runtimeInjection`. Adapter, actual plugin composition, status/doctor wording, type compatibility, and fail-closed target cases have focused RED-to-GREEN coverage. A real `experimental.chat.messages.transform` host observation remains separate. |
172
+ | #390 | closed via #413 | Canonical status, current docs navigation, inventory, docs taxonomy, acceptance index, release notes, and release truth checks pass. |
173
+ | #391 | closed via #413 | `npm test` now owns a dual-surface contract: a source checkout runs the bounded fast suite, while an installed tarball runs a packaged CLI-help smoke through the same command. The generic runner is included in the tarball, and the package smoke proves the installed `npm test` contract rather than only calling help directly. Tests reject cycles, missing aliases/files, help-only source defaults, empty-test escape hatches, duplicate unit/integration files, and package-to-smoke collapse. The source suite, typecheck, scope/docs checks, isolated package smoke, and resource-sensitive repository contract pass locally. |
174
+ | #392 | closed via #413 | Root help and README name both product tracks. The independent import-free Context dispatcher exposes five commands, creates no files, keeps Context disabled, reports no shell/network use, and blocks preview/explain with `context-core-unavailable`. Routing, compatibility, fast test, typecheck, build, docs, and isolated package smoke checks pass. |
175
+ | #393 | closed via #413 | `src/context-core` now owns v1 rule types, strict input parsing, deterministic resolution, a frozen default budget, canonical SHA-256 digest, and envelope types. The legacy runtime module is a compatibility re-export. Import-boundary, resolver, profile store, runtime delivery, and public export checks pass (31 focused tests); fast tests, typecheck, build, docs, scope, diff, and isolated package smoke pass. |
176
+ | #394 | closed via #413 | The Core adds `invariant > task > project > team > personal > language > common` precedence, topic/file-role/language/skill/scope relevance, deterministic shadow explanations, winning-layer conflict blocking, and no-silent-truncation overflow handling. The v1 adapter maps starter defaults to common and preserves the public v1 output. Five focused files (26 tests), fast tests, typecheck, build, docs, scope, diff, and isolated package smoke pass. |
177
+ | #395 | closed via #413 | The Core constructs `persona-context-envelope.v1` from resolution-only input. It canonicalizes selected capsules, shadow/conflict metadata, budget use, and SHA-256 digest; it blocks malformed targets, untrusted/unsafe content, blocked resolution, and budget overflow without reflection or truncation. Envelope/Core focused tests, fast tests, typecheck, build, docs, scope, diff, and isolated package smoke pass. |
178
+ | #396 | closed via #413 | A read-only `.persona/team-profile.json` loader uses the existing no-follow project-file reader, exact schema validation, bounded rules/selectors, and finite diagnostics. It rejects unknown fields, duplicate ids/active topics, secret/shell/exfiltration/authority-shaped rules, and symlink paths. Valid rules become Core `teamContracts`, proven with project > team > personal fixture precedence. Fast tests, typecheck, build, docs, scope, diff, and isolated package smoke pass. |
179
+ | #397 | closed via #413 | `.persona/harness.jsonc` now has a separately typed `context` configuration with a frozen disabled `targeted` default and bounded capsule/character limits. Missing Context config stays off; explicit `context.enabled` is independent from legacy guidance switches; malformed, unknown, and out-of-range Context fields return a finite Context-only diagnostic and disabled effective Context config without rewriting files or disabling legacy harness behavior. `npm test` (8 files, 49 tests), typecheck, build, docs/scope/diff checks, and isolated `test:package` smoke pass locally. |
180
+ | #398 | closed via #413 | `ph context status` now uses only the existing config and safe Team Profile readers. It renders bounded configuration/enablement/budget/Team Profile state and diagnostics, never profile/rule content. It does not write files, activate an adapter, execute workflow/authority/evidence behavior, or call network/shell/process commands. Focused status/config/team tests, the built CLI invocation, and isolated tarball `context status` smoke pass locally. |
181
+ | #399 | closed via #413 | `ph context preview <target-file>` parses only a safe relative target path and optional explicit selectors, never opens the target, then combines product invariants, starter defaults, an optional Team Profile, and active personal rules through the pure Core. It emits either a deterministic `persona-context-envelope.v1` JSON envelope or bounded nonreflective diagnostics. The explicit default-off flag remains informational; preview does not activate any host. Focused CLI/Core/store tests, typecheck, and the isolated tarball smoke cover the public surface. |
182
+ | #400 | closed via #413 | `ph context explain <target-file>` reuses the preview read boundary and renders the deterministic envelope's selected and shadowed identifiers, finite selection reasons, resolution state, budget, and digest without rendering rule content. It accepts the same safe explicit selectors, keeps Context default-off, and does not read the target, write configuration, activate a host, or create workflow state. Focused CLI/Core/store tests and the isolated tarball smoke cover the public surface. |
183
+ | #401 | closed via #413 | Bare `ph context init` remains a no-write preview. Explicit `ph context init --enable` uses no-follow exclusive creation to write only a minimal `.persona/harness.jsonc` Context configuration in a fresh safe project. Existing regular config files, unsafe paths, and malformed arguments return finite errors without rewriting any configuration. It does not alter legacy feature flags, activate a host, or create completion state. Focused init/status/routing tests and the isolated tarball smoke cover the public surface. |
184
+ | #402 | closed via #413 | `ph context doctor` now reuses the safe status readers instead of emitting fixed placeholder state. It reports bounded config/enablement/mode/budget/Team Profile diagnostics and explicitly distinguishes available local Core/CLI inspection from unavailable host delivery. It does not load personal rule content, write state, activate a host, or use network/shell/process/completion behavior. Focused doctor/status/routing tests and the isolated tarball smoke cover the public surface. |
185
+ | #403 | closed via #413 | The isolated OpenCode adapter captures only safe observed targets, uses the local Context preview/envelope boundary, suppresses duplicate digests until session compaction/deletion, and mutates only the next matching user message. `context.enabled` is its sole feature switch; it does not inherit `runtimeInjection`. Adapter, actual plugin composition, status/doctor wording, type compatibility, and fail-closed target cases have focused RED-to-GREEN coverage. A real `experimental.chat.messages.transform` host observation remains separate. |
186
+ | #411 | delivered by this source boundary | `persona-context-comparison-manifest.1` fixes ten P0 fixtures and compares `off`, `legacy-broad`, and `targeted-layered` through `persona-context-comparison-result.1`. The repository runner requires an explicit candidate commit and package version, rejects a local identity mismatch before evaluation, and produces 30 deterministic records. It emits only rule ids/layers and digests; model/host/operational fields remain `null` and every local product verdict is `INCONCLUSIVE`. |
187
+ | #414 | delivered through #437 | Stable `v0.8.33` binds a protected-main package/source release lineage. It is immutable historical release evidence and does not authorize #410, a host session, or any Context product claim by itself. |
170
188
 
171
189
  The heavy `test:installed-package-contract` and full protected repository suite
172
190
  remain unchanged. The generic package smoke is version-neutral and does not
173
191
  replace release acceptance.
174
192
 
175
- ## Candidate Verification And Residuals
193
+ ## Historical Candidate Verification And Residuals
176
194
 
177
- The current candidate was exercised in an isolated worktree before any PR or
178
- hosted action:
195
+ The historical candidate was exercised in an isolated worktree before any PR
196
+ or hosted action:
179
197
 
180
198
  - `npm test`, `npm run typecheck`, `npm run build`, `npm run check:docs`,
181
199
  `npm run check:scope:strict`, `npm run check:release-workflows`, and
182
- `npm run check:injection-value` pass.
183
- - `npm run test:package` proves the canonical tarball can be installed in a
184
- clean consumer and that its packaged `npm test` selects the installed smoke.
185
- - `npm run test:repository:resource-sensitive` passes with 10 files and 80
200
+ `npm run check:injection-value` passed.
201
+ - `npm run test:package` proved the canonical tarball could be installed in a
202
+ clean consumer and that its packaged `npm test` selected the installed smoke.
203
+ - `npm run test:repository:resource-sensitive` passed with 10 files and 80
186
204
  tests.
187
- - `npm run test:repository:parallel` reaches 2,619 passing tests and one
188
- skip, then stops at two independent project-finish OIDC caller-pin failures.
189
- The candidate does not touch the related workflow, producer, or diagnostic
205
+ - `npm run test:repository:parallel` reached 2,619 passing tests and one skip,
206
+ then stopped at two independent project-finish OIDC caller-pin failures.
207
+ The candidate did not touch the related workflow, producer, or diagnostic
190
208
  boundary; the failures are tracked separately in #404 and are not reused as
191
209
  Context evidence.
192
210
  - A real OpenCode `experimental.chat.messages.transform` observation remains
193
211
  a hosted-only residual. Local composition and type tests do not establish
194
212
  that a host session received Context.
195
213
 
214
+ ## Current 0.8.33 Audit And Residuals
215
+
216
+ The current audit used a clean detached worktree at
217
+ `9b80a45070be10659150095cf701a6f375bc6600`; the original developer worktree
218
+ was not modified.
219
+
220
+ | Command | Result | What the result means |
221
+ | --- | --- | --- |
222
+ | `npm ci` | PASS | 209 packages installed. `npm audit` reported 7 findings; no automatic fix was applied. |
223
+ | `npm test` | PASS | 8 unit files / 50 tests and 11 integration files / 64 tests passed. |
224
+ | `npm run typecheck` | PASS | Current TypeScript source type-checks. |
225
+ | `npm run build` | PASS | Current source builds successfully. |
226
+ | `npm run test:package` | PASS | The generic package smoke passed. |
227
+ | `npm pack --dry-run --json` | PASS | Current `0.8.33` package materialized with 1,631 entries. |
228
+ | `npm run test:repository` | PASS | With the regular local GitHub CLI supplied through `PERSONA_HARNESS_OBSERVER_GH`, the chained scope, docs, release-workflow, Vitest, and authoritative package-contract checks completed successfully. |
229
+
230
+ | Boundary | Current state | Residual |
231
+ | --- | --- | --- |
232
+ | P0 implementation | #413 merged at `a562331f9db321845b05da1e16edc4b83bf78ece`; #390 through #403 are observed closed after that merge. | No integration PR remains. |
233
+ | Release lineage | #414 delivered as stable `v0.8.33` through #437 on current protected main. The immutable tag, GitHub Release, npm `latest`, canonical tar, and provenance bind to `9b80a45070be10659150095cf701a6f375bc6600`. | It does not prove live host delivery. |
234
+ | Hosted Context delivery | The released package now satisfies #410's package/source prerequisite. | #410 still needs its own named Delivery Control start predicate and one bounded real OpenCode observation. |
235
+ | Deterministic comparison | #411 provides the ten-fixture OFF / legacy broad / targeted layered protocol and repository runner. | It records only deterministic technical results; host/model/operational values remain unavailable and product verdicts remain `INCONCLUSIVE`. |
236
+ | Other follow-ups | #421 owns Team Profile v2 and #412 owns the generic Context compatibility runner. | Each remains independently open and may not manufacture host or user-value evidence. |
237
+
238
+ Product-value verdict remains **INCONCLUSIVE**. Local composition, package,
239
+ release, and CI evidence do not establish host-session delivery or user benefit.
240
+
241
+ ## #411 Comparison Protocol
242
+
243
+ The Context comparison runner is repository-side tooling, not an installed
244
+ user command. It requires an explicit full candidate commit and package version
245
+ so it can reject a checkout mismatch before it evaluates the fixed corpus:
246
+
247
+ ```bash
248
+ npm run benchmark:context -- \
249
+ --candidate-commit <full-current-commit> \
250
+ --package-version <exact-package-version>
251
+ ```
252
+
253
+ It produces one `persona-context-comparison-result.1` record for each of ten
254
+ fixtures and three arms. It emits only rule identifiers, layers, and digests;
255
+ host/model/operational measurements remain `null` and product verdicts remain
256
+ `INCONCLUSIVE`. The runner never invokes a model, host adapter, network,
257
+ workflow, authority, or evidence path. Its local Git read exists only to bind
258
+ the declared candidate to the checkout.
259
+
196
260
  ## Owner Dogfooding Follow-up
197
261
 
198
262
  The private, bounded owner dogfooding store now records the observed fixed
@@ -200,12 +264,13 @@ codes without conversation text, paths, or credentials. The remediation
200
264
  program is #405, with focused follow-ups for project-philosophy diagnostics
201
265
  (#406), deep-interview control (#407), workflow bootstrap/history diagnosis
202
266
  (#408), and shared-skill routing observability (#409). These issues do not
203
- expand this candidate or change its default-off Context boundary.
267
+ expand the released Context delivery scope or change its default-off boundary.
204
268
 
205
269
  ## Next Action
206
270
 
207
- Open one protected integration PR for the frozen #390–#403 candidate after its
208
- final local package and documentation checks. After a successful merge, #410
209
- is the only route for a real OpenCode `experimental.chat.messages.transform`
210
- observation; #411 and #412 remain separate follow-up work. Do not infer host
211
- delivery from local composition tests or catalog registration.
271
+ Do not reopen the completed #390–#403 integration or #414 release paths.
272
+ Delivery Control must record #410's own named hosted start predicate before one
273
+ real OpenCode `experimental.chat.messages.transform` observation can begin.
274
+ #421 and #412 remain independent follow-up boundaries. Do not infer host
275
+ delivery or product value from local composition tests, catalog registration,
276
+ release provenance, or historical evidence.
@@ -28,7 +28,7 @@ This inventory classifies every file under `docs/**` as of the docs taxonomy cle
28
28
  - version-specific release note: 59
29
29
  - versioned durable: 26
30
30
 
31
- Total indexed files: 340
31
+ Total indexed files: 341
32
32
 
33
33
  ## File Inventory
34
34
 
@@ -58,6 +58,7 @@ Total indexed files: 340
58
58
  | `docs/current/ci-finish-contract.md` | current active pointer/status | - | Exact CI finish exit/stream and closure JSON artifact contract; documents the absence of `finish --json`. |
59
59
  | `docs/current/clean-opencode-ph-bearshell-smoke.md` | current compatibility doc | - | Compatibility/current-era doc retained in place; migrate by summary and pointer before moving. |
60
60
  | `docs/current/consumer-authority-v1-decision.md` | current active pointer/status | - | Issue #108 V1 decision: the only enabled authority behavior is explicit `workflow finish implement --assurance cooperative` within the same Finish invocation after fixed local verification and one-time in-memory consumption; it is non-persistent, status/fetch/later closure remain blocked, and default/external boundaries remain blocked. |
61
+ | `docs/current/context-comparison-manifest.json` | current test fixture manifest | - | Exact ten-fixture source-only corpus for the Context OFF, legacy broad compatibility, and targeted layered comparison protocol. |
61
62
  | `docs/current/context-program-status.md` | current active pointer/status | - | Canonical P0 audit and isolated OpenCode delivery status for the default-off Context Personalization track and its separation from Workflow Integrity. |
62
63
  | `docs/current/desktop-test-artifacts-index.md` | current compatibility doc | - | Compatibility/current-era doc retained in place; migrate by summary and pointer before moving. |
63
64
  | `docs/current/diff-rules-classification.md` | current active pointer/status | - | T6 classification table for all `references/diff-rules` files; docs-only scope fixture for future T8/T7 decisions. |
@@ -25,7 +25,7 @@
25
25
  "package": {
26
26
  "channel": "unpublished",
27
27
  "scope": "source-candidate",
28
- "version": "0.8.33"
28
+ "version": "0.8.34"
29
29
  },
30
30
  "currentSourceCandidate": {
31
31
  "registryInstall": "requires-authorized-release-before-registry-install",
@@ -0,0 +1,39 @@
1
+ # v0.8.34 Release Notes
2
+
3
+ ## Deterministic Context Comparison
4
+
5
+ This release adds a repository-side three-arm Context comparison protocol. It
6
+ evaluates the fixed ten-fixture corpus across Context OFF, legacy broad
7
+ compatibility, and targeted layered envelopes through a single versioned result
8
+ schema.
9
+
10
+ Run it from a source checkout with an explicit full Git commit and package
11
+ version:
12
+
13
+ ```bash
14
+ npm run benchmark:context -- \
15
+ --candidate-commit <full-current-commit> \
16
+ --package-version <exact-package-version>
17
+ ```
18
+
19
+ The runner rejects a checkout identity mismatch before it evaluates the corpus.
20
+ Successful local output contains thirty deterministic records with rule
21
+ identifiers, layers, and digests only.
22
+
23
+ ## Safety And Claim Boundaries
24
+
25
+ - The comparison runner is repository tooling, not an installed user command.
26
+ - It does not invoke a model, host adapter, network, workflow, authority, or
27
+ evidence path.
28
+ - Host, model, and operational measurements remain unavailable in local output.
29
+ - Every local product verdict remains `INCONCLUSIVE`; the protocol does not
30
+ establish host delivery, user benefit, or product efficacy.
31
+ - Context remains explicit opt-in and default-off. This release does not enable
32
+ broad runtime injection.
33
+
34
+ ## Verification
35
+
36
+ The release path verifies the deterministic corpus, candidate identity
37
+ rejection, package installation, type safety, documentation, scope, protected
38
+ CI, canonical tar identity, and registry provenance before recording a stable
39
+ publication.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "persona-harness",
3
- "version": "0.8.33",
3
+ "version": "0.8.34",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.8.2",
@@ -339,9 +339,10 @@
339
339
  "observe:test-contract": "node scripts/observe-test-contract.mjs",
340
340
  "measure:entry-steering": "npm run build && node experiments/entry-intent-corpus/measure.mjs",
341
341
  "report:rules": "npm run build && node scripts/report-rule-diagnostics.mjs",
342
+ "benchmark:context": "npm run build && node scripts/eval/run-context-comparison.mjs --manifest docs/current/context-comparison-manifest.json",
342
343
  "test": "node scripts/run-default-test.mjs",
343
344
  "test:fast": "npm run test:unit && npm run test:integration",
344
- "test:unit": "vitest run --testTimeout=15000 tests/npm-test-contract.test.ts tests/context-config.test.ts tests/context-core-import-boundary.test.ts tests/context-envelope-builder.test.ts tests/effective-context-v2.test.ts tests/effective-profile-resolution.test.ts tests/phase0-harness-config.test.ts tests/opencode-skill-adapter.test.ts",
345
+ "test:unit": "vitest run --testTimeout=15000 tests/npm-test-contract.test.ts tests/context-config.test.ts tests/context-comparison.test.ts tests/context-comparison-runner.test.ts tests/context-core-import-boundary.test.ts tests/context-envelope-builder.test.ts tests/effective-context-v2.test.ts tests/effective-profile-resolution.test.ts tests/phase0-harness-config.test.ts tests/opencode-skill-adapter.test.ts",
345
346
  "test:integration": "vitest run --testTimeout=15000 tests/context-command-routing.test.ts tests/context-doctor.test.ts tests/context-init.test.ts tests/context-preview.test.ts tests/context-explain.test.ts tests/context-status.test.ts tests/opencode-context-delivery.test.ts tests/personalization-profile-store.test.ts tests/team-profile-store.test.ts tests/phase0-runtime-context-delivery.test.ts tests/personalization-profile-package-contract.test.ts",
346
347
  "test:smoke": "npm run build && node dist/cli/index.js --help",
347
348
  "test:full": "npm run test:repository",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@persona-harness/shared-skills",
3
- "version": "0.8.33",
3
+ "version": "0.8.34",
4
4
  "type": "module",
5
5
  "private": true,
6
6
  "description": "Persona-owned portable skill procedures and optional overlays",