persona-harness 0.8.36 → 0.8.37

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.
Files changed (27) hide show
  1. package/README.md +16 -0
  2. package/dist/context-external-validation/context-external-validation-parser.d.ts +3 -0
  3. package/dist/context-external-validation/context-external-validation-parser.js +251 -0
  4. package/dist/context-external-validation/context-external-validation-parser.js.map +1 -0
  5. package/dist/context-external-validation/context-external-validation-types.d.ts +77 -0
  6. package/dist/context-external-validation/context-external-validation-types.js +12 -0
  7. package/dist/context-external-validation/context-external-validation-types.js.map +1 -0
  8. package/dist/context-external-validation/context-external-validation.d.ts +2 -0
  9. package/dist/context-external-validation/context-external-validation.js +56 -0
  10. package/dist/context-external-validation/context-external-validation.js.map +1 -0
  11. package/dist/context-external-validation/index.d.ts +4 -0
  12. package/dist/context-external-validation/index.js +4 -0
  13. package/dist/context-external-validation/index.js.map +1 -0
  14. package/dist/context-external-validation.d.ts +1 -0
  15. package/dist/context-external-validation.js +2 -0
  16. package/dist/context-external-validation.js.map +1 -0
  17. package/docs/current/README.md +2 -0
  18. package/docs/current/canonical-docs-index.md +2 -0
  19. package/docs/current/context-contributor-map.json +89 -0
  20. package/docs/current/context-external-validation-status.json +7 -0
  21. package/docs/current/context-external-validation.md +91 -0
  22. package/docs/current/context-program-status.md +41 -19
  23. package/docs/current/docs-inventory.md +3 -0
  24. package/docs/current/release/consumer-authority-current-acceptance.json +1 -1
  25. package/docs/current/release/v0.8.37-release-notes.md +38 -0
  26. package/package.json +7 -3
  27. package/packages/shared-skills/package.json +1 -1
package/README.md CHANGED
@@ -95,6 +95,22 @@ Persona Harness exposes two deliberately separate tracks:
95
95
  OpenCode plugin registered, it delivers one bounded Context block only after
96
96
  a safe observed file target. It grants no completion authority.
97
97
 
98
+ ### Context Boundary
99
+
100
+ - **Activation:** `context.enabled` is explicit and `default-off`; it does not
101
+ inherit broad runtime guidance switches.
102
+ - **Authority:** Context is `non-authoritative`: it cannot grant completion or
103
+ verification authority.
104
+ - **Isolation:** Context-only paths do not execute project commands or contact
105
+ GitHub/network.
106
+ - **Host:** OpenCode is the only implemented delivery adapter; live host
107
+ delivery remains a separate, unobserved boundary.
108
+ - **Evidence:** Context usefulness remains `INCONCLUSIVE` until independent
109
+ external evidence exists.
110
+ - **Product focus:** the productized workflow focus is Java/Spring. The
111
+ TypeScript reference implementation and fixtures support this experimental
112
+ Context boundary; they are not a TypeScript code-quality claim.
113
+
98
114
  Context configuration is separate from legacy runtime guidance switches. A
99
115
  missing block stays disabled. An explicit `context.enabled` setting controls
100
116
  only the targeted Context adapter; it does not enable legacy runtime guidance,
