procedure-cli 0.1.0 → 0.1.1

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/CODE-REVIEW.md CHANGED
@@ -251,3 +251,35 @@
251
251
 
252
252
  ### Residual Risks / Testing Gaps
253
253
  - No automated UI tests currently cover end-to-end Powerline branching (`gitCommitted` true/false).
254
+
255
+ ---
256
+
257
+ ## Entry 2026-02-21
258
+
259
+ ### Entry ID
260
+ - `CR-20260221-006`
261
+
262
+ ### Supersedes
263
+ - `CR-20260221-005`
264
+
265
+ ### Scope
266
+ - New review cycle after latest documented fix entry (`CF-20260222-003`).
267
+ - Validate current status of previously fixed findings and scan for regressions.
268
+
269
+ ### Validation Matrix
270
+ | Finding # | Previous Severity | Current Status | Evidence | Notes |
271
+ |-----------|-------------------|----------------|----------|-------|
272
+ | 9 | Low | Fixed | `CODE-FIXED.md:112`, `src/steps/powerline.tsx:22`, `src/steps/powerline.tsx:127`, `src/steps/powerline.tsx:132` | Commit outcome is now reflected in UI; mixed success/warning state is resolved. |
273
+ | 6 | Low | Fixed | `CODE-FIXED.md:54`, `templates/docs/USER-STORIES.md.hbs:3`, `templates/docs/USER-STORIES.md.hbs:23` | USER-STORIES fallback remains present and active when story array is empty. |
274
+
275
+ ### Findings (ordered by severity)
276
+ - No new functional findings identified in this review cycle.
277
+
278
+ ### Verification Notes
279
+ - Procedure compliance: read latest `CODE-REVIEW.md` and latest `CODE-FIXED.md` before review.
280
+ - `npm run typecheck`: pass.
281
+ - `npm run build`: pass.
282
+ - Code inspection confirms `CF-20260222-003` changes remain present in `src/steps/powerline.tsx`.
283
+
284
+ ### Residual Risks / Testing Gaps
285
+ - No automated UI tests currently cover end-to-end Powerline branching (`gitCommitted` true/false).
@@ -3,15 +3,49 @@ import { useState } from "react";
3
3
  import { Text } from "ink";
4
4
  import { TextInput } from "@inkjs/ui";
5
5
  import { GutterLine } from "../components/gutter-line.js";
6
- import { GutteredSelect } from "../components/guttered-select.js";
6
+ import { GutteredSelect, GutteredMultiSelect } from "../components/guttered-select.js";
7
7
  const PRESET_OPTIONS = [
8
8
  { label: "TypeScript + Node.js", value: "typescript-node" },
9
9
  ];
