persona-harness 0.8.39 → 0.8.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -0
- package/dist/runtime/product-deep-interview.d.ts +5 -0
- package/dist/runtime/product-deep-interview.js +38 -13
- package/dist/runtime/product-deep-interview.js.map +1 -1
- package/dist/runtime/product-interview-control.d.ts +4 -0
- package/dist/runtime/product-interview-control.js +57 -0
- package/dist/runtime/product-interview-control.js.map +1 -0
- package/docs/current/context-program-status.md +25 -10
- package/docs/current/persona-shared-skills-core.md +15 -0
- package/docs/current/release/consumer-authority-current-acceptance.json +1 -1
- package/docs/current/release/v0.8.40-release-notes.md +38 -0
- package/package.json +1 -1
- package/packages/shared-skills/package.json +1 -1
package/README.md
CHANGED
|
@@ -148,6 +148,47 @@ local configuration and Team Profile state, including the bundled OpenCode 1.x
|
|
|
148
148
|
adapter. It cannot prove that a particular OpenCode session has loaded the
|
|
149
149
|
project plugin.
|
|
150
150
|
|
|
151
|
+
### Context Lifecycle
|
|
152
|
+
|
|
153
|
+
Context configuration lives only in `.persona/harness.jsonc`. Inspect the
|
|
154
|
+
current local state before changing it:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
npx ph context status
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
For a safe project with no existing harness configuration, create the minimal
|
|
161
|
+
opt-in configuration explicitly:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
npx ph context init --enable
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
The command does not overwrite an existing `.persona/harness.jsonc`. For an
|
|
168
|
+
existing harness configuration, review and preserve the file, then manually
|
|
169
|
+
merge only this top-level `context` object using its existing JSONC style:
|
|
170
|
+
|
|
171
|
+
```jsonc
|
|
172
|
+
{
|
|
173
|
+
"context": {
|
|
174
|
+
"enabled": true,
|
|
175
|
+
"mode": "targeted",
|
|
176
|
+
"maxCapsules": 8,
|
|
177
|
+
"maxChars": 1600
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
To disable Context while keeping its bounded settings for a later opt-in, set
|
|
183
|
+
`context.enabled` to `false`. A missing `context` object is also disabled by
|
|
184
|
+
default. Remove only the `context` object when it is no longer wanted; do not
|
|
185
|
+
delete a shared `.persona/harness.jsonc` that contains other Persona Harness
|
|
186
|
+
configuration. To roll back a tracked change, review local edits and restore
|
|
187
|
+
the previous tracked configuration through your normal version-control flow.
|
|
188
|
+
|
|
189
|
+
These lifecycle actions do not enable `features.runtimeInjection`, and they do
|
|
190
|
+
not create workflow, evidence, or authority state or use network or GitHub.
|
|
191
|
+
|
|
151
192
|
With Context enabled, the OpenCode adapter accepts only a safe observed
|
|
152
193
|
project-relative target from a read or edit tool. It resolves the local
|
|
153
194
|
envelope, rejects invalid/unsafe/budget-exceeding input without delivery, and
|
|
@@ -52,6 +52,10 @@ export type ProductDeepInterviewResult = {
|
|
|
52
52
|
readonly kind: "recommendation";
|
|
53
53
|
readonly topic: ProductInterviewTopic;
|
|
54
54
|
readonly block: string;
|
|
55
|
+
} | {
|
|
56
|
+
readonly kind: "clarification-required";
|
|
57
|
+
readonly topic: ProductInterviewTopic;
|
|
58
|
+
readonly block: string;
|
|
55
59
|
} | {
|
|
56
60
|
readonly kind: "approval-required";
|
|
57
61
|
readonly block: string;
|
|
@@ -67,6 +71,7 @@ export declare function isProductDeepInterviewStart(message: string): boolean;
|
|
|
67
71
|
export declare class ProductDeepInterviewTracker {
|
|
68
72
|
private readonly options;
|
|
69
73
|
private readonly sessions;
|
|
74
|
+
private readonly suppressedSessions;
|
|
70
75
|
constructor(options?: ProductDeepInterviewOptions);
|
|
71
76
|
hasActiveSession(sessionId: string): boolean;
|
|
72
77
|
route(sessionId: string, message: string): ProductDeepInterviewResult | undefined;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createOpenCodeSkillRoute } from "./opencode-skill-adapter.js";
|
|
2
|
+
import { isExplicitProductInterviewRequest, isProductInterviewApproval, isProductInterviewClarification, isProductInterviewStop, } from "./product-interview-control.js";
|
|
2
3
|
const TOPICS = [
|
|
3
4
|
{
|
|
4
5
|
id: "target-user",
|
|
@@ -50,10 +51,9 @@ const TOPICS = [
|
|
|
50
51
|
},
|
|
51
52
|
];
|
|
52
53
|
const START_PATTERN = /(만들래|만들고\s*싶|기획해|구상해|서비스\s*만들|웹\s*서비스|기존\s*(?:서비스|제품|앱|흐름).*(?:개선|변경)|product\s+idea|want\s+to\s+(?:build|create|make|explore)|(?:build|create|make)\s+(?:an?|the)\s+(?:app|service|product)|new\s+(?:app|service|product)|(?:app|service|product)\s+idea|(?:improve|change)\s+(?:an?\s+)?existing(?:\s+\w+){0,2}\s+(?:app|service|product|flow))/iu;
|
|
53
|
-
const APPROVAL_PATTERN = /^(?:승인|진행하자|시작하자|approve|proceed|go\s+ahead)$/iu;
|
|
54
|
-
const STOP_PATTERN = /^(?:stop|pause|그만|중단)$/iu;
|
|
55
54
|
const DEFER_PATTERN = /^(?:defer|skip|later|보류|넘겨)$/iu;
|
|
56
55
|
const RECOMMEND_PATTERN = /^(?:recommend|recommendation|추천)$/iu;
|
|
56
|
+
const STOPPED_BLOCK = "[Persona Harness Product Interview]\nProduct discovery is paused.\nNo project, workflow, issue, agent, or file state was changed.";
|
|
57
57
|
export function isProductDeepInterviewStart(message) {
|
|
58
58
|
return START_PATTERN.test(message.trim());
|
|
59
59
|
}
|
|
@@ -120,6 +120,25 @@ function renderRecommendation(session) {
|
|
|
120
120
|
].join("\n"),
|
|
121
121
|
};
|
|
122
122
|
}
|
|
123
|
+
function renderClarificationRequired(session) {
|
|
124
|
+
const topic = topicAt(session.topicIndex);
|
|
125
|
+
if (topic === undefined) {
|
|
126
|
+
return renderApprovalRequired(session);
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
kind: "clarification-required",
|
|
130
|
+
topic: topic.id,
|
|
131
|
+
block: [
|
|
132
|
+
"[Persona Harness Product Interview]",
|
|
133
|
+
`Current topic: ${topic.id}`,
|
|
134
|
+
"The user's latest message is a clarification request, not a product decision.",
|
|
135
|
+
"Explain only the current question in plain language, then wait for the user's reply.",
|
|
136
|
+
"Do not record an answer, advance to another topic, or ask a neighbouring question.",
|
|
137
|
+
`Question to explain: ${topic.question}`,
|
|
138
|
+
"No project, workflow, issue, agent, or file state was changed.",
|
|
139
|
+
].join("\n"),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
123
142
|
function briefAnswer(session, topic) {
|
|
124
143
|
return session.answers.get(topic) ?? "deferred";
|
|
125
144
|
}
|
|
@@ -146,6 +165,7 @@ function startSession(mode) {
|
|
|
146
165
|
export class ProductDeepInterviewTracker {
|
|
147
166
|
options;
|
|
148
167
|
sessions = new Map();
|
|
168
|
+
suppressedSessions = new Set();
|
|
149
169
|
constructor(options = {}) {
|
|
150
170
|
this.options = options;
|
|
151
171
|
}
|
|
@@ -159,28 +179,33 @@ export class ProductDeepInterviewTracker {
|
|
|
159
179
|
}
|
|
160
180
|
const current = this.sessions.get(sessionId);
|
|
161
181
|
if (current === undefined) {
|
|
182
|
+
if (this.suppressedSessions.has(sessionId)) {
|
|
183
|
+
if (!isExplicitProductInterviewRequest(normalized)) {
|
|
184
|
+
return undefined;
|
|
185
|
+
}
|
|
186
|
+
this.suppressedSessions.delete(sessionId);
|
|
187
|
+
}
|
|
162
188
|
if (!isProductDeepInterviewStart(normalized)) {
|
|
163
|
-
|
|
189
|
+
if (!isExplicitProductInterviewRequest(normalized)) {
|
|
190
|
+
return undefined;
|
|
191
|
+
}
|
|
164
192
|
}
|
|
165
193
|
const started = startSession(this.options.mode ?? "new-product");
|
|
166
194
|
this.sessions.set(sessionId, started);
|
|
167
195
|
return renderQuestion(started);
|
|
168
196
|
}
|
|
169
|
-
if (
|
|
197
|
+
if (isProductInterviewStop(normalized)) {
|
|
170
198
|
this.sessions.delete(sessionId);
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
block: [
|
|
174
|
-
"[Persona Harness Product Interview]",
|
|
175
|
-
"Product discovery is paused.",
|
|
176
|
-
"No project, workflow, issue, agent, or file state was changed.",
|
|
177
|
-
].join("\n"),
|
|
178
|
-
};
|
|
199
|
+
this.suppressedSessions.add(sessionId);
|
|
200
|
+
return { kind: "stopped", block: STOPPED_BLOCK };
|
|
179
201
|
}
|
|
180
202
|
if (RECOMMEND_PATTERN.test(normalized)) {
|
|
181
203
|
return renderRecommendation(current);
|
|
182
204
|
}
|
|
183
|
-
if (
|
|
205
|
+
if (isProductInterviewClarification(normalized)) {
|
|
206
|
+
return renderClarificationRequired(current);
|
|
207
|
+
}
|
|
208
|
+
if (isProductInterviewApproval(normalized)) {
|
|
184
209
|
if (current.topicIndex < TOPICS.length) {
|
|
185
210
|
return renderQuestion(current, true);
|
|
186
211
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-deep-interview.js","sourceRoot":"","sources":["../../src/runtime/product-deep-interview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"product-deep-interview.js","sourceRoot":"","sources":["../../src/runtime/product-deep-interview.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function isProductInterviewApproval(message: string): boolean;
|
|
2
|
+
export declare function isProductInterviewClarification(message: string): boolean;
|
|
3
|
+
export declare function isExplicitProductInterviewRequest(message: string): boolean;
|
|
4
|
+
export declare function isProductInterviewStop(message: string): boolean;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { isProductDiscoverySuppressed, parseExplicitPersonaSkillCommand, } from "./persona-shared-skill-activation.js";
|
|
2
|
+
const APPROVAL_PATTERN = /^(?:승인|진행하자|시작하자|approve|proceed|go\s+ahead)$/iu;
|
|
3
|
+
const STOP_PATTERN = /^(?:stop|pause|그만|중단)$/iu;
|
|
4
|
+
const NATURAL_STOP_PATTERN = /(?:(?:do\s+not|don't|stop|skip)\s+(?:the\s+)?(?:product\s+)?(?:discovery|interview|questions?)|(?:(?:product\s+)?(?:discovery|interview|questions?))\s+(?:is\s+)?(?:not\s+(?:needed|now)|stop|skip)|(?:제품|프로덕트)?\s*(?:탐색|인터뷰|질문)\s*(?:를|을|은|는)?\s*(?:하지\s*마(?:요|세요)?|말아(?:줘|주세요)?|그만(?:해|하자|해줘|해주세요)?|중단(?:해|하자|해줘|해주세요)?|필요\s*없(?:어|어요|습니다)?))/iu;
|
|
5
|
+
const NON_PRODUCT_TASK_SWITCH_PATTERN = /(?:feedback[-\s]?dogfooding|dogfooding|workflow\s+finish(?:\s+implement)?|source-read-runtime-unavailable|history\s+archive|(?:피드백|이슈)\s*(?:로|을|를|에)?\s*(?:기록|남기|등록|정리)|(?:워크플로|workflow)\s*(?:finish|진단|오류)|(?:구현|리뷰)\s*보고서)/iu;
|
|
6
|
+
const CLARIFICATION_PATTERN = /(?:무슨\s*말|뭔\s*말|이해(?:가)?\s*안|모르겠|설명(?:해|해줘|해주세요|좀)|쉽게\s*(?:말|설명)|what\s+(?:does|do)\b.*\bmean|(?:i\s+)?(?:do\s+not|don't)\s+understand|(?:can|could)\s+you\s+explain|please\s+explain)/iu;
|
|
7
|
+
function isEditDistanceAtMostOne(value, expected) {
|
|
8
|
+
if (value === expected) {
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
if (Math.abs(value.length - expected.length) > 1) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
let valueIndex = 0;
|
|
15
|
+
let expectedIndex = 0;
|
|
16
|
+
let edits = 0;
|
|
17
|
+
while (valueIndex < value.length && expectedIndex < expected.length) {
|
|
18
|
+
if (value[valueIndex] === expected[expectedIndex]) {
|
|
19
|
+
valueIndex += 1;
|
|
20
|
+
expectedIndex += 1;
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
edits += 1;
|
|
24
|
+
if (edits > 1) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
if (value.length > expected.length) {
|
|
28
|
+
valueIndex += 1;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (value.length < expected.length) {
|
|
32
|
+
expectedIndex += 1;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
valueIndex += 1;
|
|
36
|
+
expectedIndex += 1;
|
|
37
|
+
}
|
|
38
|
+
return edits + (value.length - valueIndex) + (expected.length - expectedIndex) <= 1;
|
|
39
|
+
}
|
|
40
|
+
export function isProductInterviewApproval(message) {
|
|
41
|
+
return APPROVAL_PATTERN.test(message)
|
|
42
|
+
|| (/^[a-z]+$/iu.test(message) && isEditDistanceAtMostOne(message.toLowerCase(), "approve"));
|
|
43
|
+
}
|
|
44
|
+
export function isProductInterviewClarification(message) {
|
|
45
|
+
return CLARIFICATION_PATTERN.test(message);
|
|
46
|
+
}
|
|
47
|
+
export function isExplicitProductInterviewRequest(message) {
|
|
48
|
+
const command = parseExplicitPersonaSkillCommand(message);
|
|
49
|
+
return command.kind === "valid" && command.skillId === "deep-interview";
|
|
50
|
+
}
|
|
51
|
+
export function isProductInterviewStop(message) {
|
|
52
|
+
return STOP_PATTERN.test(message)
|
|
53
|
+
|| NATURAL_STOP_PATTERN.test(message)
|
|
54
|
+
|| isProductDiscoverySuppressed(message)
|
|
55
|
+
|| NON_PRODUCT_TASK_SWITCH_PATTERN.test(message);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=product-interview-control.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"product-interview-control.js","sourceRoot":"","sources":["../../src/runtime/product-interview-control.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,gCAAgC,GACjC,MAAM,sCAAsC,CAAA;AAE7C,MAAM,gBAAgB,GAAG,iDAAiD,CAAA;AAC1E,MAAM,YAAY,GAAG,0BAA0B,CAAA;AAC/C,MAAM,oBAAoB,GAAG,mVAAmV,CAAA;AAChX,MAAM,+BAA+B,GAAG,iOAAiO,CAAA;AACzQ,MAAM,qBAAqB,GAAG,0LAA0L,CAAA;AAExN,SAAS,uBAAuB,CAAC,KAAa,EAAE,QAAgB;IAC9D,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvB,OAAO,IAAI,CAAA;IACb,CAAC;IACD,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QACjD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,UAAU,GAAG,CAAC,CAAA;IAClB,IAAI,aAAa,GAAG,CAAC,CAAA;IACrB,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,OAAO,UAAU,GAAG,KAAK,CAAC,MAAM,IAAI,aAAa,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpE,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YAClD,UAAU,IAAI,CAAC,CAAA;YACf,aAAa,IAAI,CAAC,CAAA;YAClB,SAAQ;QACV,CAAC;QACD,KAAK,IAAI,CAAC,CAAA;QACV,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,OAAO,KAAK,CAAA;QACd,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;YACnC,UAAU,IAAI,CAAC,CAAA;YACf,SAAQ;QACV,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;YACnC,aAAa,IAAI,CAAC,CAAA;YAClB,SAAQ;QACV,CAAC;QACD,UAAU,IAAI,CAAC,CAAA;QACf,aAAa,IAAI,CAAC,CAAA;IACpB,CAAC;IAED,OAAO,KAAK,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAA;AACrF,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,OAAe;IACxD,OAAO,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC;WAChC,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,uBAAuB,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,SAAS,CAAC,CAAC,CAAA;AAChG,CAAC;AAED,MAAM,UAAU,+BAA+B,CAAC,OAAe;IAC7D,OAAO,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;AAC5C,CAAC;AAED,MAAM,UAAU,iCAAiC,CAAC,OAAe;IAC/D,MAAM,OAAO,GAAG,gCAAgC,CAAC,OAAO,CAAC,CAAA;IACzD,OAAO,OAAO,CAAC,IAAI,KAAK,OAAO,IAAI,OAAO,CAAC,OAAO,KAAK,gBAAgB,CAAA;AACzE,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,OAAe;IACpD,OAAO,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC;WAC5B,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC;WAClC,4BAA4B,CAAC,OAAO,CAAC;WACrC,+BAA+B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;AACpD,CAAC"}
|
|
@@ -6,8 +6,11 @@ Last reconciled: 2026-08-30
|
|
|
6
6
|
P0 integration release: `a82b85ddef7e9fd9518348bff16deb38f53b4676`
|
|
7
7
|
P0 integration package: [`persona-harness@0.8.37`](https://www.npmjs.com/package/persona-harness/v/0.8.37)
|
|
8
8
|
P0 integration lineage: [#442](https://github.com/jyt6640/persona-harness/issues/442) delivered through [#443](https://github.com/jyt6640/persona-harness/pull/443)
|
|
9
|
-
|
|
9
|
+
Prior program-status publication: [`persona-harness@0.8.38`](https://www.npmjs.com/package/persona-harness/v/0.8.38)
|
|
10
10
|
Program-status publication lineage: [#444](https://github.com/jyt6640/persona-harness/issues/444) reconciled through [#445](https://github.com/jyt6640/persona-harness/pull/445) and published by [#446](https://github.com/jyt6640/persona-harness/issues/446)
|
|
11
|
+
Current structural-observability release: [`persona-harness@0.8.39`](https://www.npmjs.com/package/persona-harness/v/0.8.39)
|
|
12
|
+
Structural-observability lineage: [#449](https://github.com/jyt6640/persona-harness/issues/449) delivered through [#450](https://github.com/jyt6640/persona-harness/pull/450) on `ec3680bcceccf582521952dc77bf3cc9fb7cd874`
|
|
13
|
+
Current lifecycle documentation merge: [#451](https://github.com/jyt6640/persona-harness/issues/451) delivered through [#452](https://github.com/jyt6640/persona-harness/pull/452) on `881be07b3e3baa443a66126ca94008499082b732`
|
|
11
14
|
P0 implementation release baseline: `9b80a45070be10659150095cf701a6f375bc6600`
|
|
12
15
|
P0 implementation package: [`persona-harness@0.8.33`](https://www.npmjs.com/package/persona-harness/v/0.8.33)
|
|
13
16
|
P0 implementation lineage: [#414](https://github.com/jyt6640/persona-harness/issues/414) delivered through [#437](https://github.com/jyt6640/persona-harness/pull/437)
|
|
@@ -22,7 +25,7 @@ Current compatibility package: [`persona-harness@0.8.36`](https://www.npmjs.com/
|
|
|
22
25
|
Current compatibility lineage: [#412](https://github.com/jyt6640/persona-harness/issues/412) delivered through [#441](https://github.com/jyt6640/persona-harness/pull/441)
|
|
23
26
|
Historical pre-integration audit source: `f677a635040ad55d8b7d25abab280c5703a153ea`
|
|
24
27
|
Program issue: [#389](https://github.com/jyt6640/persona-harness/issues/389)
|
|
25
|
-
Remaining bounded work: the terminal, non-retryable hosted-observation record in [#410](https://github.com/jyt6640/persona-harness/issues/410)
|
|
28
|
+
Remaining bounded work: the terminal, non-retryable hosted-observation record in [#410](https://github.com/jyt6640/persona-harness/issues/410) and the not-started independent-value protocol from [#429](https://github.com/jyt6640/persona-harness/issues/429), whose real preregistered participant route is [#317](https://github.com/jyt6640/persona-harness/issues/317). [#449](https://github.com/jyt6640/persona-harness/issues/449) is a delivered metadata-only structural observer boundary; it does not replay #410, begin a host action, or establish product value. The deterministic local P0 boundaries integrated by #443 are closed.
|
|
26
29
|
|
|
27
30
|
## Purpose
|
|
28
31
|
|
|
@@ -170,17 +173,19 @@ evidence rather than a description of current protected main.
|
|
|
170
173
|
evidence do not establish Context delivery or independent user value. #410
|
|
171
174
|
ran its one authorized real OpenCode session, but its privacy-preserving
|
|
172
175
|
observation could not classify delivery; the #429 status intentionally has
|
|
173
|
-
no independent-user observations.
|
|
176
|
+
no independent-user observations. The real preregistered independent
|
|
177
|
+
participant boundary remains #317.
|
|
174
178
|
- **Hosted-observation verdict: `hosted-unavailable`.** The #410 one-shot
|
|
175
179
|
completed its safe read and same-session checks, then retained only a
|
|
176
180
|
sanitized OpenCode export. OpenCode `v1.17.16` redacts every text part in
|
|
177
181
|
`export --sanitize`, so the absence of a Context marker in that export does
|
|
178
182
|
not prove that the transform did not inject one. The run is terminal and
|
|
179
183
|
cannot be retried as a debugger.
|
|
180
|
-
- **Next allowed step:** no Context host action starts automatically. #449
|
|
181
|
-
|
|
182
|
-
observation still needs its own explicit Delivery Control
|
|
183
|
-
semantically new consumer/session. It cannot reuse or replay
|
|
184
|
+
- **Next allowed step:** no Context host action starts automatically. #449 is
|
|
185
|
+
delivered as a metadata-only structural observer boundary in `v0.8.39`, but
|
|
186
|
+
any future observation still needs its own explicit Delivery Control
|
|
187
|
+
predicate and a semantically new consumer/session. It cannot reuse or replay
|
|
188
|
+
#410.
|
|
184
189
|
|
|
185
190
|
## Current Delivery Order
|
|
186
191
|
|
|
@@ -205,13 +210,23 @@ evidence rather than a description of current protected main.
|
|
|
205
210
|
as stable `v0.8.37` on
|
|
206
211
|
`a82b85ddef7e9fd9518348bff16deb38f53b4676`. The release does not create
|
|
207
212
|
host-delivery or product-value evidence.
|
|
208
|
-
7. **
|
|
213
|
+
7. **Metadata-only structural-observability release:** #449 delivered through
|
|
214
|
+
#450 as stable `v0.8.39` on
|
|
215
|
+
`ec3680bcceccf582521952dc77bf3cc9fb7cd874`. It makes a separate synthetic
|
|
216
|
+
Context input part observable in sanitized OpenCode exports, but it does
|
|
217
|
+
not run a host observation or establish Context delivery or product value.
|
|
218
|
+
8. **Explicit lifecycle documentation:** #451 delivered through #452 on
|
|
219
|
+
`881be07b3e3baa443a66126ca94008499082b732`. The guide documents inspection,
|
|
220
|
+
fresh-safe enablement, manual merge for an existing configuration,
|
|
221
|
+
disablement, Context-only removal, and VCS rollback without changing CLI or
|
|
222
|
+
runtime behavior.
|
|
223
|
+
9. **Remaining independent evidence:** #410's named predicate ran once on a
|
|
209
224
|
released `0.8.33` consumer and reached terminal `hosted-unavailable`.
|
|
210
225
|
Because the retained OpenCode `v1.17.16` `export --sanitize` result redacts
|
|
211
226
|
every text part, its marker count is not a delivery verdict; #410 cannot be
|
|
212
227
|
retried. #429 owns the preregistered external-validation schema; its current
|
|
213
|
-
empty status remains `INCONCLUSIVE` until
|
|
214
|
-
|
|
228
|
+
empty status remains `INCONCLUSIVE` until real preregistered participants
|
|
229
|
+
begin the separate #317 protocol.
|
|
215
230
|
|
|
216
231
|
Only one public command, schema, resolver, adapter, CI, script, or documentation
|
|
217
232
|
boundary is changed per child issue. A child issue closes only when its stated
|
|
@@ -74,6 +74,21 @@ recommendation plus its tradeoff. A user may answer, request a recommendation,
|
|
|
74
74
|
defer, or stop. After the facts are complete, it renders a brief and requires
|
|
75
75
|
an explicit `approve` before technical intake.
|
|
76
76
|
|
|
77
|
+
While an interview is active, a natural-language request not to interview, a
|
|
78
|
+
whole-task discovery defer, or a workflow feedback/dogfooding task switch ends
|
|
79
|
+
that interview before the message can become an answer. The session remains
|
|
80
|
+
suppressed until the user explicitly sends `/persona deep-interview`; another
|
|
81
|
+
ambiguous product request does not restart it. A bare `defer` remains a
|
|
82
|
+
per-topic answer. A clarification request holds the current topic and asks the
|
|
83
|
+
host to explain only that question in plain language. At the final approval
|
|
84
|
+
boundary only, an English token within one edit of `approve` is accepted once;
|
|
85
|
+
it cannot advance an unresolved topic.
|
|
86
|
+
|
|
87
|
+
The compact `[Persona Harness Skill Route]` marker is emitted only when
|
|
88
|
+
`deep-interview` is actually selected. A stop or clarification carries the
|
|
89
|
+
`[Persona Harness Product Interview]` control marker but is not a new skill
|
|
90
|
+
activation or a claim that the complete skill body ran.
|
|
91
|
+
|
|
77
92
|
Before that approval, the route creates no plan, ticket, workflow state,
|
|
78
93
|
branch, issue, file, or agent. For a brownfield change, read the relevant
|
|
79
94
|
existing code first and ask only product intent the code cannot establish.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# v0.8.40 Release Notes
|
|
2
|
+
|
|
3
|
+
## Deep Interview Controls That Respect The Current Task
|
|
4
|
+
|
|
5
|
+
This release makes the product deep-interview route less disruptive when a
|
|
6
|
+
developer is already doing bounded work or gives direct feedback.
|
|
7
|
+
|
|
8
|
+
- Direct feedback, diagnostics, report requests, explicit commands, and
|
|
9
|
+
bounded implementation requests stay outside product-discovery capture.
|
|
10
|
+
- A natural-language stop, whole-task defer, or feedback/dogfooding task
|
|
11
|
+
switch ends an active interview and suppresses automatic follow-up prompts.
|
|
12
|
+
- Only an explicit `/persona deep-interview` request starts a new interview
|
|
13
|
+
after that suppression.
|
|
14
|
+
- An explanation request holds the current unresolved question instead of
|
|
15
|
+
treating it as an answer or advancing to a neighbouring topic.
|
|
16
|
+
- A one-character English typo of `approve` is accepted only at the terminal
|
|
17
|
+
approval boundary; earlier answers remain non-terminal.
|
|
18
|
+
- The shared-skill and router documentation distinguishes a visible interview
|
|
19
|
+
control marker from an actual shared-skill activation.
|
|
20
|
+
|
|
21
|
+
## Safety And Scope Boundaries
|
|
22
|
+
|
|
23
|
+
- Context remains explicit opt-in and default-off; this release does not alter
|
|
24
|
+
the runtime injection default.
|
|
25
|
+
- The interaction controls do not infer workflow, shell/process execution,
|
|
26
|
+
network, GitHub, evidence, authority, credential, external-observation, or
|
|
27
|
+
issue-creation actions.
|
|
28
|
+
- This release does not claim a real host-session result, independent 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 release path verifies the focused deep-interview tracker and hook
|
|
36
|
+
regressions, type safety, documentation and release-policy checks, a fresh
|
|
37
|
+
isolated tarball installation, protected CI, canonical package identity, and
|
|
38
|
+
registry provenance.
|
package/package.json
CHANGED