@@ -0,0 +1,3 @@
1
+ import type { ContextExternalValidationProtocol, ContextExternalValidationStatus } from "./context-external-validation-types.js";
2
+ export declare function parseContextExternalValidationProtocol(value: unknown): ContextExternalValidationProtocol | undefined;
3
+ export declare function parseContextExternalValidationStatus(value: unknown): ContextExternalValidationStatus | undefined;
@@ -0,0 +1,251 @@
1
+ import { CONTEXT_EXTERNAL_VALIDATION_INITIAL_STATUS, CONTEXT_EXTERNAL_VALIDATION_PROTOCOL_SCHEMA, CONTEXT_EXTERNAL_VALIDATION_STATUS_SCHEMA, } from "./context-external-validation-types.js";
2
+ const CANDIDATE_KEYS = ["commit", "packageVersion", "tarSha256"];
3
+ const PARTICIPANT_KEYS = ["id", "relationship"];
4
+ const PROTOCOL_KEYS = ["candidate", "cohort", "interventionPolicy", "maximumMinutesPerStart", "schemaVersion", "taskDigest", "tokenReference"];
5
+ const STATUS_KEYS = ["observations", "productVerdict", "protocol", "schemaVersion", "status"];
6
+ const OBSERVATION_KEYS = [
7
+ "candidate",
8
+ "conflictResolution",
9
+ "contradictionIncreased",
10
+ "correctionReduced",
11
+ "durationMinutes",
12
+ "intervention",
13
+ "outcome",
14
+ "overreachIncreased",
15
+ "participantId",
16
+ "policySurvived",
17
+ "startState",
18
+ "taskDigest",
19
+ "taskRegressed",
20
+ "tokenOverheadPermille",
21
+ ];
22
+ const MINIMUM_COHORT_SIZE = 3;
23
+ const MAXIMUM_COHORT_SIZE = 5;
24
+ const MAXIMUM_MINUTES_PER_START = 240;
25
+ const MAXIMUM_RECORDED_TOKEN_OVERHEAD_PERMILLE = 10_000;
26
+ export function parseContextExternalValidationProtocol(value) {
27
+ if (!isRecord(value) || !hasExactKeys(value, PROTOCOL_KEYS) || value.schemaVersion !== CONTEXT_EXTERNAL_VALIDATION_PROTOCOL_SCHEMA)
28
+ return undefined;
29
+ const candidate = parseCandidate(value.candidate);
30
+ const cohort = parseCohort(value.cohort);
31
+ if (candidate === undefined || cohort === undefined || !isSha256(value.taskDigest))
32
+ return undefined;
33
+ if (value.tokenReference !== "same-task-context-off")
34
+ return undefined;
35
+ if (value.interventionPolicy !== "none" && value.interventionPolicy !== "clarification-only")
36
+ return undefined;
37
+ if (!isBoundedInteger(value.maximumMinutesPerStart, 1, MAXIMUM_MINUTES_PER_START))
38
+ return undefined;
39
+ return {
40
+ candidate,
41
+ cohort,
42
+ interventionPolicy: value.interventionPolicy,
43
+ maximumMinutesPerStart: value.maximumMinutesPerStart,
44
+ schemaVersion: CONTEXT_EXTERNAL_VALIDATION_PROTOCOL_SCHEMA,
45
+ taskDigest: value.taskDigest,
46
+ tokenReference: "same-task-context-off",
47
+ };
48
+ }
49
+ export function parseContextExternalValidationStatus(value) {
50
+ if (!isRecord(value) || !hasExactKeys(value, STATUS_KEYS) || value.schemaVersion !== CONTEXT_EXTERNAL_VALIDATION_STATUS_SCHEMA)
51
+ return undefined;
52
+ if (value.status === "not-started") {
53
+ if (value.protocol !== null || !isEmptyArray(value.observations) || value.productVerdict !== "INCONCLUSIVE")
54
+ return undefined;
55
+ return CONTEXT_EXTERNAL_VALIDATION_INITIAL_STATUS;
56
+ }
57
+ const protocol = parseContextExternalValidationProtocol(value.protocol);
58
+ const observations = parseObservations(value.observations);
59
+ if (protocol === undefined || observations === undefined || !observationsMatchProtocol(observations, protocol))
60
+ return undefined;
61
+ if (value.status === "preregistered") {
62
+ if (!isEmptyArray(observations) || value.productVerdict !== "INCONCLUSIVE")
63
+ return undefined;
64
+ return { observations, productVerdict: "INCONCLUSIVE", protocol, schemaVersion: CONTEXT_EXTERNAL_VALIDATION_STATUS_SCHEMA, status: "preregistered" };
65
+ }
66
+ if (value.status === "observing") {
67
+ if (observations.length === 0 || observations.length >= protocol.cohort.length || value.productVerdict !== "INCONCLUSIVE")
68
+ return undefined;
69
+ return { observations, productVerdict: "INCONCLUSIVE", protocol, schemaVersion: CONTEXT_EXTERNAL_VALIDATION_STATUS_SCHEMA, status: "observing" };
70
+ }
71
+ if (value.status !== "completed" || !hasCompleteDenominator(observations, protocol.cohort))
72
+ return undefined;
73
+ if (value.productVerdict !== "PRODUCT_GO" && value.productVerdict !== "PRODUCT_NO_GO")
74
+ return undefined;
75
+ return { observations, productVerdict: value.productVerdict, protocol, schemaVersion: CONTEXT_EXTERNAL_VALIDATION_STATUS_SCHEMA, status: "completed" };
76
+ }
77
+ function parseCandidate(value) {
78
+ if (!isRecord(value) || !hasExactKeys(value, CANDIDATE_KEYS))
79
+ return undefined;
80
+ if (!isCommit(value.commit) || !isPackageVersion(value.packageVersion) || !isSha256(value.tarSha256))
81
+ return undefined;
82
+ return { commit: value.commit, packageVersion: value.packageVersion, tarSha256: value.tarSha256 };
83
+ }
84
+ function parseCohort(value) {
85
+ if (!Array.isArray(value) || value.length < MINIMUM_COHORT_SIZE || value.length > MAXIMUM_COHORT_SIZE)
86
+ return undefined;
87
+ const cohort = [];
88
+ for (const entry of value) {
89
+ const participant = parseParticipant(entry);
90
+ if (participant === undefined)
91
+ return undefined;
92
+ cohort.push(participant);
93
+ }
94
+ return isStrictlySortedUnique(cohort.map((participant) => participant.id)) ? cohort : undefined;
95
+ }
96
+ function parseParticipant(value) {
97
+ if (!isRecord(value) || !hasExactKeys(value, PARTICIPANT_KEYS) || !isParticipantId(value.id))
98
+ return undefined;
99
+ if (value.relationship !== "independent" && value.relationship !== "past-collaborator" && value.relationship !== "disclosed-other")
100
+ return undefined;
101
+ return { id: value.id, relationship: value.relationship };
102
+ }
103
+ function parseObservations(value) {
104
+ if (!Array.isArray(value) || value.length > MAXIMUM_COHORT_SIZE)
105
+ return undefined;
106
+ const observations = [];
107
+ for (const entry of value) {
108
+ const observation = parseObservation(entry);
109
+ if (observation === undefined)
110
+ return undefined;
111
+ observations.push(observation);
112
+ }
113
+ return hasUnique(observations.map((observation) => observation.participantId)) ? observations : undefined;
114
+ }
115
+ function parseObservation(value) {
116
+ if (!isRecord(value) || !hasExactKeys(value, OBSERVATION_KEYS))
117
+ return undefined;
118
+ const candidate = parseCandidate(value.candidate);
119
+ const participantId = value.participantId;
120
+ const taskDigest = value.taskDigest;
121
+ if (candidate === undefined || !isParticipantId(participantId) || !isSha256(taskDigest))
122
+ return undefined;
123
+ const identity = { candidate, participantId, taskDigest };
124
+ if (value.startState === "accepted-start")
125
+ return parseAcceptedStart(value, identity);
126
+ if (value.startState === "declined-before-start" || value.startState === "withdrawn-before-start") {
127
+ return parseUnstartedObservation(value, identity, value.startState);
128
+ }
129
+ return undefined;
130
+ }
131
+ function parseAcceptedStart(value, identity) {
132
+ const outcome = value.outcome;
133
+ const conflictResolution = value.conflictResolution;
134
+ const contradictionIncreased = value.contradictionIncreased;
135
+ const correctionReduced = value.correctionReduced;
136
+ const durationMinutes = value.durationMinutes;
137
+ const intervention = value.intervention;
138
+ const overreachIncreased = value.overreachIncreased;
139
+ const policySurvived = value.policySurvived;
140
+ const taskRegressed = value.taskRegressed;
141
+ const tokenOverheadPermille = value.tokenOverheadPermille;
142
+ if ((outcome !== "completed" && outcome !== "not-completed") || (conflictResolution !== "accurate" && conflictResolution !== "inaccurate"))
143
+ return undefined;
144
+ if (!isBoolean(contradictionIncreased) || !isBoolean(correctionReduced) || !isBoundedInteger(durationMinutes, 1, MAXIMUM_MINUTES_PER_START))
145
+ return undefined;
146
+ if (!isBoolean(overreachIncreased) || !isBoolean(policySurvived) || !isBoolean(taskRegressed))
147
+ return undefined;
148
+ if (!isBoundedInteger(tokenOverheadPermille, 0, MAXIMUM_RECORDED_TOKEN_OVERHEAD_PERMILLE))
149
+ return undefined;
150
+ if (intervention !== "none" && intervention !== "declared-clarification")
151
+ return undefined;
152
+ return {
153
+ candidate: identity.candidate,
154
+ conflictResolution,
155
+ contradictionIncreased,
156
+ correctionReduced,
157
+ durationMinutes,
158
+ intervention,
159
+ overreachIncreased,
160
+ outcome,
161
+ participantId: identity.participantId,
162
+ policySurvived,
163
+ startState: "accepted-start",
164
+ taskDigest: identity.taskDigest,
165
+ taskRegressed,
166
+ tokenOverheadPermille,
167
+ };
168
+ }
169
+ function parseUnstartedObservation(value, identity, startState) {
170
+ if (value.outcome !== "not-observed" || value.conflictResolution !== "not-observed" || value.intervention !== "none")
171
+ return undefined;
172
+ if (value.contradictionIncreased !== null || value.correctionReduced !== null || value.durationMinutes !== null || value.overreachIncreased !== null)
173
+ return undefined;
174
+ if (value.policySurvived !== null || value.taskRegressed !== null || value.tokenOverheadPermille !== null)
175
+ return undefined;
176
+ return {
177
+ candidate: identity.candidate,
178
+ conflictResolution: "not-observed",
179
+ contradictionIncreased: null,
180
+ correctionReduced: null,
181
+ durationMinutes: null,
182
+ intervention: "none",
183
+ overreachIncreased: null,
184
+ outcome: "not-observed",
185
+ participantId: identity.participantId,
186
+ policySurvived: null,
187
+ startState,
188
+ taskDigest: identity.taskDigest,
189
+ taskRegressed: null,
190
+ tokenOverheadPermille: null,
191
+ };
192
+ }
193
+ function observationsMatchProtocol(observations, protocol) {
194
+ return observations.every((observation) => {
195
+ if (!sameCandidate(observation.candidate, protocol.candidate) || observation.taskDigest !== protocol.taskDigest)
196
+ return false;
197
+ if (!protocol.cohort.some((participant) => participant.id === observation.participantId))
198
+ return false;
199
+ if (observation.startState !== "accepted-start")
200
+ return true;
201
+ if (observation.durationMinutes === null || observation.durationMinutes > protocol.maximumMinutesPerStart)
202
+ return false;
203
+ return protocol.interventionPolicy === "clarification-only" || observation.intervention === "none";
204
+ });
205
+ }
206
+ function hasCompleteDenominator(observations, cohort) {
207
+ return observations.length === cohort.length && observations.every((observation, index) => observation.participantId === cohort[index]?.id);
208
+ }
209
+ function sameCandidate(left, right) {
210
+ return left.commit === right.commit && left.packageVersion === right.packageVersion && left.tarSha256 === right.tarSha256;
211
+ }
212
+ function hasExactKeys(value, keys) {
213
+ return Object.keys(value).length === keys.length && Object.keys(value).every((key) => keys.includes(key));
214
+ }
215
+ function isRecord(value) {
216
+ return typeof value === "object" && value !== null && !Array.isArray(value);
217
+ }
218
+ function isEmptyArray(value) {
219
+ return Array.isArray(value) && value.length === 0;
220
+ }
221
+ function isStrictlySortedUnique(values) {
222
+ let previous;
223
+ for (const value of values) {
224
+ if (previous !== undefined && previous >= value)
225
+ return false;
226
+ previous = value;
227
+ }
228
+ return true;
229
+ }
230
+ function hasUnique(values) {
231
+ return new Set(values).size === values.length;
232
+ }
233
+ function isCommit(value) {
234
+ return typeof value === "string" && /^[0-9a-f]{40}$/u.test(value);
235
+ }
236
+ function isPackageVersion(value) {
237
+ return typeof value === "string" && /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u.test(value);
238
+ }
239
+ function isSha256(value) {
240
+ return typeof value === "string" && /^[0-9a-f]{64}$/u.test(value);
241
+ }
242
+ function isParticipantId(value) {
243
+ return typeof value === "string" && /^P-(?:0[1-9]|[1-9][0-9])$/u.test(value);
244
+ }
245
+ function isBoundedInteger(value, minimum, maximum) {
246
+ return typeof value === "number" && Number.isInteger(value) && value >= minimum && value <= maximum;
247
+ }
248
+ function isBoolean(value) {
249
+ return typeof value === "boolean";
250
+ }
251
+ //# sourceMappingURL=context-external-validation-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-external-validation-parser.js","sourceRoot":"","sources":["../../src/context-external-validation/context-external-validation-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ export declare const CONTEXT_EXTERNAL_VALIDATION_PROTOCOL_SCHEMA: "persona-context-external-validation-protocol.1";
2
+ export declare const CONTEXT_EXTERNAL_VALIDATION_STATUS_SCHEMA: "persona-context-external-validation-status.1";
3
+ export declare const CONTEXT_EXTERNAL_VALIDATION_RESULT_SCHEMA: "persona-context-external-validation-result.1";
4
+ export type ContextExternalValidationCandidate = {
5
+ readonly commit: string;
6
+ readonly packageVersion: string;
7
+ readonly tarSha256: string;
8
+ };
9
+ export type ContextExternalValidationParticipant = {
10
+ readonly id: string;
11
+ readonly relationship: "independent" | "past-collaborator" | "disclosed-other";
12
+ };
13
+ export type ContextExternalValidationProtocol = {
14
+ readonly candidate: ContextExternalValidationCandidate;
15
+ readonly cohort: readonly ContextExternalValidationParticipant[];
16
+ readonly interventionPolicy: "none" | "clarification-only";
17
+ readonly maximumMinutesPerStart: number;
18
+ readonly schemaVersion: typeof CONTEXT_EXTERNAL_VALIDATION_PROTOCOL_SCHEMA;
19
+ readonly taskDigest: string;
20
+ readonly tokenReference: "same-task-context-off";
21
+ };
22
+ export type ContextExternalValidationObservation = {
23
+ readonly candidate: ContextExternalValidationCandidate;
24
+ readonly conflictResolution: "accurate" | "inaccurate" | "not-observed";
25
+ readonly contradictionIncreased: boolean | null;
26
+ readonly correctionReduced: boolean | null;
27
+ readonly durationMinutes: number | null;
28
+ readonly intervention: "none" | "declared-clarification";
29
+ readonly overreachIncreased: boolean | null;
30
+ readonly outcome: "completed" | "not-completed" | "not-observed";
31
+ readonly participantId: string;
32
+ readonly policySurvived: boolean | null;
33
+ readonly startState: "accepted-start" | "declined-before-start" | "withdrawn-before-start";
34
+ readonly taskDigest: string;
35
+ readonly taskRegressed: boolean | null;
36
+ readonly tokenOverheadPermille: number | null;
37
+ };
38
+ export type ContextExternalValidationProductVerdict = "INCONCLUSIVE" | "PRODUCT_GO" | "PRODUCT_NO_GO";
39
+ export type ContextExternalValidationStatus = {
40
+ readonly observations: readonly [];
41
+ readonly productVerdict: "INCONCLUSIVE";
42
+ readonly protocol: null;
43
+ readonly schemaVersion: typeof CONTEXT_EXTERNAL_VALIDATION_STATUS_SCHEMA;
44
+ readonly status: "not-started";
45
+ } | {
46
+ readonly observations: readonly [];
47
+ readonly productVerdict: "INCONCLUSIVE";
48
+ readonly protocol: ContextExternalValidationProtocol;
49
+ readonly schemaVersion: typeof CONTEXT_EXTERNAL_VALIDATION_STATUS_SCHEMA;
50
+ readonly status: "preregistered";
51
+ } | {
52
+ readonly observations: readonly ContextExternalValidationObservation[];
53
+ readonly productVerdict: "INCONCLUSIVE";
54
+ readonly protocol: ContextExternalValidationProtocol;
55
+ readonly schemaVersion: typeof CONTEXT_EXTERNAL_VALIDATION_STATUS_SCHEMA;
56
+ readonly status: "observing";
57
+ } | {
58
+ readonly observations: readonly ContextExternalValidationObservation[];
59
+ readonly productVerdict: "PRODUCT_GO" | "PRODUCT_NO_GO";
60
+ readonly protocol: ContextExternalValidationProtocol;
61
+ readonly schemaVersion: typeof CONTEXT_EXTERNAL_VALIDATION_STATUS_SCHEMA;
62
+ readonly status: "completed";
63
+ };
64
+ export type ContextExternalValidationResult = {
65
+ readonly code: "context-external-validation-status-invalid" | "context-external-validation-verdict-mismatch";
66
+ readonly schemaVersion: typeof CONTEXT_EXTERNAL_VALIDATION_RESULT_SCHEMA;
67
+ readonly status: "blocked";
68
+ } | {
69
+ readonly acceptedStartCount: number;
70
+ readonly independentStartCount: number;
71
+ readonly observationCount: number;
72
+ readonly phase: ContextExternalValidationStatus["status"];
73
+ readonly productVerdict: ContextExternalValidationProductVerdict;
74
+ readonly schemaVersion: typeof CONTEXT_EXTERNAL_VALIDATION_RESULT_SCHEMA;
75
+ readonly status: "ready";
76
+ };
77
+ export declare const CONTEXT_EXTERNAL_VALIDATION_INITIAL_STATUS: ContextExternalValidationStatus;
@@ -0,0 +1,12 @@
1
+ export const CONTEXT_EXTERNAL_VALIDATION_PROTOCOL_SCHEMA = "persona-context-external-validation-protocol.1";
2
+ export const CONTEXT_EXTERNAL_VALIDATION_STATUS_SCHEMA = "persona-context-external-validation-status.1";
3
+ export const CONTEXT_EXTERNAL_VALIDATION_RESULT_SCHEMA = "persona-context-external-validation-result.1";
4
+ const EMPTY_OBSERVATIONS = [];
5
+ export const CONTEXT_EXTERNAL_VALIDATION_INITIAL_STATUS = Object.freeze({
6
+ observations: EMPTY_OBSERVATIONS,
7
+ productVerdict: "INCONCLUSIVE",
8
+ protocol: null,
9
+ schemaVersion: CONTEXT_EXTERNAL_VALIDATION_STATUS_SCHEMA,
10
+ status: "not-started",
11
+ });
12
+ //# sourceMappingURL=context-external-validation-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-external-validation-types.js","sourceRoot":"","sources":["../../src/context-external-validation/context-external-validation-types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,2CAA2C,GAAG,gDAAyD,CAAA;AACpH,MAAM,CAAC,MAAM,yCAAyC,GAAG,8CAAuD,CAAA;AAChH,MAAM,CAAC,MAAM,yCAAyC,GAAG,8CAAuD,CAAA;AAwFhH,MAAM,kBAAkB,GAAgB,EAAE,CAAA;AAE1C,MAAM,CAAC,MAAM,0CAA0C,GAAoC,MAAM,CAAC,MAAM,CAAC;IACvG,YAAY,EAAE,kBAAkB;IAChC,cAAc,EAAE,cAAc;IAC9B,QAAQ,EAAE,IAAI;IACd,aAAa,EAAE,yCAAyC;IACxD,MAAM,EAAE,aAAa;CACtB,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ import type { ContextExternalValidationResult } from "./context-external-validation-types.js";
2
+ export declare function evaluateContextExternalValidationStatus(value: unknown): ContextExternalValidationResult;
@@ -0,0 +1,56 @@
1
+ import { CONTEXT_EXTERNAL_VALIDATION_RESULT_SCHEMA } from "./context-external-validation-types.js";
2
+ import { parseContextExternalValidationStatus } from "./context-external-validation-parser.js";
3
+ const MINIMUM_INDEPENDENT_STARTS = 3;
4
+ const PRODUCT_GO_TOKEN_OVERHEAD_PERMILLE = 1_300;
5
+ export function evaluateContextExternalValidationStatus(value) {
6
+ const parsed = parseContextExternalValidationStatus(value);
7
+ if (parsed === undefined)
8
+ return blocked("context-external-validation-status-invalid");
9
+ if (parsed.status === "not-started") {
10
+ return {
11
+ acceptedStartCount: 0,
12
+ independentStartCount: 0,
13
+ observationCount: 0,
14
+ phase: "not-started",
15
+ productVerdict: "INCONCLUSIVE",
16
+ schemaVersion: CONTEXT_EXTERNAL_VALIDATION_RESULT_SCHEMA,
17
+ status: "ready",
18
+ };
19
+ }
20
+ const acceptedStarts = parsed.observations.filter((observation) => observation.startState === "accepted-start");
21
+ const independentStartCount = acceptedStarts.filter((observation) => relationshipFor(parsed.protocol.cohort, observation.participantId) === "independent").length;
22
+ const productVerdict = parsed.status === "completed"
23
+ ? calculateCompletedVerdict(parsed.protocol, acceptedStarts, independentStartCount)
24
+ : "INCONCLUSIVE";
25
+ if (parsed.productVerdict !== productVerdict)
26
+ return blocked("context-external-validation-verdict-mismatch");
27
+ return {
28
+ acceptedStartCount: acceptedStarts.length,
29
+ independentStartCount,
30
+ observationCount: parsed.observations.length,
31
+ phase: parsed.status,
32
+ productVerdict,
33
+ schemaVersion: CONTEXT_EXTERNAL_VALIDATION_RESULT_SCHEMA,
34
+ status: "ready",
35
+ };
36
+ }
37
+ function calculateCompletedVerdict(protocol, acceptedStarts, independentStartCount) {
38
+ const positiveOutcomes = acceptedStarts.filter((observation) => observation.correctionReduced === true || observation.policySurvived === true).length;
39
+ const qualifies = independentStartCount >= MINIMUM_INDEPENDENT_STARTS
40
+ && positiveOutcomes >= 2
41
+ && acceptedStarts.every((observation) => observation.outcome === "completed")
42
+ && acceptedStarts.every((observation) => observation.conflictResolution === "accurate")
43
+ && acceptedStarts.every((observation) => observation.contradictionIncreased === false && observation.overreachIncreased === false)
44
+ && acceptedStarts.every((observation) => observation.taskRegressed === false)
45
+ && acceptedStarts.every((observation) => observation.durationMinutes !== null && observation.durationMinutes <= protocol.maximumMinutesPerStart)
46
+ && acceptedStarts.every((observation) => observation.tokenOverheadPermille !== null && observation.tokenOverheadPermille <= PRODUCT_GO_TOKEN_OVERHEAD_PERMILLE)
47
+ && acceptedStarts.every((observation) => observation.intervention === "none");
48
+ return qualifies ? "PRODUCT_GO" : "PRODUCT_NO_GO";
49
+ }
50
+ function relationshipFor(cohort, participantId) {
51
+ return cohort.find((participant) => participant.id === participantId)?.relationship;
52
+ }
53
+ function blocked(code) {
54
+ return { code, schemaVersion: CONTEXT_EXTERNAL_VALIDATION_RESULT_SCHEMA, status: "blocked" };
55
+ }
56
+ //# sourceMappingURL=context-external-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-external-validation.js","sourceRoot":"","sources":["../../src/context-external-validation/context-external-validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { CONTEXT_EXTERNAL_VALIDATION_INITIAL_STATUS, CONTEXT_EXTERNAL_VALIDATION_PROTOCOL_SCHEMA, CONTEXT_EXTERNAL_VALIDATION_RESULT_SCHEMA, CONTEXT_EXTERNAL_VALIDATION_STATUS_SCHEMA, } from "./context-external-validation-types.js";
2
+ export type { ContextExternalValidationCandidate, ContextExternalValidationObservation, ContextExternalValidationParticipant, ContextExternalValidationProductVerdict, ContextExternalValidationProtocol, ContextExternalValidationResult, ContextExternalValidationStatus, } from "./context-external-validation-types.js";
3
+ export { evaluateContextExternalValidationStatus } from "./context-external-validation.js";
4
+ export { parseContextExternalValidationProtocol, parseContextExternalValidationStatus } from "./context-external-validation-parser.js";
@@ -0,0 +1,4 @@
1
+ export { CONTEXT_EXTERNAL_VALIDATION_INITIAL_STATUS, CONTEXT_EXTERNAL_VALIDATION_PROTOCOL_SCHEMA, CONTEXT_EXTERNAL_VALIDATION_RESULT_SCHEMA, CONTEXT_EXTERNAL_VALIDATION_STATUS_SCHEMA, } from "./context-external-validation-types.js";
2
+ export { evaluateContextExternalValidationStatus } from "./context-external-validation.js";
3
+ export { parseContextExternalValidationProtocol, parseContextExternalValidationStatus } from "./context-external-validation-parser.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/context-external-validation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0CAA0C,EAC1C,2CAA2C,EAC3C,yCAAyC,EACzC,yCAAyC,GAC1C,MAAM,wCAAwC,CAAA;AAU/C,OAAO,EAAE,uCAAuC,EAAE,MAAM,kCAAkC,CAAA;AAC1F,OAAO,EAAE,sCAAsC,EAAE,oCAAoC,EAAE,MAAM,yCAAyC,CAAA"}
@@ -0,0 +1 @@
1
+ export * from "./context-external-validation/index.js";
@@ -0,0 +1,2 @@
1
+ export * from "./context-external-validation/index.js";
2
+ //# sourceMappingURL=context-external-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-external-validation.js","sourceRoot":"","sources":["../src/context-external-validation.ts"],"names":[],"mappings":"AAAA,cAAc,wCAAwC,CAAA"}
@@ -23,6 +23,8 @@ history but do not become a current product or release claim.
23
23
  | Use the portable shared-skill or product-discovery guidance | [Persona Shared Skills Core](persona-shared-skills-core.md) |