10
- const ADVANCED_FIELDS = [
11
- { key: "language", label: "Language" },
12
- { key: "framework", label: "Framework" },
13
- { key: "codeStyle", label: "Code style conventions (comma-separated)" },
10
+ const LANGUAGE_OPTIONS = [
11
+ { label: "TypeScript", value: "TypeScript", description: "Typed JavaScript, strict mode recommended" },
12
+ { label: "JavaScript", value: "JavaScript", description: "Dynamic, runs everywhere" },
13
+ { label: "Python", value: "Python", description: "Readable, great ecosystem for AI/ML & web" },
14
+ { label: "Go", value: "Go", description: "Fast compilation, built-in concurrency" },
15
+ { label: "Rust", value: "Rust", description: "Memory-safe systems programming" },
16
+ { label: "Java", value: "Java", description: "Enterprise-grade, JVM ecosystem" },
17
+ { label: "Ruby", value: "Ruby", description: "Developer happiness, Rails ecosystem" },
18
+ { label: "PHP", value: "PHP", description: "Web-native, Laravel & WordPress" },
19
+ { label: "Swift", value: "Swift", description: "Apple platforms, type-safe" },
20
+ { label: "Kotlin", value: "Kotlin", description: "Modern JVM, Android-first" },
14
21
  ];
22
+ const FRAMEWORK_OPTIONS = [
23
+ { label: "Node.js", value: "Node.js", description: "JS/TS server runtime" },
24
+ { label: "React", value: "React", description: "Component-based UI library" },
25
+ { label: "Next.js", value: "Next.js", description: "Full-stack React framework" },
26
+ { label: "Vue", value: "Vue", description: "Progressive UI framework" },
27
+ { label: "Svelte", value: "Svelte", description: "Compile-time UI framework" },
28
+ { label: "Express", value: "Express", description: "Minimal Node.js web framework" },
29
+ { label: "Fastify", value: "Fastify", description: "Fast Node.js web framework" },
30
+ { label: "Django", value: "Django", description: "Batteries-included Python web" },
31
+ { label: "Flask", value: "Flask", description: "Lightweight Python web" },
32
+ { label: "Rails", value: "Rails", description: "Convention-over-config Ruby web" },
33
+ ];
34
+ /** Suggest frameworks based on selected languages */
35
+ function getFrameworkPreselect(languages) {
36
+ const langSet = new Set(languages.map((l) => l.toLowerCase()));
37
+ const preselect = [];
38
+ if (langSet.has("typescript") || langSet.has("javascript")) {
39
+ preselect.push("Node.js");
40
+ }
41
+ if (langSet.has("python")) {
42
+ preselect.push("Django");
43
+ }
44
+ if (langSet.has("ruby")) {
45
+ preselect.push("Rails");
46
+ }
47
+ return preselect;
48
+ }
15
49
  const PRESETS = {
16
50
  "typescript-node": {
17
51
  language: "TypeScript",
@@ -30,8 +64,9 @@ const PRESETS = {
30
64
  };
31
65
  export default function StackStyle({ onComplete }) {
32
66
  const [mode, setMode] = useState("choosing");
33
- const [advancedIndex, setAdvancedIndex] = useState(0);
34
- const [answers, setAnswers] = useState({});
67
+ const [advancedStep, setAdvancedStep] = useState("language");
68
+ const [selectedLanguages, setSelectedLanguages] = useState([]);
69
+ const [selectedFrameworks, setSelectedFrameworks] = useState([]);
35
70
  if (mode === "choosing") {
36
71
  return (_jsxs(_Fragment, { children: [_jsx(GutterLine, { children: _jsx(Text, { bold: true, children: "Setup mode:" }) }), _jsx(GutteredSelect, { options: [
37
72
  { label: "QuickStart (use a preset)", value: "quickstart" },
@@ -47,21 +82,29 @@ export default function StackStyle({ onComplete }) {
47
82
  } })] }));
48
83
  }
49
84
  // Advanced mode
50
- const current = ADVANCED_FIELDS[advancedIndex];
51
- function handleSubmit(value) {
52
- const next = { ...answers, [current.key]: value };
53
- setAnswers(next);
54
- if (advancedIndex < ADVANCED_FIELDS.length - 1) {
55
- setAdvancedIndex(advancedIndex + 1);
56
- }
57
- else {
58
- onComplete({
59
- language: next.language,
60
- framework: next.framework,
61
- codeStyle: (next.codeStyle || "").split(",").map((s) => s.trim()),
62
- });
63
- }
85
+ const advStep = advancedStep;
86
+ if (advStep === "language") {
87
+ return (_jsxs(_Fragment, { children: [_jsx(GutterLine, { children: _jsx(Text, { bold: true, children: "Programming languages:" }) }), _jsx(GutteredMultiSelect, { options: LANGUAGE_OPTIONS, onSubmit: (values) => {
88
+ setSelectedLanguages(values);
89
+ setAdvancedStep("framework");
90
+ } })] }));
91
+ }
92
+ if (advStep === "framework") {
93
+ return (_jsxs(_Fragment, { children: [_jsx(GutterLine, { children: _jsxs(Text, { dimColor: true, children: ["Languages: ", selectedLanguages.join(", ")] }) }), _jsx(GutterLine, { children: _jsx(Text, { bold: true, children: "Frameworks:" }) }), _jsx(GutteredMultiSelect, { options: FRAMEWORK_OPTIONS, initialSelected: getFrameworkPreselect(selectedLanguages), onSubmit: (values) => {
94
+ setSelectedFrameworks(values);
95
+ setAdvancedStep("codeStyle");
96
+ } })] }));
64
97
  }
65
- return (_jsxs(_Fragment, { children: [ADVANCED_FIELDS.slice(0, advancedIndex).map((f) => (_jsx(GutterLine, { children: _jsxs(Text, { dimColor: true, children: [f.label, ": ", answers[f.key]] }) }, f.key))), _jsxs(GutterLine, { children: [_jsxs(Text, { bold: true, children: [current.label, ": "] }), _jsx(TextInput, { placeholder: "...", onSubmit: handleSubmit })] })] }));
98
+ // codeStyle step
99
+ return (_jsxs(_Fragment, { children: [_jsx(GutterLine, { children: _jsxs(Text, { dimColor: true, children: ["Languages: ", selectedLanguages.join(", ")] }) }), _jsx(GutterLine, { children: _jsxs(Text, { dimColor: true, children: ["Frameworks: ", selectedFrameworks.join(", ")] }) }), _jsxs(GutterLine, { children: [_jsx(Text, { bold: true, children: "Code style conventions (comma-separated): " }), _jsx(TextInput, { placeholder: "e.g. strict mode, camelCase, ESM imports", onSubmit: (value) => {
100
+ onComplete({
101
+ language: selectedLanguages.join(", "),
102
+ framework: selectedFrameworks.join(", "),
103
+ codeStyle: value
104
+ .split(",")
105
+ .map((s) => s.trim())
106
+ .filter(Boolean),
107
+ });
108
+ } })] })] }));
66
109
  }
67
110
  //# sourceMappingURL=stack-style.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stack-style.js","sourceRoot":"","sources":["../../src/steps/stack-style.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stack-style.js","sourceRoot":"","sources":["../../src/steps/stack-style.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "procedure-cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "CLI-based AI Agent powered by AI SDK 6, Z.ai, and OpenAI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -2,7 +2,7 @@ import React, { useState } from "react";
2
2
  import { Text } from "ink";
3
3
  import { TextInput } from "@inkjs/ui";
4
4
  import { GutterLine } from "../components/gutter-line.js";
5
- import { GutteredSelect } from "../components/guttered-select.js";
5
+ import { GutteredSelect, GutteredMultiSelect } from "../components/guttered-select.js";
6
6
  import type { WizardAnswers } from "../lib/types.js";
7
7
 
8
8
  interface Props {
@@ -10,18 +10,54 @@ interface Props {
10
10
  }
11
11
 
12
12
  type Mode = "choosing" | "quickstart" | "advanced";
13
- type AdvancedField = "language" | "framework" | "codeStyle";
13
+ type AdvancedStep = "language" | "framework" | "codeStyle";
14
14
 
15
15
  const PRESET_OPTIONS = [
16
16
  { label: "TypeScript + Node.js", value: "typescript-node" },
17
17
  ];
18
18
 
19
- const ADVANCED_FIELDS: { key: AdvancedField; label: string }[] = [
20
- { key: "language", label: "Language" },
21
- { key: "framework", label: "Framework" },
22
- { key: "codeStyle", label: "Code style conventions (comma-separated)" },
19
+ const LANGUAGE_OPTIONS = [
20
+ { label: "TypeScript", value: "TypeScript", description: "Typed JavaScript, strict mode recommended" },
21
+ { label: "JavaScript", value: "JavaScript", description: "Dynamic, runs everywhere" },
22
+ { label: "Python", value: "Python", description: "Readable, great ecosystem for AI/ML & web" },
23
+ { label: "Go", value: "Go", description: "Fast compilation, built-in concurrency" },
24
+ { label: "Rust", value: "Rust", description: "Memory-safe systems programming" },
25
+ { label: "Java", value: "Java", description: "Enterprise-grade, JVM ecosystem" },
26
+ { label: "Ruby", value: "Ruby", description: "Developer happiness, Rails ecosystem" },
27
+ { label: "PHP", value: "PHP", description: "Web-native, Laravel & WordPress" },
28
+ { label: "Swift", value: "Swift", description: "Apple platforms, type-safe" },
29
+ { label: "Kotlin", value: "Kotlin", description: "Modern JVM, Android-first" },
23
30
  ];
24
31
 
32
+ const FRAMEWORK_OPTIONS = [
33
+ { label: "Node.js", value: "Node.js", description: "JS/TS server runtime" },
34
+ { label: "React", value: "React", description: "Component-based UI library" },
35
+ { label: "Next.js", value: "Next.js", description: "Full-stack React framework" },
36
+ { label: "Vue", value: "Vue", description: "Progressive UI framework" },
37
+ { label: "Svelte", value: "Svelte", description: "Compile-time UI framework" },
38
+ { label: "Express", value: "Express", description: "Minimal Node.js web framework" },
39
+ { label: "Fastify", value: "Fastify", description: "Fast Node.js web framework" },
40
+ { label: "Django", value: "Django", description: "Batteries-included Python web" },
41
+ { label: "Flask", value: "Flask", description: "Lightweight Python web" },
42
+ { label: "Rails", value: "Rails", description: "Convention-over-config Ruby web" },
43
+ ];
44
+
45
+ /** Suggest frameworks based on selected languages */
46
+ function getFrameworkPreselect(languages: string[]): string[] {
47
+ const langSet = new Set(languages.map((l) => l.toLowerCase()));
48
+ const preselect: string[] = [];
49
+ if (langSet.has("typescript") || langSet.has("javascript")) {
50
+ preselect.push("Node.js");
51
+ }
52
+ if (langSet.has("python")) {
53
+ preselect.push("Django");
54
+ }
55
+ if (langSet.has("ruby")) {
56
+ preselect.push("Rails");
57
+ }
58
+ return preselect;
59
+ }
60
+
25
61
  const PRESETS: Record<string, Partial<WizardAnswers>> = {
26
62
  "typescript-node": {
27
63
  language: "TypeScript",
@@ -41,8 +77,9 @@ const PRESETS: Record<string, Partial<WizardAnswers>> = {
41
77
 
42
78
  export default function StackStyle({ onComplete }: Props) {
43
79
  const [mode, setMode] = useState<Mode>("choosing");
44
- const [advancedIndex, setAdvancedIndex] = useState(0);
45
- const [answers, setAnswers] = useState<Record<string, string>>({});
80
+ const [advancedStep, setAdvancedStep] = useState<AdvancedStep>("language");
81
+ const [selectedLanguages, setSelectedLanguages] = useState<string[]>([]);
82
+ const [selectedFrameworks, setSelectedFrameworks] = useState<string[]>([]);
46
83
 
47
84
  if (mode === "choosing") {
48
85
  return (
@@ -81,36 +118,70 @@ export default function StackStyle({ onComplete }: Props) {
81
118
  }
82
119
 
83
120
  // Advanced mode
84
- const current = ADVANCED_FIELDS[advancedIndex];
121
+ const advStep = advancedStep as AdvancedStep;
85
122
 
86
- function handleSubmit(value: string) {
87
- const next = { ...answers, [current!.key]: value };
88
- setAnswers(next);
123
+ if (advStep === "language") {
124
+ return (
125
+ <>
126
+ <GutterLine>
127
+ <Text bold>Programming languages:</Text>
128
+ </GutterLine>
129
+ <GutteredMultiSelect
130
+ options={LANGUAGE_OPTIONS}
131
+ onSubmit={(values) => {
132
+ setSelectedLanguages(values);
133
+ setAdvancedStep("framework");
134
+ }}
135
+ />
136
+ </>
137
+ );
138
+ }
89
139
 
90
- if (advancedIndex < ADVANCED_FIELDS.length - 1) {
91
- setAdvancedIndex(advancedIndex + 1);
92
- } else {
93
- onComplete({
94
- language: next.language,
95
- framework: next.framework,
96
- codeStyle: (next.codeStyle || "").split(",").map((s) => s.trim()),
97
- });
98
- }
140
+ if (advStep === "framework") {
141
+ return (
142
+ <>
143
+ <GutterLine>
144
+ <Text dimColor>Languages: {selectedLanguages.join(", ")}</Text>
145
+ </GutterLine>
146
+ <GutterLine>
147
+ <Text bold>Frameworks:</Text>
148
+ </GutterLine>
149
+ <GutteredMultiSelect
150
+ options={FRAMEWORK_OPTIONS}
151
+ initialSelected={getFrameworkPreselect(selectedLanguages)}
152
+ onSubmit={(values) => {
153
+ setSelectedFrameworks(values);
154
+ setAdvancedStep("codeStyle");
155
+ }}
156
+ />
157
+ </>
158
+ );
99
159
  }
100
160
 
161
+ // codeStyle step
101
162
  return (
102
163
  <>
103
- {ADVANCED_FIELDS.slice(0, advancedIndex).map((f) => (
104
- <GutterLine key={f.key}>
105
- <Text dimColor>
106
- {f.label}: {answers[f.key]}
107
- </Text>
108
- </GutterLine>
109
- ))}
110
-
111
164
  <GutterLine>
112
- <Text bold>{current!.label}: </Text>
113
- <TextInput placeholder="..." onSubmit={handleSubmit} />
165
+ <Text dimColor>Languages: {selectedLanguages.join(", ")}</Text>
166
+ </GutterLine>
167
+ <GutterLine>
168
+ <Text dimColor>Frameworks: {selectedFrameworks.join(", ")}</Text>
169
+ </GutterLine>
170
+ <GutterLine>
171
+ <Text bold>Code style conventions (comma-separated): </Text>
172
+ <TextInput
173
+ placeholder="e.g. strict mode, camelCase, ESM imports"
174
+ onSubmit={(value) => {
175
+ onComplete({
176
+ language: selectedLanguages.join(", "),
177
+ framework: selectedFrameworks.join(", "),
178
+ codeStyle: value
179
+ .split(",")
180
+ .map((s) => s.trim())
181
+ .filter(Boolean),
182
+ });
183
+ }}
184
+ />
114
185
  </GutterLine>
115
186
  </>
116
187
  );