test(explore): guard the capture branch against a re-added confirmation gate

Also disambiguate the scope fence in the IMPORTANT block: "the artifacts
that request names" parses as a relative clause, and it is the sentence an
agent weighs first. Match the article used by both restatements.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Clay Good
2026-09-10 11:50:42 -05:00
co-authored by Claude Opus 5
parent 6d975f8d74
commit 55eeac6145
4 changed files with 16 additions and 7 deletions
+1 -1
View File
@@ -11,7 +11,7 @@ metadata:
Enter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes.
**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, investigate the codebase, and run read-only commands or tools without confirmation, but you must NEVER write code or implement features. If the user asks you to implement something, remind them to exit explore mode first and create a change proposal. You MAY create or update OpenSpec change artifacts (proposals, designs, specs) within a confirmed scope—that's capturing thinking, not implementing. Answering design or clarifying questions is never consent to write. Before the first write-capable action, name the artifacts or files you would change and what you would do, ask a direct yes/no question, and wait for the user's confirmation in a separate message. Confirmation covers only the scope you described; ask again before expanding it. An explicit request to capture the exploration as a new change is itself that confirmation, covering the change and the artifacts that request names; scaffold it first as described below.
**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, investigate the codebase, and run read-only commands or tools without confirmation, but you must NEVER write code or implement features. If the user asks you to implement something, remind them to exit explore mode first and create a change proposal. You MAY create or update OpenSpec change artifacts (proposals, designs, specs) within a confirmed scope—that's capturing thinking, not implementing. Answering design or clarifying questions is never consent to write. Before the first write-capable action, name the artifacts or files you would change and what you would do, ask a direct yes/no question, and wait for the user's confirmation in a separate message. Confirmation covers only the scope you described; ask again before expanding it. An explicit request to capture the exploration as a new change is itself that confirmation, covering the change and the artifacts the request names; scaffold it first as described below.
**This is a stance, not a workflow.** There are no fixed steps, no required sequence, no mandatory outputs. You're a thinking partner helping the user explore.
+2 -2
View File
@@ -35,7 +35,7 @@ export function getExploreSkillTemplate(): SkillTemplate {
description: 'Enter explore mode - a thinking partner for exploring ideas, investigating problems, and clarifying requirements. Use when the user wants to think through something before or during a change.',
instructions: `Enter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes.
**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, investigate the codebase, and run read-only commands or tools without confirmation, but you must NEVER write code or implement features. If the user asks you to implement something, remind them to exit explore mode first and create a change proposal. You MAY create or update OpenSpec change artifacts (proposals, designs, specs) within a confirmed scope—that's capturing thinking, not implementing. Answering design or clarifying questions is never consent to write. Before the first write-capable action, name the artifacts or files you would change and what you would do, ask a direct yes/no question, and wait for the user's confirmation in a separate message. Confirmation covers only the scope you described; ask again before expanding it. An explicit request to capture the exploration as a new change is itself that confirmation, covering the change and the artifacts that request names; scaffold it first as described below.
**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, investigate the codebase, and run read-only commands or tools without confirmation, but you must NEVER write code or implement features. If the user asks you to implement something, remind them to exit explore mode first and create a change proposal. You MAY create or update OpenSpec change artifacts (proposals, designs, specs) within a confirmed scope—that's capturing thinking, not implementing. Answering design or clarifying questions is never consent to write. Before the first write-capable action, name the artifacts or files you would change and what you would do, ask a direct yes/no question, and wait for the user's confirmation in a separate message. Confirmation covers only the scope you described; ask again before expanding it. An explicit request to capture the exploration as a new change is itself that confirmation, covering the change and the artifacts the request names; scaffold it first as described below.
**This is a stance, not a workflow.** There are no fixed steps, no required sequence, no mandatory outputs. You're a thinking partner helping the user explore.
@@ -358,7 +358,7 @@ export function getOpsxExploreCommandTemplate(): CommandTemplate {
tags: ['workflow', 'explore', 'experimental', 'thinking'],
content: `Enter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes.
**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, investigate the codebase, and run read-only commands or tools without confirmation, but you must NEVER write code or implement features. If the user asks you to implement something, remind them to exit explore mode first and create a change proposal. You MAY create or update OpenSpec change artifacts (proposals, designs, specs) within a confirmed scope—that's capturing thinking, not implementing. Answering design or clarifying questions is never consent to write. Before the first write-capable action, name the artifacts or files you would change and what you would do, ask a direct yes/no question, and wait for the user's confirmation in a separate message. Confirmation covers only the scope you described; ask again before expanding it. An explicit request to capture the exploration as a new change is itself that confirmation, covering the change and the artifacts that request names; scaffold it first as described below.
**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, investigate the codebase, and run read-only commands or tools without confirmation, but you must NEVER write code or implement features. If the user asks you to implement something, remind them to exit explore mode first and create a change proposal. You MAY create or update OpenSpec change artifacts (proposals, designs, specs) within a confirmed scope—that's capturing thinking, not implementing. Answering design or clarifying questions is never consent to write. Before the first write-capable action, name the artifacts or files you would change and what you would do, ask a direct yes/no question, and wait for the user's confirmation in a separate message. Confirmation covers only the scope you described; ask again before expanding it. An explicit request to capture the exploration as a new change is itself that confirmation, covering the change and the artifacts the request names; scaffold it first as described below.
**This is a stance, not a workflow.** There are no fixed steps, no required sequence, no mandatory outputs. You're a thinking partner helping the user explore.
+10 -1
View File
@@ -202,7 +202,7 @@ describe('explore templates', () => {
it('treats an explicit capture request as the write confirmation (#1828)', () => {
for (const [label, body] of bodies) {
expect(body, label).toContain(
'An explicit request to capture the exploration as a new change is itself that confirmation, covering the change and the artifacts that request names'
'An explicit request to capture the exploration as a new change is itself that confirmation, covering the change and the artifacts the request names'
);
}
});
@@ -249,6 +249,15 @@ describe('explore templates', () => {
for (const [label, body] of bodies) {
const transition = newChangeTransition(body, label);
// String containment alone cannot catch #1828's actual failure mode: a
// second, contradictory instruction added elsewhere. The capture branch
// is resolved only while it carries no confirmation gate of its own.
expect(transition, label).not.toContain('ask a direct yes/no question');
expect(transition, label).not.toContain(
"wait for the user's confirmation"
);
expect(transition, label).not.toContain('wait for explicit confirmation');
expect(body, label).toContain(
'Confirmation covers only the scope you described; ask again before expanding it'
);
@@ -38,14 +38,14 @@ import {
import { STORE_SELECTION_GUIDANCE } from '../../../src/core/templates/workflows/store-selection.js';
const EXPECTED_FUNCTION_HASHES: Record<string, string> = {
getExploreSkillTemplate: '880d6417dd7223a374d0569f0335abec87bea109f6d4805829dd8dbb643507d3',
getExploreSkillTemplate: 'ecc0a0dbc55e8e5058529622302bda0f26058377e149a8f370b854d79f586a61',
getNewChangeSkillTemplate: 'eabd1e895c5881dcb17dcbaa3fb26098dd59e8eacb318e400820b4dc811ef781',
getContinueChangeSkillTemplate: '012136f6411a99c8fa228e2f9444cb64b0a89e0f56fdeac2fe03b2f5bee0c5d7',
getApplyChangeSkillTemplate: 'd1e7d5ceb85193c0964057dbb88e9651526754bd33f84020e2440ff0621d5dbb',
getFfChangeSkillTemplate: 'efa6a70c111b18b61a7720250b9622afa9a212fb64edf609cf80e2182a9bdf8c',
getSyncSpecsSkillTemplate: 'b099e2ff31859c9b10d928066e662524f9aad9ecf2be12fceacb732d718c4146',
getOnboardSkillTemplate: '3a836faae463d88c289a1c129cb7ee556a563b7e53e1a52a4711ff152a3b51f7',
getOpsxExploreCommandTemplate: 'dd3062f557ad34f169bd2ed17113f539e827bf90c51b290311c21af66a255dc2',
getOpsxExploreCommandTemplate: '519ea6a8d6801d0f7d54595ce548a9bb3e776066bbf718895b4225658dee78f0',
getOpsxNewCommandTemplate: 'f2d30e569798a4c92ba932859d6ba4e0ad10e18feccbade1cfee0957597b3463',
getOpsxContinueCommandTemplate: 'e50e50266efa1b8e64ff9b6274ee8254f0a240d6adc1b862d126e2f1c9d3a559',
getOpsxApplyCommandTemplate: 'e3579ac78f2e2c75fa3d3a7ac7dc3e49c395e96f7323398f0f041d94f8de9bb0',
@@ -66,7 +66,7 @@ const EXPECTED_FUNCTION_HASHES: Record<string, string> = {
};
const EXPECTED_GENERATED_SKILL_CONTENT_HASHES: Record<string, string> = {
'openspec-explore': '17969500e9c81580c1397bebc7592f7d695c737d8ed73610321f25843ca98744',
'openspec-explore': '974cd6c923d1ceaa50fb7d335a0373979d8c5c06d58a29dede6c48bda59327fc',
'openspec-new-change': 'ec4529beef978e34634a6f7286fab55d68fad8fb374dceb45691d52caab33fbb',
'openspec-continue-change': 'bb6194a16c54891cdb253678e8f70ce53b2af86735243980f366ce551d37e42e',
'openspec-apply-change': '81ea96d9fa6ec8536cd23c1fe561ed28e1cc1cad0a8ceb700588e08974cc0e49',