24
24
  | Maintain a local personalization profile | [Personalization Profile V1](personalization-profile-v1.md) |
25
25
  | Follow the Context Personalization program | [Context Personalization Program Status](context-program-status.md) |
26
+ | Contribute to Context Personalization safely | [Context contributor map](context-contributor-map.json) |
27
+ | Prepare or audit Context external validation | [Context External Validation Protocol](context-external-validation.md) |
26
28
  | Define safe project-shareable team conventions | [Team Profile V2](context-team-profile-v2.md) |
27
29
  | Understand claims and measurement limits | [Measurement scorecard](measurement-scorecard.md) |
28
30
  | Review Finish or external authority boundaries | [Consumer Authority V1 decision](consumer-authority-v1-decision.md); the repository-only external-attested walkthrough supplies the full procedure |
@@ -16,6 +16,8 @@ Start with [Current Docs](README.md) unless you need a specific decision.
16
16
  | Portable shared-skill and product-discovery contract | `docs/current/persona-shared-skills-core.md` | Catalog ownership, interview approval, explicit handoffs, host boundary, and packaged surface. |
17
17
  | Personalization profile store | `docs/current/personalization-profile-v1.md` | Versioned local profile records, append-only lifecycle, privacy, and fail-closed storage. |
18
18
  | Context Personalization program | `docs/current/context-program-status.md` | Canonical P0 audit, isolated OpenCode delivery boundary, separation invariants, and claim status. |
