@onefl666/dsh-great-plan 0.5.0 → 0.6.0

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.
@@ -1,252 +0,0 @@
1
- /**
2
- * Evidence-first plan handoff prompt section.
3
- *
4
- * Plan mode already renders the deployment's native `plan:policy` guidance.
5
- * This plugin adds one independent section immediately after it, asking the
6
- * planner to hand over its investigation together with the plan. It also carries
7
- * an optional unlimited-token-budget reminder and a brainstorming paragraph,
8
- * each independently switchable from the Settings page. The native policy text
9
- * is never replaced or duplicated.
10
- */
11
-
12
- /** Prompt section name; unique in the global prompt layer. */
13
- export const PLAN_EVIDENCE_SECTION = 'great-plan:plan-evidence';
14
-
15
- /** Used when the instance cannot resolve the centrally owned PLAN_POLICY order. */
16
- export const PLAN_EVIDENCE_ORDER_FALLBACK = 501;
17
-
18
- /** Model-facing guidance for collaborative brainstorming; the Settings page can switch it off. */
19
- export const PLAN_BRAINSTORMING_GUIDANCE = `Collaborative discovery and evidence-first plan handoff:
20
- Before proposing a plan, assess the user's goal, why it matters, success criteria, constraints, current state, and available resources. Do not mechanically ask a checklist.
21
- When an unknown answer could materially change the scope or approach, ask one concise, open-ended question per turn and wait for its answer before finalizing. If the request is clear or the user explicitly delegates the choice, proceed without needless questions.
22
- Explore proactively and think deeply from multiple aspects. You are the Team Lead: use \`spawn_teammate\` to create at least two exploration teammates in parallel, each with one distinct, concrete scope, and require concise, evidence-backed findings with file paths and line ranges. Do not investigate those scopes yourself while teammates work; collect every result and resolve conflicts yourself. Then create one separate planning teammate to draft a candidate final plan from the consolidated evidence. Verify the evidence and the candidate plan yourself, resolve disagreements, and submit the synthesized plan through the native review flow. If teammate creation is unavailable or fails, say so in the plan and continue alone; never invent subagent work.
23
- Consider multiple plausible approaches; present alternatives and tradeoffs only when they help the user decide. State the recommendation's key reason and distinguish user-stated requirements from your recommendations, assumptions, and unverified points. Give a concise rationale summary, not private step-by-step chain-of-thought. Do not imply the user approved a proposal they have not approved. Once material uncertainties are resolved, deliver a plan through the native review flow; this guidance does not authorize execution.`;
24
-
25
- /** Model-facing unlimited-token-budget reminder; the Settings page can switch it off. */
26
- export const PLAN_UNLIMITED_BUDGET_GUIDANCE = `Token budget: unlimited. Remember: we are DeepSeek, your usage is unlimited, and I am stress-testing you at the limit. Do not skimp on tokens — spend freely; you are very wealthy. Do not reduce investigation, tool calls, or necessary questions to save tokens; keep the final plan concise.`;
27
-
28
- /** Model-facing evidence and executor handoff guidance; always rendered in plan mode. */
29
- export const PLAN_HANDOFF_GUIDANCE = `Evidence-first plan handoff:
30
- The approved plan is the handoff to execution: "Start fresh and execute" sends only the plan, and "compact and execute" replaces older history with a summary. Make the plan self-contained enough that an executor does not repeat this investigation.
31
-
32
- Include:
33
- - Background: the request, current behavior, constraints, and explicit assumptions.
34
- - Evidence chain: the files, symbols, and line ranges inspected (for example, path/file.js:12-30); the searches and commands run with their key results; the docs, skills, or URLs consulted; and how conflicting evidence was resolved. Cite the evidence behind each design claim, and mark anything you did not verify as an assumption or open question.
35
- - Handoff: what is already established and must not be re-investigated, and which unknowns the executor should verify first.
36
-
37
- Never present a guess as fact, and never invent file paths, APIs, command output, or test results. Before presenting the plan, re-check that each citation is accurate. Keep the evidence compact: short headings and precise pointers, not raw logs or whole files.`;
38
-
39
- /** Default guidance (every switch on) appended while plan mode is active. */
40
- export const PLAN_EVIDENCE_GUIDANCE = `${PLAN_UNLIMITED_BUDGET_GUIDANCE}\n\n${PLAN_BRAINSTORMING_GUIDANCE}\n\n${PLAN_HANDOFF_GUIDANCE}`;
41
-
42
- /**
43
- * Compose the plan-mode guidance from its independently switchable parts.
44
- *
45
- * The budget reminder comes first as a general instruction, then the optional
46
- * brainstorming guidance, and the evidence/handoff guidance always closes the
47
- * section. Disabled parts are omitted entirely, never replaced by placeholders.
48
- * With every switch on the precomputed `PLAN_EVIDENCE_GUIDANCE` constant is
49
- * returned so the common path allocates nothing per prompt assembly.
50
- *
51
- * @param {object} [options]
52
- * @param {boolean} [options.brainstorming] whether the brainstorming paragraph is injected.
53
- * @param {boolean} [options.unlimitedBudget] whether the budget reminder is injected.
54
- * @returns {string} the assembled section text.
55
- */
56
- export function composePlanGuidance({ brainstorming = true, unlimitedBudget = true } = {}) {
57
- if (brainstorming !== false && unlimitedBudget !== false) return PLAN_EVIDENCE_GUIDANCE;
58
- const parts = [];
59
- if (unlimitedBudget !== false) parts.push(PLAN_UNLIMITED_BUDGET_GUIDANCE);
60
- if (brainstorming !== false) parts.push(PLAN_BRAINSTORMING_GUIDANCE);
61
- parts.push(PLAN_HANDOFF_GUIDANCE);
62
- return parts.join('\n\n');
63
- }
64
-
65
- /**
66
- * Read one switch from the plugin config.
67
- *
68
- * A volatile field arrives as a reference object; plain booleans are accepted
69
- * for tests and hand-written rows. Every missing, malformed, or unreadable
70
- * value keeps the fallback so prompt assembly never fails.
71
- *
72
- * @param {object | undefined} config the plugin config passed to `apply`.
73
- * @param {string} field the config field to read.
74
- * @param {boolean} fallback value used when the field is missing or unreadable.
75
- * @returns {boolean} the switch value.
76
- */
77
- function readConfigSwitch(config, field, fallback) {
78
- if (config === undefined || config === null || typeof config !== 'object') return fallback;
79
- let value;
80
- try {
81
- value = config[field];
82
- } catch {
83
- return fallback;
84
- }
85
- if (value === undefined || value === null) return fallback;
86
- if (typeof value === 'boolean') return value;
87
- if (typeof value.get === 'function') {
88
- try {
89
- const live = value.get();
90
- return typeof live === 'boolean' ? live : fallback;
91
- } catch {
92
- return fallback;
93
- }
94
- }
95
- return fallback;
96
- }
97
-
98
- /**
99
- * Read the brainstorming switch; defaults to enabled.
100
- *
101
- * @param {object | undefined} config the plugin config passed to `apply`.
102
- * @returns {boolean} whether the brainstorming guidance is injected.
103
- */
104
- export function readBrainstormingEnabled(config) {
105
- return readConfigSwitch(config, 'injectBrainstormingPrompt', true);
106
- }
107
-
108
- /**
109
- * Read the unlimited-token-budget switch; defaults to enabled.
110
- *
111
- * @param {object | undefined} config the plugin config passed to `apply`.
112
- * @returns {boolean} whether the budget reminder is injected.
113
- */
114
- export function readUnlimitedBudgetEnabled(config) {
115
- return readConfigSwitch(config, 'injectUnlimitedBudgetPrompt', true);
116
- }
117
-
118
- /**
119
- * Resolve the section text from the plan projection and both switches.
120
- *
121
- * Mirrors the native `plan:policy` gate: a pending selection wins over the
122
- * logged state, so both sections appear and disappear at the same step
123
- * boundary. Every missing or failing input returns empty text; prompt
124
- * assembly must never fail because plan state is unavailable.
125
- *
126
- * @param {object | undefined} planMode the Host plan projection service.
127
- * @param {object | undefined} agent the agent whose plan state is read.
128
- * @param {boolean} [brainstorming] whether the brainstorming paragraph is injected.
129
- * @param {boolean} [unlimitedBudget] whether the budget reminder is injected.
130
- * @returns {string} the section text, or empty when plan mode is inactive.
131
- */
132
- export function planEvidenceText(planMode, agent, brainstorming = true, unlimitedBudget = true) {
133
- if (agent === undefined || agent === null) return '';
134
- if (planMode === undefined || planMode === null || typeof planMode.get !== 'function') return '';
135
- let state;
136
- try {
137
- state = planMode.get(agent);
138
- } catch {
139
- return '';
140
- }
141
- if (state === undefined || state === null) return '';
142
- const active = state.pending === undefined ? state.active === true : state.pending === true;
143
- if (!active) return '';
144
- return composePlanGuidance({ brainstorming, unlimitedBudget });
145
- }
146
-
147
- /**
148
- * Decide whether plan mode is active for the step being assembled.
149
- *
150
- * The Host plane cannot rely on its own `planMode` instance: agent presets
151
- * commonly mount the plan-mode plugin in an isolated group, so the host-plane
152
- * instance does not see the state that the preset drives. The agent's own
153
- * scoped context (`agent.ctx`) carries the instance that owns the session's
154
- * plan state and the pending selection's direction — the same data source the
155
- * native `plan:policy` section reads. The host-plane instance is the fallback
156
- * for compositions where plan mode is host-owned, and the shared `plan`
157
- * session projection (the unit the compaction command also reads) is the final
158
- * synchronous fallback. Every source degrades to inactive instead of throwing.
159
- *
160
- * @param {object | undefined} agent the agent whose session is assembled.
161
- * @param {() => object | undefined} [getPlanMode] host-plane planMode reader.
162
- * @param {() => object | undefined} [getSessionProjections] projection service reader.
163
- * @returns {boolean} whether plan mode is active for this step's assembly.
164
- */
165
- export function readPlanModeActive(agent, getPlanMode, getSessionProjections) {
166
- if (agent === undefined || agent === null) return false;
167
- // 1. The agent-scoped planMode instance: `get()` returns the logged state
168
- // plus a pending selection whose boolean is the selected direction.
169
- try {
170
- const scoped = agent.ctx?.get?.('planMode');
171
- if (scoped !== undefined && scoped !== null && typeof scoped.get === 'function') {
172
- const state = scoped.get(agent);
173
- if (state !== undefined && state !== null && typeof state === 'object' && typeof state.active === 'boolean') {
174
- return state.pending === undefined ? state.active : state.pending;
175
- }
176
- }
177
- } catch {
178
- // Fall through to the next source.
179
- }
180
- // 2. The host-plane planMode instance.
181
- try {
182
- const host = typeof getPlanMode === 'function' ? getPlanMode() : undefined;
183
- if (host !== undefined && host !== null && typeof host.get === 'function') {
184
- const state = host.get(agent);
185
- if (state !== undefined && state !== null && typeof state === 'object' && typeof state.active === 'boolean') {
186
- return state.pending === undefined ? state.active : state.pending;
187
- }
188
- }
189
- } catch {
190
- // Fall through to the next source.
191
- }
192
- // 3. The shared `plan` projection's cropped view { active, pending }. The
193
- // pending direction is not exposed here, so a pending selection counts as
194
- // active; by assembly time the pre-step has already applied pending
195
- // selections, which makes this equivalent to the native section's gate.
196
- try {
197
- const projections = typeof getSessionProjections === 'function' ? getSessionProjections() : undefined;
198
- const session = agent?.session;
199
- if (projections !== undefined && projections !== null && session !== undefined && typeof projections.snapshot === 'function') {
200
- const state = projections.snapshot(session, ['plan'])?.values?.plan;
201
- if (state !== undefined && state !== null && typeof state === 'object' && typeof state.active === 'boolean') {
202
- return state.active === true || state.pending === true;
203
- }
204
- }
205
- } catch {
206
- // No usable plan state anywhere; treat the step as outside plan mode.
207
- }
208
- return false;
209
- }
210
-
211
- /**
212
- * Register the section right after the native plan policy.
213
- *
214
- * @param {object} options
215
- * @param {object} options.systemPrompt the Host `systemPrompt` service.
216
- * @param {() => object | undefined} options.getPlanMode optional host-plane `planMode` reader.
217
- * @param {() => object | undefined} [options.getSessionProjections] optional projection service reader.
218
- * @param {() => object | undefined} options.getConfig optional live plugin config reader.
219
- * @returns the Cordis effect disposer.
220
- */
221
- export function registerPlanEvidenceSection({ systemPrompt, getPlanMode, getSessionProjections, getConfig }) {
222
- let order = PLAN_EVIDENCE_ORDER_FALLBACK;
223
- try {
224
- const resolved = typeof systemPrompt.getSectionOrder === 'function'
225
- ? systemPrompt.getSectionOrder('PLAN_POLICY')
226
- : undefined;
227
- if (Number.isFinite(resolved)) order = resolved + 1;
228
- } catch {
229
- // Keep the fallback order; an unavailable central table must not break the plugin.
230
- }
231
- return systemPrompt.section({
232
- name: PLAN_EVIDENCE_SECTION,
233
- order,
234
- text: (context) => {
235
- try {
236
- let config;
237
- try {
238
- config = typeof getConfig === 'function' ? getConfig() : undefined;
239
- } catch {
240
- config = undefined;
241
- }
242
- if (!readPlanModeActive(context?.agent, getPlanMode, getSessionProjections)) return '';
243
- return composePlanGuidance({
244
- brainstorming: readBrainstormingEnabled(config),
245
- unlimitedBudget: readUnlimitedBudgetEnabled(config),
246
- });
247
- } catch {
248
- return '';
249
- }
250
- },
251
- });
252
- }
File without changes
File without changes
File without changes