knoxis-helper 1.7.2 → 1.8.2

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.
@@ -397,7 +397,7 @@ async function main() {
397
397
  console.log(`knoxis-helper@${pkgVersion}`);
398
398
  if (fw) {
399
399
  console.log(`framework bundle: v${fw.bundle}`);
400
- console.log(` kickoff v${fw.documents.kickoff}, resume v${fw.documents.resume}, session-end v${fw.documents.sessionEnd}, recovery v${fw.documents.recovery}, ruleset v${fw.documents.codingRuleset}, portal-contract v${fw.documents.portalContract}`);
400
+ console.log(` kickoff v${fw.documents.kickoff}, feature-kickoff v${fw.documents.featureKickoff}, resume v${fw.documents.resume}, session-end v${fw.documents.sessionEnd}, recovery v${fw.documents.recovery}, ruleset v${fw.documents.codingRuleset}, portal-contract v${fw.documents.portalContract}`);
401
401
  }
402
402
  process.exit(0);
403
403
  }
@@ -12,10 +12,11 @@
12
12
  // "what methodology version is baked into it." Both ride together in every
13
13
  // session record so the portal can render them.
14
14
  module.exports = {
15
- bundle: '1.1.0',
15
+ bundle: '1.2.0',
16
16
  documents: {
17
17
  overview: 1,
18
18
  kickoff: 8,
19
+ featureKickoff: 1,
19
20
  resume: 4,
20
21
  sessionEnd: 4,
21
22
  recovery: 3,
@@ -367,13 +367,19 @@ async function runKitMode(kitMode, task, identity, scaffoldResult) {
367
367
  const pattern = process.env.KNOXIS_KIT_PATTERN || null;
368
368
  let tpl;
369
369
  try {
370
+ // feature-kickoff additionally consumes identity (userId, workspaceId,
371
+ // parent task) so the manifest can carry portal linkage. The other kit
372
+ // templates ignore unknown fields, so passing them through is safe.
370
373
  tpl = kitTemplates.getTemplate(kitMode, {
371
374
  taskDescription: task || null,
372
375
  archetype,
373
376
  pattern,
374
377
  productSlug: identity.productSlug,
375
378
  projectSlug: identity.projectSlug,
376
- workspace: identity.workspace
379
+ workspace: identity.workspace,
380
+ userId: identity.userId,
381
+ workspaceId: identity.workspaceId,
382
+ parentTaskId: (identity.taskIds && identity.taskIds.length) ? identity.taskIds[0] : null
377
383
  });
378
384
  } catch (e) {
379
385
  console.error('Kit template error: ' + e.message);
@@ -594,14 +594,15 @@ function resolvePairProgramScript() {
594
594
  return null;
595
595
  }
596
596
 
597
- const KIT_MODES = new Set(['kickoff', 'resume', 'session-end', 'recovery']);
598
- // kickoff and resume rely on Claude actually writing files to disk
599
- // (docs/state/OPEN_QUESTIONS.md and the rest of the context pack). The
600
- // interactive runner invokes `claude -p --session-id`, which gives Claude
601
- // proper tool access; pair-program.js pipes to `claude` without -p and
602
- // silently skips the file writes. Route those two kits through the
603
- // interactive runner so their kit prompts actually do their work.
604
- const KIT_MODES_VIA_INTERACTIVE = new Set(['kickoff', 'resume']);
597
+ const KIT_MODES = new Set(['kickoff', 'feature-kickoff', 'resume', 'session-end', 'recovery']);
598
+ // Every kit mode rewrites files on disk STATUS / HANDOFF / DECISIONS for
599
+ // session-end, the docs/state/* + docs/features/<slug>/* bag for kickoff /
600
+ // feature-kickoff / resume, and recovery's triage notes. The interactive
601
+ // runner invokes `claude -p --session-id`, which gives Claude proper tool
602
+ // access; the older pair-program.js pipes to `claude` without -p and silently
603
+ // skips the file writes. Route every kit mode through the interactive runner
604
+ // so their kit prompts actually do their work.
605
+ const KIT_MODES_VIA_INTERACTIVE = new Set(['kickoff', 'feature-kickoff', 'resume', 'session-end', 'recovery']);
605
606
 
606
607
  function buildPairProgramCommand({ scriptPath, workspace, mode, archetype, pattern, productSlug, projectSlug, taskPrompt, userId, workspaceId, taskIds }) {
607
608
  const q = v => `"${escapeForDoubleQuotedShellArg(v)}"`;
@@ -34,39 +34,106 @@ function extractFilesTouched(diff) {
34
34
  return Array.from(seen);
35
35
  }
36
36
 
37
- // Snapshot the 6 well-known state files (docs/state/*.md) so the
38
- // session record carries the latest STATUS / HANDOFF / DECISIONS / etc.
39
- // up to the portal for display on qig.ai.
37
+ // Snapshot the canonical state files so the session record carries the
38
+ // latest STATUS / HANDOFF / DECISIONS / etc. up to the portal for display
39
+ // on qig.ai. Three groups are captured into a single bag keyed by relative
40
+ // path; the frontend distinguishes them by path prefix.
41
+ //
42
+ // docs/state/*.md — project-level state (always present after scaffold)
43
+ // docs/architecture/*.md — ARCHITECTURE.md + ADRs from project-kickoff
44
+ // docs/features/<slug>/* — per-feature ROADMAP / PHASES / STATUS / manifest
45
+ // from feature-kickoff (one entry per feature)
46
+ //
47
+ // All three flow through `stateFiles` on the session record. The Java
48
+ // PairProgrammerSessionService persists the bag to the `state_files` JSONB
49
+ // column; no schema change is needed to add new path prefixes.
40
50
  const STATE_FILES_TO_CAPTURE = [
41
51
  'docs/state/STATUS.md',
42
52
  'docs/state/HANDOFF.md',
43
53
  'docs/state/DECISIONS.md',
44
54
  'docs/state/CHANGELOG.md',
45
55
  'docs/state/OPEN_QUESTIONS.md',
46
- 'docs/state/RISKS.md'
56
+ 'docs/state/RISKS.md',
57
+ // Project architecture pack from kickoff v7.
58
+ 'docs/architecture/ARCHITECTURE.md'
59
+ ];
60
+ const FEATURE_FILE_NAMES = [
61
+ 'ROADMAP.md',
62
+ 'PHASES.md',
63
+ 'STATUS.md',
64
+ 'OPEN_QUESTIONS.md',
65
+ 'manifest.json'
47
66
  ];
48
67
  const MAX_STATE_FILE_BYTES = 256 * 1024; // 256KB per file
49
68
 
69
+ function readSafe(absPath, relPath, out) {
70
+ try {
71
+ const stat = fs.statSync(absPath);
72
+ if (!stat.isFile()) return;
73
+ if (stat.size > MAX_STATE_FILE_BYTES) {
74
+ out[relPath] = `[File omitted: ${stat.size} bytes exceeds ${MAX_STATE_FILE_BYTES}-byte cap]`;
75
+ return;
76
+ }
77
+ out[relPath] = fs.readFileSync(absPath, 'utf8');
78
+ } catch (e) {
79
+ // Missing file is normal — skip silently.
80
+ }
81
+ }
82
+
50
83
  function readStateFiles(workspace) {
51
84
  const out = {};
52
85
  if (!workspace) return out;
86
+
87
+ // Fixed list (state pack + ARCHITECTURE).
53
88
  for (const rel of STATE_FILES_TO_CAPTURE) {
54
- const abs = path.join(workspace, rel);
55
- try {
56
- const stat = fs.statSync(abs);
57
- if (!stat.isFile()) continue;
58
- if (stat.size > MAX_STATE_FILE_BYTES) {
59
- out[rel] = `[File omitted: ${stat.size} bytes exceeds ${MAX_STATE_FILE_BYTES}-byte cap]`;
60
- continue;
89
+ readSafe(path.join(workspace, rel), rel, out);
90
+ }
91
+
92
+ // ADRs — docs/architecture/adr/*.md.
93
+ const adrDir = path.join(workspace, 'docs', 'architecture', 'adr');
94
+ try {
95
+ for (const entry of fs.readdirSync(adrDir, { withFileTypes: true })) {
96
+ if (!entry.isFile() || !entry.name.endsWith('.md')) continue;
97
+ const rel = `docs/architecture/adr/${entry.name}`;
98
+ readSafe(path.join(adrDir, entry.name), rel, out);
99
+ }
100
+ } catch (e) {
101
+ // No ADR dir is normal.
102
+ }
103
+
104
+ // Per-feature files — docs/features/<slug>/{ROADMAP,PHASES,STATUS,OPEN_QUESTIONS}.md
105
+ // and manifest.json. One slug = one folder.
106
+ const featuresDir = path.join(workspace, 'docs', 'features');
107
+ try {
108
+ for (const entry of fs.readdirSync(featuresDir, { withFileTypes: true })) {
109
+ if (!entry.isDirectory()) continue;
110
+ for (const filename of FEATURE_FILE_NAMES) {
111
+ const rel = `docs/features/${entry.name}/${filename}`;
112
+ readSafe(path.join(featuresDir, entry.name, filename), rel, out);
61
113
  }
62
- out[rel] = fs.readFileSync(abs, 'utf8');
63
- } catch (e) {
64
- // Missing file is normal — skip silently.
65
114
  }
115
+ } catch (e) {
116
+ // No features dir is normal.
66
117
  }
118
+
67
119
  return out;
68
120
  }
69
121
 
122
+ // Enumerate feature slugs from the workspace so the frontend can list features
123
+ // without parsing the bag. Returns sorted array of slug strings.
124
+ function listFeatureSlugs(workspace) {
125
+ if (!workspace) return [];
126
+ const featuresDir = path.join(workspace, 'docs', 'features');
127
+ try {
128
+ return fs.readdirSync(featuresDir, { withFileTypes: true })
129
+ .filter(e => e.isDirectory())
130
+ .map(e => e.name)
131
+ .sort();
132
+ } catch (e) {
133
+ return [];
134
+ }
135
+ }
136
+
70
137
  // Snapshot product.local.json from the project's parent directory (per
71
138
  // kickoff v7 Phase -1) so the session record carries product context up to
72
139
  // the portal. Multiple projects under one product share this file; the
@@ -270,10 +337,16 @@ class SessionRecorder {
270
337
  completedSteps,
271
338
  closedCleanly,
272
339
  filesTouched: extractFilesTouched(totalDiff),
273
- // Snapshot of docs/state/*.md at session-end so the QIG frontend can
274
- // display the latest STATUS / HANDOFF / DECISIONS / etc. without
275
- // needing live filesystem access on the dev's machine.
340
+ // Snapshot of state-pack + architecture + feature files at session-end
341
+ // so the QIG frontend can display the latest STATUS / HANDOFF /
342
+ // DECISIONS / ROADMAP / etc. without needing live filesystem access
343
+ // on the dev's machine. Single bag keyed by relative path; frontend
344
+ // filters by prefix (docs/state/*, docs/architecture/*,
345
+ // docs/features/<slug>/*).
276
346
  stateFiles: readStateFiles(this.workspace),
347
+ // Quick index of feature slugs found in docs/features/. Lets the
348
+ // frontend enumerate features without parsing the bag.
349
+ featureSlugs: listFeatureSlugs(this.workspace),
277
350
  // Snapshot of product.local.json from the parent directory so the
278
351
  // frontend can render product context alongside the session record.
279
352
  productContext: readProductContext(this.workspace),
@@ -299,5 +372,6 @@ module.exports = {
299
372
  slugify,
300
373
  extractFilesTouched,
301
374
  readStateFiles,
302
- readProductContext
375
+ readProductContext,
376
+ listFeatureSlugs
303
377
  };
@@ -0,0 +1,327 @@
1
+ 'use strict';
2
+
3
+ // Feature Kickoff — single-shot, autonomous (v1)
4
+ //
5
+ // Where project-kickoff sets up a brand-new project context pack, feature-kickoff
6
+ // takes a single feature task from the operator, decomposes it into a phased
7
+ // roadmap, and writes the roadmap + phase plan + machine-readable manifest into
8
+ // docs/features/<slug>/. Multiple features can coexist; each is independently
9
+ // trackable from the QIG dashboard via its manifest.json.
10
+ //
11
+ // State machine (similar shape to resume.js, autonomous-first):
12
+ // A: docs/features/<slug>/ missing → write the roadmap
13
+ // B: directory exists with unanswered _(fill in)_ entries → wait
14
+ // C: directory exists, no pending answers → refresh in place
15
+
16
+ const FEATURE_KICKOFF_BODY = `# Feature Kickoff (single-shot, autonomous)
17
+
18
+ You are running in single-shot mode. You produce one response and the process
19
+ exits. Your job is to take the operator's feature description (the task in the
20
+ session header above), decompose it into a concrete phased roadmap, and write
21
+ the roadmap + phase plan + manifest to disk so the QIG dashboard can track it.
22
+
23
+ This is **planning only** — you do not change application code in this run.
24
+
25
+ ## Step 0 — Orient on the project
26
+
27
+ Read these files first (whichever exist) to ground your plan in the codebase:
28
+
29
+ - \`CLAUDE.md\`
30
+ - \`README.md\`
31
+ - \`docs/state/STATUS.md\`
32
+ - \`docs/state/HANDOFF.md\`
33
+ - \`docs/state/DECISIONS.md\`
34
+ - \`docs/architecture/ARCHITECTURE.md\` (if present)
35
+ - Any entry-point files mentioned in CLAUDE.md
36
+
37
+ If the project has none of this, still proceed — feature-kickoff does not
38
+ require project-kickoff to have run first.
39
+
40
+ ## Step 1 — Pick a feature slug
41
+
42
+ Derive a slug from the feature description in the session header. Lowercase,
43
+ dashes, ≤40 chars, semantically descriptive. Examples:
44
+
45
+ - "Add real-time notification toasts" → \`realtime-notification-toasts\`
46
+ - "Replace polling with SSE on the dashboard" → \`dashboard-sse-replacement\`
47
+
48
+ Do not include the words "feature" or "task" in the slug.
49
+
50
+ ## Step 2 — State-branch detection
51
+
52
+ Check \`docs/features/<slug>/\`:
53
+
54
+ - **State A — directory missing.** First run for this feature. Continue to Step 3.
55
+ - **State B — directory exists and \`docs/features/<slug>/OPEN_QUESTIONS.md\` has at least one entry under \`## Pending Answers\` whose \`**Answer:**\` line is still \`_(fill in)_\`.** Print:
56
+
57
+ \`\`\`
58
+ Feature kickoff blocked — waiting on answers in docs/features/<slug>/OPEN_QUESTIONS.md.
59
+
60
+ Unanswered: #<n>, #<n>
61
+ Answered: #<n>
62
+
63
+ Fill in the remaining **Answer:** lines and re-run feature-kickoff.
64
+ \`\`\`
65
+
66
+ Then stop. Do not edit the roadmap or phase files.
67
+
68
+ - **State C — directory exists, no pending answers (refresh).** Re-read the
69
+ existing roadmap and phases. Reconcile with the operator's note in the session
70
+ header (if it adds new scope or corrects something), then update files in place.
71
+ Skip to Step 4.
72
+
73
+ ## Step 3 — Decompose the feature into phases
74
+
75
+ Plan 3–6 phases. Each phase has 2–6 concrete steps. Phases run sequentially.
76
+ Each phase must have a clear "done" definition.
77
+
78
+ Default phase shape (adjust per feature; collapse to 2–3 phases if small,
79
+ expand if large):
80
+
81
+ 1. **Discovery** — read existing code, find integration points, list
82
+ constraints
83
+ 2. **Design** — data model / API contract / UI shape decisions; capture in
84
+ DECISIONS where non-trivial
85
+ 3. **Implementation** — break into commit-sized steps; each step touches
86
+ named files
87
+ 4. **Testing** — unit / integration / manual coverage
88
+ 5. **Rollout** — feature flag, docs, telemetry, deprecations
89
+
90
+ Each step is one imperative-voice action plus the file(s) or surface it
91
+ touches. Steps must be small enough to ship in one pair-program session.
92
+
93
+ **Don't pad.** A 4-step feature is fine. A 30-step feature with 3 phases of
94
+ filler is not.
95
+
96
+ ## Step 4 — Capture genuine open questions only
97
+
98
+ If something truly cannot be decided autonomously (missing API decision,
99
+ ambiguous scope, conflicting existing patterns), append it to
100
+ \`docs/features/<slug>/OPEN_QUESTIONS.md\` under \`## Pending Answers\` using
101
+ this shape:
102
+
103
+ \`\`\`markdown
104
+ ### N. <question>
105
+ *Phase: <phase number>. Raised: <today's ISO date>.*
106
+ **Answer:** _(fill in)_
107
+ \`\`\`
108
+
109
+ **Be sparing.** Most "questions" are decisions you should make and capture in
110
+ the feature's DECISIONS section. If you write more than 3 pending questions
111
+ you are over-using this.
112
+
113
+ If you write any pending questions, you are now in a partial State A — write
114
+ OPEN_QUESTIONS.md, write a stub manifest.json with \`"status": "blocked"\` at
115
+ the feature level, do NOT write ROADMAP.md / PHASES.md / STATUS.md, and stop
116
+ with a short note pointing the operator at OPEN_QUESTIONS.md. The next run
117
+ (after answers are filled) will pick up at State C and write the rest.
118
+
119
+ ## Step 5 — Write files
120
+
121
+ All paths are relative to the workspace root. Create \`docs/features/<slug>/\`
122
+ if missing.
123
+
124
+ ### \`docs/features/<slug>/ROADMAP.md\`
125
+
126
+ \`\`\`markdown
127
+ ---
128
+ feature_slug: <slug>
129
+ feature_title: <descriptive title>
130
+ parent_task_id: <from session header; null if not provided>
131
+ workspace_id: <from session header; null if not provided>
132
+ user_id: <from session header; null if not provided>
133
+ created_at: <ISO date>
134
+ status: planning
135
+ ---
136
+
137
+ # Feature Roadmap: <title>
138
+
139
+ ## Summary
140
+ <2–3 sentence summary of what this feature does and why it matters>
141
+
142
+ ## Phases
143
+ 1. **<Phase 1 title>** — <one-line goal>
144
+ 2. **<Phase 2 title>** — <one-line goal>
145
+ ...
146
+
147
+ ## Definition of done
148
+ - <criterion>
149
+ - <criterion>
150
+
151
+ ## Notes
152
+ <anything important the operator should know — risks, constraints,
153
+ discovered-during-planning facts. "None." if none.>
154
+ \`\`\`
155
+
156
+ ### \`docs/features/<slug>/PHASES.md\`
157
+
158
+ \`\`\`markdown
159
+ ---
160
+ feature_slug: <slug>
161
+ ---
162
+
163
+ # <title> — Phases
164
+
165
+ ## Phase 1: <title>
166
+ **Goal:** <one sentence>
167
+ **Done when:** <crisp criterion>
168
+
169
+ - [ ] 1.1 — <action> *(touches: <file or surface>)*
170
+ - [ ] 1.2 — ...
171
+
172
+ ## Phase 2: <title>
173
+ **Goal:** ...
174
+ **Done when:** ...
175
+
176
+ - [ ] 2.1 — ...
177
+ ...
178
+ \`\`\`
179
+
180
+ ### \`docs/features/<slug>/STATUS.md\`
181
+
182
+ \`\`\`markdown
183
+ ---
184
+ feature_slug: <slug>
185
+ ---
186
+
187
+ # <title> — Status
188
+
189
+ _Last updated: <ISO date>_
190
+ _Current phase: 1_
191
+
192
+ ## Progress
193
+ - [ ] Phase 1: <title>
194
+ - [ ] Phase 2: <title>
195
+ ...
196
+
197
+ ## Active step
198
+ None yet — kicked off, awaiting first work session.
199
+
200
+ ## Recent activity
201
+ - <ISO date>: feature kicked off
202
+
203
+ ## Notes
204
+ None.
205
+ \`\`\`
206
+
207
+ ### \`docs/features/<slug>/manifest.json\`
208
+
209
+ \`\`\`json
210
+ {
211
+ "feature_slug": "<slug>",
212
+ "feature_title": "<title>",
213
+ "parent_task_id": "<id or null>",
214
+ "workspace_id": "<id or null>",
215
+ "user_id": "<id or null>",
216
+ "product_slug": "<from session header or null>",
217
+ "project_slug": "<from session header or null>",
218
+ "kicked_off_at": "<ISO timestamp>",
219
+ "status": "planning",
220
+ "current_phase": "phase-1",
221
+ "phases": [
222
+ {
223
+ "id": "phase-1",
224
+ "title": "<title>",
225
+ "goal": "<goal>",
226
+ "done_when": "<criterion>",
227
+ "status": "pending",
228
+ "steps": [
229
+ {
230
+ "id": "phase-1-step-1",
231
+ "action": "<imperative action>",
232
+ "touches": "<file or surface>",
233
+ "status": "pending"
234
+ }
235
+ ]
236
+ }
237
+ ],
238
+ "definition_of_done": ["<criterion>", "<criterion>"]
239
+ }
240
+ \`\`\`
241
+
242
+ The \`manifest.json\` is the canonical machine-readable form. The MD files are
243
+ the human-readable view. Keep them consistent — if you change a phase title or
244
+ step in one, change it in all four files.
245
+
246
+ ## Step 6 — Append to project state (don't overwrite)
247
+
248
+ Touch two project-level files. **Append only — do not overwrite other
249
+ sections.**
250
+
251
+ \`docs/state/STATUS.md\` — under \`## Notes\` (create the section if missing),
252
+ append:
253
+
254
+ > Feature kicked off: \`<slug>\` — see \`docs/features/<slug>/\`.
255
+
256
+ \`docs/state/CHANGELOG.md\` — under \`## [Unreleased]\` → \`### Added\`,
257
+ append a single bullet:
258
+
259
+ > Feature roadmap: \`<slug>\` (kickoff <date>).
260
+
261
+ Do not touch \`docs/state/HANDOFF.md\`, \`docs/state/DECISIONS.md\`,
262
+ \`docs/state/OPEN_QUESTIONS.md\`, or any application code. Feature
263
+ kickoff is planning only.
264
+
265
+ ## Step 7 — Output for the operator
266
+
267
+ End your response with a copyable block summarizing what was written:
268
+
269
+ \`\`\`
270
+ Feature kickoff complete: <slug>
271
+
272
+ Files:
273
+ docs/features/<slug>/ROADMAP.md
274
+ docs/features/<slug>/PHASES.md
275
+ docs/features/<slug>/STATUS.md
276
+ docs/features/<slug>/manifest.json
277
+
278
+ Project state:
279
+ docs/state/STATUS.md (appended Notes entry)
280
+ docs/state/CHANGELOG.md (appended Added entry)
281
+
282
+ Next: pick a step from PHASES.md and start a normal pair-program session on it.
283
+ The dashboard will track progress against manifest.json.
284
+ \`\`\`
285
+
286
+ ## Non-negotiables
287
+
288
+ - Write files. Do not describe what you would write.
289
+ - Use the operator's task description as the feature description verbatim
290
+ where reasonable; only paraphrase to fit slug/title/summary length.
291
+ - Keep \`manifest.json\` consistent with the three MD files at all times.
292
+ - One feature per run. The slug picked in Step 1 is final for this run.
293
+ - Do not modify project code. Planning only.
294
+ - Never overwrite an existing \`docs/features/<slug>/ROADMAP.md\` outside
295
+ State C. If State A detection misfires (directory exists but you think it
296
+ shouldn't), halt with a one-line note rather than clobbering.
297
+
298
+ ---
299
+
300
+ `;
301
+
302
+ function buildFeatureKickoffPrompt({
303
+ taskDescription,
304
+ productSlug,
305
+ projectSlug,
306
+ workspace,
307
+ userId,
308
+ workspaceId,
309
+ parentTaskId
310
+ } = {}) {
311
+ const header = ['Mode: feature-kickoff'];
312
+ if (productSlug) header.push(`Product: ${productSlug}`);
313
+ if (projectSlug) header.push(`Project: ${projectSlug}`);
314
+ if (workspace) header.push(`Workspace: ${workspace}`);
315
+ if (userId) header.push(`User ID: ${userId}`);
316
+ if (workspaceId) header.push(`Workspace ID: ${workspaceId}`);
317
+ if (parentTaskId) header.push(`Parent task ID: ${parentTaskId}`);
318
+ if (taskDescription) header.push(`Feature description (use as-is for the title and summary):\n${taskDescription}`);
319
+ const ctx = `Session context:\n${header.join('\n')}\n\n`;
320
+ return ctx + FEATURE_KICKOFF_BODY;
321
+ }
322
+
323
+ module.exports = {
324
+ title: 'Feature Kickoff',
325
+ body: FEATURE_KICKOFF_BODY,
326
+ buildPrompt: buildFeatureKickoffPrompt
327
+ };
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const kickoff = require('./kickoff');
4
+ const featureKickoff = require('./feature-kickoff');
4
5
  const resume = require('./resume');
5
6
  const sessionEnd = require('./session-end');
6
7
  const recovery = require('./recovery');
@@ -8,6 +9,7 @@ const codingRuleset = require('./coding-ruleset');
8
9
 
9
10
  const MODES = {
10
11
  kickoff,
12
+ 'feature-kickoff': featureKickoff,
11
13
  resume,
12
14
  'session-end': sessionEnd,
13
15
  recovery
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knoxis-helper",
3
- "version": "1.7.2",
3
+ "version": "1.8.2",
4
4
  "description": "Local helper for Knoxis pair programming - connects your machine to Knoxis on qig.ai",
5
5
  "bin": {
6
6
  "knoxis-helper": "./bin/knoxis-helper.js"