19
+ | Context contributor map | `docs/current/context-contributor-map.json` | Machine-checked current source ownership, credential-free local checks, and boundaries that stay separate from Context work. |
20
+ | Context external-validation protocol | `docs/current/context-external-validation.md` | Strict preregistration and finite result-status contract; default state is no observations and `INCONCLUSIVE`. |
19
21
  | Team Profile V2 boundary | `docs/current/context-team-profile-v2.md` | Read-only project-shareable v2 Team Profile schema, v1 separation, shared-text safety, and pure resolver bridge. |
20
22
  | External environment procedure | `docs/current/external-environment-verification.md` | A bounded packaged-install check on a separate machine. |
21
23
  | External-attested Finish walkthrough | `docs/current/external-attested-finish-walkthrough.md` | Source-checkout-only enrolled/fetch/Finish/replay procedure and its limits. |
@@ -0,0 +1,89 @@
1
+ {
2
+ "schemaVersion": "persona-context-contributor-map.2",
3
+ "localChecks": [
4
+ {
5
+ "script": "test",
6
+ "command": "npm test"
7
+ },
8
+ {
9
+ "script": "typecheck",
10
+ "command": "npm run typecheck"
11
+ },
12
+ {
13
+ "script": "check:docs",
14
+ "command": "npm run check:docs"
15
+ }
16
+ ],
17
+ "operationalRoutes": [
18
+ {
19
+ "id": "private-security-report",
20
+ "marker": "## Reporting a vulnerability",
21
+ "path": "SECURITY.md"
22
+ },
23
+ {
24
+ "id": "context-local-verification",
25
+ "marker": "## Context contribution route",
26
+ "path": "CONTRIBUTING.md",
27
+ "script": "test"
28
+ },
29
+ {
30
+ "id": "owner-release-operations",
31
+ "marker": "# Release Operations",
32
+ "path": "docs/current/release/README.md"
33
+ },
34
+ {
35
+ "command": "npx ph doctor",
36
+ "id": "bootstrap-intake-diagnosis",
37
+ "marker": "if (command === \"doctor\")",
38
+ "path": "src/cli/index.ts"
39
+ }
40
+ ],
41
+ "ownership": [
42
+ {
43
+ "id": "context-core",
44
+ "paths": ["src/context-core/"]
45
+ },
46
+ {
47
+ "id": "context-profile",
48
+ "paths": ["src/context-profile/"]
49
+ },
50
+ {
51
+ "id": "context-cli",
52
+ "paths": ["src/cli/context-command.ts"]
53
+ },
54
+ {
55
+ "id": "context-delivery",
56
+ "paths": ["src/context-delivery/opencode-context-hooks.ts"]
57
+ },
58
+ {
59
+ "id": "context-external-validation",
60
+ "paths": ["src/context-external-validation/"]
61
+ },
62
+ {
63
+ "id": "workflow-integrity",
64
+ "paths": ["src/cli/workflow-command.ts", "src/cli/authority-command.ts"]
65
+ }
66
+ ],
67
+ "separateBoundaries": [
68
+ {
69
+ "id": "installed-package",
70
+ "reference": "test:package"
71
+ },
72
+ {
73
+ "id": "repository-contract",
74
+ "reference": "test:repository"
75
+ },
76
+ {
77
+ "id": "p0-implementation-release",
78
+ "reference": "#414"
79
+ },
80
+ {
81
+ "id": "generic-compatibility-release",
82
+ "reference": "#412"
83
+ },
84
+ {
85
+ "id": "host-observation",
86
+ "reference": "#410"
87
+ }
88
+ ]
89
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "observations": [],
3
+ "productVerdict": "INCONCLUSIVE",
4
+ "protocol": null,
5
+ "schemaVersion": "persona-context-external-validation-status.1",
6
+ "status": "not-started"
7
+ }
@@ -0,0 +1,91 @@
1
+ # Context External Validation Protocol
2
+
3
+ Status: current Context-specific preregistration and result-status contract.
4
+
5
+ Machine-readable current state:
6
+ [`context-external-validation-status.json`](context-external-validation-status.json).
7
+ It records no protocol, no observations, and an `INCONCLUSIVE` product verdict.
8
+ That is an absence of external evidence, not a negative result and not an
9
+ invitation to simulate participants.
10
+
11
+ ## Purpose And Separation
12
+
13
+ This protocol belongs to Context Personalization M9 and is tracked by
14
+ [#429](https://github.com/jyt6640/persona-harness/issues/429). It records what
15
+ must be fixed before a future independent observation can be interpreted.
16
+
17
+ It does not replace either of these separate boundaries:
18
+
19
+ - `context-comparison-manifest.json` is deterministic local fixture evidence
20
+ for OFF, legacy-broad, and targeted layered Context composition.
21
+ - The independent Spring maintainer procedure is a Workflow Integrity
22
+ experiment and is not Context product-value evidence.
23
+
24
+ No command, runtime hook, network call, GitHub authority action, workflow
25
+ state, or participant action is implemented by this protocol. The evaluator is
26
+ pure TypeScript and only validates supplied JSON-shaped values. It is available
27
+ from the installed package as `persona-harness/context-external-validation`;
28
+ that subpath is a parser and evaluator, not an observation runner.
29
+
30
+ ## Schemas
31
+
32
+ The protocol uses `persona-context-external-validation-protocol.1`. Before any
33
+ observation begins it requires exactly:
34
+
35
+ - a 40-character candidate commit, package version, and SHA-256 tar digest;
36
+ - one SHA-256 task digest, rather than task text, prompts, source, paths, or
37
+ participant contact information;
38
+ - a three-to-five member pseudonymous cohort (`P-01` through `P-99`) with a
39
+ finite relationship category;
40
+ - a finite per-start time limit, one declared intervention policy, and the
41
+ fixed `same-task-context-off` token reference.
42
+
43
+ The result record uses `persona-context-external-validation-status.1` with
44
+ four states:
45
+
46
+ | State | Required meaning | Allowed product verdict |
47
+ | --- | --- | --- |
48
+ | `not-started` | No protocol and no observations have been recorded. | `INCONCLUSIVE` |
49
+ | `preregistered` | An exact protocol exists, but no observation has started. | `INCONCLUSIVE` |
50
+ | `observing` | A strict subset of the cohort has terminal records. | `INCONCLUSIVE` |
51
+ | `completed` | Every cohort member has exactly one terminal record. | Calculated `PRODUCT_GO` or `PRODUCT_NO_GO` |
52
+
53
+ Unknown fields, unbounded text, raw participant data, URLs, paths, credential
54
+ shapes, unsupported relationship or intervention values, candidate mismatches,
55
+ and malformed metrics are rejected. A missing protocol after `not-started`, a
56
+ partial completed denominator, or a mismatched claimed verdict is also
57
+ rejected.
58
+
59
+ ## Denominator And Verdict
60
+
61
+ Each `completed` record must contain exactly one entry for every preregistered
62
+ cohort pseudonym. An `accepted-start` carries bounded outcome metrics; a
63
+ declined or pre-start withdrawal carries only fixed `not-observed` null
64
+ metrics. This keeps every accepted start in the denominator and prevents a
65
+ selective completed result.
66
+
67
+ `PRODUCT_GO` is calculated only when all of the following are true:
68
+
69
+ 1. At least three recorded starts are independent.
70
+ 2. At least two starts reduce corrections or preserve the declared policy.
71
+ 3. Every started record completed the task, resolved its conflict accurately,
72
+ had no task regression, contradiction increase, or overreach increase, and
73
+ stayed inside the preregistered time budget.
74
+ 4. Every started record has token overhead at or below `1300` permille (1.3x)
75
+ and no maintainer intervention.
76
+
77
+ `tokenOverheadPermille` is a normalized comparison value against the fixed
78
+ `same-task-context-off` reference: `1000` means the reference amount. The
79
+ status file retains neither raw token counts nor prompts; it only accepts the
80
+ bounded normalized metric.
81
+
82
+ A valid completed cohort that misses any criterion is `PRODUCT_NO_GO`. Before
83
+ completion, or with no external evidence, the only possible verdict is
84
+ `INCONCLUSIVE`. The record never stores raw prompts, source, paths,
85
+ credentials, participant names, or free-form feedback.
86
+
87
+ ## What This Does Not Claim
88
+
89
+ The initial status does not show that an external host received Context, that a
90
+ model followed it, that users benefited, or that token use improved. It only
91
+ makes the future evidence bar reproducible and fail-closed.
@@ -12,9 +12,12 @@ Current comparison lineage: [#411](https://github.com/jyt6640/persona-harness/is
12
12
  Current Team Profile v2 release: `90a913168edac40eb29290e7ff47885bb94b30fd`
13
13
  Current Team Profile v2 package: [`persona-harness@0.8.35`](https://www.npmjs.com/package/persona-harness/v/0.8.35)
14
14
  Current Team Profile v2 lineage: [#421](https://github.com/jyt6640/persona-harness/issues/421) delivered through [#440](https://github.com/jyt6640/persona-harness/pull/440)
15
+ Current compatibility release: `9e8dcc3e72fab52dcb71c12c1a45cd3846929be8`
16
+ Current compatibility package: [`persona-harness@0.8.36`](https://www.npmjs.com/package/persona-harness/v/0.8.36)
17
+ Current compatibility lineage: [#412](https://github.com/jyt6640/persona-harness/issues/412) delivered through [#441](https://github.com/jyt6640/persona-harness/pull/441)
15
18
  Historical pre-integration audit source: `f677a635040ad55d8b7d25abab280c5703a153ea`
16
19
  Program issue: [#389](https://github.com/jyt6640/persona-harness/issues/389)
17
- Remaining bounded work: [#410](https://github.com/jyt6640/persona-harness/issues/410) and [#412](https://github.com/jyt6640/persona-harness/issues/412)
20
+ Remaining bounded work: hosted residual [#410](https://github.com/jyt6640/persona-harness/issues/410), plus local integration candidates [#429](https://github.com/jyt6640/persona-harness/issues/429), [#430](https://github.com/jyt6640/persona-harness/issues/430), [#433](https://github.com/jyt6640/persona-harness/issues/433), [#434](https://github.com/jyt6640/persona-harness/issues/434), [#435](https://github.com/jyt6640/persona-harness/issues/435), and [#436](https://github.com/jyt6640/persona-harness/issues/436)
18
21
 
19
22
  ## Purpose
20
23
 
@@ -125,12 +128,14 @@ evidence rather than a description of current protected main.
125
128
  | M4 | delivered via #413 | Pure Core resolves the seven precedence layers and produces a deterministic `persona-context-envelope.v1`. | Keep Core host-neutral. |
126
129
  | 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. |
127
130
  | M6 | implementation delivered; hosted residual | Context resolution, rendering, and delivery are separated from legacy workflow/authority behavior. | Preserve the isolated adapter boundary during #410. |
128
- | M7 | in progress | Historical version checks remain a maintenance concern. | #412 owns the generic Context compatibility manifest and runner. |
131
+ | M7 | delivered and released via #412/#441 | The generic Context compatibility manifest and runner are version-neutral. | Preserve the manifest-driven runner. |
129
132
  | M8 | delivered via #413 | `npm test` now selects focused source evidence and installed packages receive a separate smoke. | Keep full protected verification separate. |
130
- | 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. |
131
- | M10 | delivered and released via #411/#439 | #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`. |
132
- | M11 | in progress | Historical version-specific checks still need a version-neutral Context compatibility boundary. | #412 owns the manifest/runner work. |
133
- | M12 | verified-existing | CI critical-path optimization is already measured and active. | Preserve it and add only bounded Context checks to the correct lane. |
133
+ | M9 | implementation candidate; external evidence absent | Local Context inspection and deterministic fixtures do not establish independent usefulness. | #429 adds a strict preregistration and result-status contract; its committed state records no observation and `INCONCLUSIVE`. |
134
+ | M10 | delivered via #411/#439; #436 local candidate | #411 provides a versioned three-arm protocol, strict ten-fixture manifest, and deterministic evaluator for Context OFF, legacy broad compatibility, and targeted layered envelopes. #436 adds an explicit clean-current-checkout candidate source without changing the fixed corpus. | Keep model, host, and operational measurements unavailable until a separately authorized observation; every local product verdict remains `INCONCLUSIVE`. |
135
+ | M11 | delivered and released via #412/#441 | The installed-package compatibility boundary uses a generic manifest and runner. | Keep version-specific acceptance scripts out of new Context changes. |
136
+ | M12 | verified-existing; #431 local candidate | CI critical-path optimization is already measured and active. #431 classifies an unavailable repository observer as `clean-package-observer-gh-required` rather than a source-test failure. | Preserve the critical path; treat the named observer prerequisite as `ENVIRONMENT_BLOCKED` and add only bounded Context checks to the correct lane. |
137
+ | M13 | mixed: #412 delivered; #430/#435 local candidates | Stable `v0.8.36` provides the generic manifest/runner; the contributor map and its security/release/bootstrap-intake routes are local candidates for a readable credential-free contributor route. | Preserve generic package/source-fallback checks and keep the route separate from hosted or release work. |
138
+ | M14 | #433 local candidate | The README entrypoint makes Context activation, authority, host, evidence, and product-focus limits explicit, with usefulness still `INCONCLUSIVE`. | Preserve the public boundary without promoting local evidence to host delivery or product value. |
134
139
 
135
140
  ## Invariants
136
141
 
@@ -163,9 +168,20 @@ evidence rather than a description of current protected main.
163
168
  4. **Team Profile v2 release:** #421 is delivered as stable `v0.8.35` through
164
169
  #440 on `90a913168edac40eb29290e7ff47885bb94b30fd`. It preserves the
165
170
  explicit Context boundary and does not begin host observation.
166
- 5. **Remaining independent work:** #410 owns the sole real OpenCode-host
167
- observation route and #412 owns the generic installed-package compatibility
168
- boundary.
171
+ 5. **Compatibility release:** #412 is delivered as stable `v0.8.36` through
172
+ #441 on `9e8dcc3e72fab52dcb71c12c1a45cd3846929be8`. It provides the
173
+ generic installed-package compatibility manifest and runner.
174
+ 6. **Remaining independent work:** #410 owns the sole real OpenCode-host
175
+ observation route. #429 owns a preregistered external-validation schema
176
+ whose initial state remains `INCONCLUSIVE` without an observation.
177
+ 7. **Current local P0 candidates:** #429 records the external-validation
178
+ parser/evaluator and empty status, #430 records the contributor map, #433
179
+ records the README claim boundary, #434 reconciles current program status,
180
+ #435 binds contributor operations to existing security/release/diagnosis
181
+ routes, #436 adds the explicit clean-current-checkout comparison route, and
182
+ #431 classifies the repository observer prerequisite before package work.
183
+ They are local integration candidates only; none is release, host-delivery,
184
+ or product-value evidence.
169
185
 
170
186
  Only one public command, schema, resolver, adapter, CI, script, or documentation
171
187
  boundary is changed per child issue. A child issue closes only when its stated
@@ -195,7 +211,7 @@ not assert direct closure causality.
195
211
  | #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. |
196
212
  | #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. |
197
213
  | #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. |
198
- | #411 | delivered through #439 | Stable `v0.8.34` binds the deterministic three-arm comparison source at `19c397e4fed5b1cce7d024fbcc51350e9676105f`. `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`. |
214
+ | #411 | delivered through #439; #436 local candidate | Stable `v0.8.34` binds the deterministic three-arm comparison source at `19c397e4fed5b1cce7d024fbcc51350e9676105f`. `persona-context-comparison-manifest.1` fixes ten P0 fixtures and compares `off`, `legacy-broad`, and `targeted-layered` through `persona-context-comparison-result.1`. The historical runner accepts explicit candidate commit and package-version metadata; #436 adds a distinct explicit `--current-checkout` source that binds a clean root checkout before evaluation. Both forms produce 30 deterministic records and emit only rule ids/layers and digests; model/host/operational fields remain `null` and every local product verdict is `INCONCLUSIVE`. |
199
215
  | #414 | delivered through #437 | Stable `v0.8.33` binds the P0 implementation 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. |
200
216
  | #421 | delivered through #440 | Stable `v0.8.35` binds the Team Profile v2 source at `90a913168edac40eb29290e7ff47885bb94b30fd`. The separate JSONC loader and explicit pure-resolver layer reject unknown fields, unsafe shared text, duplicate ids, active topic conflicts, malformed JSONC, and symlinked files without reading personal state or activating a host. | Release and provenance evidence do not begin CLI delivery, adapter delivery, runtime activation, or external effectiveness observation. |
201
217
 
@@ -246,7 +262,7 @@ was not modified.
246
262
  | P0 implementation release lineage | #414 delivered stable `v0.8.33` through #437. Its immutable tag, GitHub Release, npm `latest`, canonical tar, and provenance bind to `9b80a45070be10659150095cf701a6f375bc6600`. | Historical P0 implementation release evidence does not prove live host delivery. |
247
263
  | Deterministic comparison release lineage | #411 delivered stable `v0.8.34` through #439. Its immutable tag, GitHub Release, npm `latest`, canonical tar, and provenance bind to `19c397e4fed5b1cce7d024fbcc51350e9676105f`. | It records only deterministic technical results; host/model/operational values remain unavailable and product verdicts remain `INCONCLUSIVE`. |
248
264
  | Hosted Context delivery | The current published comparison package contains the merged #403 adapter boundary, but no package/release record substitutes for the #410 start predicate. | #410 still needs its own named Delivery Control start predicate and one bounded real OpenCode observation. |
249
- | Other follow-ups | #421 is delivered as stable `v0.8.35` through #440; #412 owns the generic Context compatibility runner. | #412 may not manufacture host or user-value evidence. |
265
+ | Other follow-ups | #421 is delivered as stable `v0.8.35` through #440; #412 is delivered as stable `v0.8.36` through #441. | Neither release manufactures host or user-value evidence. |
250
266
 
251
267
  Product-value verdict remains **INCONCLUSIVE**. Local composition, package,
252
268
  release, and CI evidence do not establish host-session delivery or user benefit.
@@ -254,15 +270,20 @@ release, and CI evidence do not establish host-session delivery or user benefit.
254
270
  ## #411 Comparison Protocol
255
271
 
256
272
  The Context comparison runner is repository-side tooling, not an installed
257
- user command. It requires an explicit full candidate commit and package version
258
- so it can reject a checkout mismatch before it evaluates the fixed corpus:
273
+ user command. Its default command explicitly selects the clean current
274
+ checkout as the candidate source:
259
275
 
260
276
  ```bash
261
- npm run benchmark:context -- \
262
- --candidate-commit <full-current-commit> \
263
- --package-version <exact-package-version>
277
+ npm run benchmark:context
264
278
  ```
265
279
 
280
+ The runner reads only the local Git root, full `HEAD`, clean working-tree state,
281
+ and root `package.json` version for that mode. For reproducible supplied
282
+ metadata, invoke the runner directly with both `--candidate-commit` and
283
+ `--package-version`; mixing the two source forms, partial metadata, a dirty
284
+ checkout, or a package root outside the Git root fails before manifest
285
+ evaluation.
286
+
266
287
  It produces one `persona-context-comparison-result.1` record for each of ten
267
288
  fixtures and three arms. It emits only rule identifiers, layers, and digests;
268
289
  host/model/operational measurements remain `null` and product verdicts remain
@@ -284,6 +305,7 @@ expand the released Context delivery scope or change its default-off boundary.
284
305
  Do not reopen the completed #390–#403 integration or #414 release paths.
285
306
  Delivery Control must record #410's own named hosted start predicate before one
286
307
  real OpenCode `experimental.chat.messages.transform` observation can begin.
287
- #412 remains an independent follow-up boundary. Do not infer host delivery or
288
- product value from local composition tests, catalog registration, release
289
- provenance, or historical evidence.
308
+ #429 may validate a preregistration/result schema, but its initial state must
309
+ remain `INCONCLUSIVE`. Do not infer host delivery or product value from local
310
+ composition tests, catalog registration, release provenance, an empty
311
+ external-validation status, or historical evidence.
@@ -59,6 +59,9 @@ Total indexed files: 342
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
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. |
62
+ | `docs/current/context-contributor-map.json` | current test fixture manifest | - | Machine-readable current source-path and npm-script bindings for the Context contributor ownership map and local verification route. |
63
+ | `docs/current/context-external-validation-status.json` | current active pointer/status | - | Machine-readable initial state for the Context external-validation protocol; it records no observations and an `INCONCLUSIVE` product verdict. |
64
+ | `docs/current/context-external-validation.md` | current active pointer/status | - | Context-specific preregistration, denominator, privacy, and finite outcome contract for future independent observation; it does not record one. |
62
65
  | `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. |
63
66
  | `docs/current/context-team-profile-v2.md` | current active pointer/status | - | Read-only project-shareable Team Profile v2 schema, safety boundary, v1 separation, and pure resolver bridge. |
64
67
  | `docs/current/desktop-test-artifacts-index.md` | current compatibility doc | - | Compatibility/current-era doc retained in place; migrate by summary and pointer before moving. |
@@ -25,7 +25,7 @@
25
25
  "package": {
26
26
  "channel": "unpublished",
27
27
  "scope": "source-candidate",
28
- "version": "0.8.36"
28
+ "version": "0.8.37"
29
29
  },
30
30
  "currentSourceCandidate": {
31
31
  "registryInstall": "requires-authorized-release-before-registry-install",
@@ -0,0 +1,38 @@
1
+ # v0.8.37 Release Notes
2
+
3
+ ## Context P0 Boundaries
4
+
5
+ This release consolidates the deterministic Context Personalization boundaries
6
+ that stay separate from Workflow Integrity. It adds a preregistered
7
+ external-validation protocol with an explicit empty result state, contributor
8
+ ownership and operational-route maps, a public README claim boundary, and a
9
+ benchmark command bound to the clean checked-out source identity.
10
+
11
+ The comparison protocol continues to distinguish deterministic technical
12
+ results from product usefulness. Without a preregistered external observation,
13
+ the product verdict remains `INCONCLUSIVE`.
14
+
15
+ ## Repository Contract Clarity
16
+
17
+ The full repository contract now classifies an unavailable selected observer
18
+ path as `clean-package-observer-gh-required`. This is an
19
+ `ENVIRONMENT_BLOCKED` prerequisite, not a source-test failure. Empty or missing
20
+ observer input stops before package preparation; nonempty malformed paths remain
21
+ argument errors.
22
+
23
+ ## Safety And Scope Boundaries
24
+
25
+ - Context remains explicit opt-in and default-off.
26
+ - Context-only paths do not infer workflow, shell/process execution, network,
27
+ GitHub, evidence, authority, credential, or host-observation actions.
28
+ - This release does not claim a live OpenCode delivery result, external user
29
+ result, token saving, or product efficacy.
30
+ - Historical releases remain immutable and cannot supply current package or
31
+ host-observation evidence.
32
+
33
+ ## Verification
34
+
35
+ The delivery path verifies default unit and integration contracts, Context
36
+ comparison source binding, type safety, documentation and release-policy
37
+ checks, a fresh isolated tarball installation, protected CI, canonical package
38
+ identity, and registry provenance.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "persona-harness",
3
- "version": "0.8.36",
3
+ "version": "0.8.37",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.8.2",
@@ -14,6 +14,7 @@
14
14
  },
15
15
  "exports": {
16
16
  ".": "./dist/index.js",
17
+ "./context-external-validation": "./dist/context-external-validation.js",
17
18
  "./effective-profile": "./dist/effective-profile.js",
18
19
  "./portable-skill": "./dist/portable-skill.js"
19
20
  },
@@ -62,6 +63,9 @@
62
63
  "docs/current/v0.3.0-alpha-publish-readiness.md",
63
64
  "docs/current/persona-harness-detailed-usage.md",
64
65
  "docs/current/context-program-status.md",
66
+ "docs/current/context-contributor-map.json",
67
+ "docs/current/context-external-validation.md",
68
+ "docs/current/context-external-validation-status.json",
65
69
  "docs/current/context-team-profile-v2.md",
66
70
  "docs/current/README.md",
67
71
  "docs/current/personalization-profile-v1.md",
@@ -340,10 +344,10 @@
340
344
  "observe:test-contract": "node scripts/observe-test-contract.mjs",
341
345
  "measure:entry-steering": "npm run build && node experiments/entry-intent-corpus/measure.mjs",
342
346
  "report:rules": "npm run build && node scripts/report-rule-diagnostics.mjs",
343
- "benchmark:context": "npm run build && node scripts/eval/run-context-comparison.mjs --manifest docs/current/context-comparison-manifest.json",
347
+ "benchmark:context": "npm run build && node scripts/eval/run-context-comparison.mjs --manifest docs/current/context-comparison-manifest.json --current-checkout",
344
348
  "test": "node scripts/run-default-test.mjs",
345
349
  "test:fast": "npm run test:unit && npm run test:integration",
346
- "test:unit": "vitest run --testTimeout=15000 tests/npm-test-contract.test.ts tests/context-compatibility-manifest.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",
350
+ "test:unit": "vitest run --testTimeout=15000 tests/npm-test-contract.test.ts tests/context-compatibility-manifest.test.ts tests/context-config.test.ts tests/context-comparison.test.ts tests/context-comparison-runner.test.ts tests/context-contributor-route.test.ts tests/context-core-import-boundary.test.ts tests/context-envelope-builder.test.ts tests/context-external-validation.test.ts tests/context-program-status.test.ts tests/context-readme-boundary.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",
347
351
  "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/team-profile-v2-store.test.ts tests/phase0-runtime-context-delivery.test.ts tests/personalization-profile-package-contract.test.ts",
348
352
  "test:smoke": "npm run build && node dist/cli/index.js --help",
349
353
  "test:full": "npm run test:repository",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@persona-harness/shared-skills",
3
- "version": "0.8.36",
3
+ "version": "0.8.37",
4
4
  "type": "module",
5
5
  "private": true,
6
6
  "description": "Persona-owned portable skill procedures and optional overlays",