@nova286/nova-workflow 0.2.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.
- package/README.md +246 -0
- package/dist/cli/commands/archive.d.ts +1 -0
- package/dist/cli/commands/archive.js +120 -0
- package/dist/cli/commands/archive.js.map +1 -0
- package/dist/cli/commands/context.d.ts +1 -0
- package/dist/cli/commands/context.js +23 -0
- package/dist/cli/commands/context.js.map +1 -0
- package/dist/cli/commands/guard.d.ts +1 -0
- package/dist/cli/commands/guard.js +21 -0
- package/dist/cli/commands/guard.js.map +1 -0
- package/dist/cli/commands/init.d.ts +1 -0
- package/dist/cli/commands/init.js +22 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/status.d.ts +1 -0
- package/dist/cli/commands/status.js +72 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/error-handler.d.ts +1 -0
- package/dist/cli/error-handler.js +18 -0
- package/dist/cli/error-handler.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +35 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/ui.d.ts +10 -0
- package/dist/cli/ui.js +21 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/cli-core/__tests__/context-generator.test.d.ts +1 -0
- package/dist/cli-core/__tests__/context-generator.test.js +97 -0
- package/dist/cli-core/__tests__/context-generator.test.js.map +1 -0
- package/dist/cli-core/__tests__/dispatcher.test.d.ts +1 -0
- package/dist/cli-core/__tests__/dispatcher.test.js +99 -0
- package/dist/cli-core/__tests__/dispatcher.test.js.map +1 -0
- package/dist/cli-core/__tests__/guard.test.d.ts +1 -0
- package/dist/cli-core/__tests__/guard.test.js +136 -0
- package/dist/cli-core/__tests__/guard.test.js.map +1 -0
- package/dist/cli-core/__tests__/init-manager.test.d.ts +1 -0
- package/dist/cli-core/__tests__/init-manager.test.js +150 -0
- package/dist/cli-core/__tests__/init-manager.test.js.map +1 -0
- package/dist/cli-core/__tests__/pipeline.test.d.ts +1 -0
- package/dist/cli-core/__tests__/pipeline.test.js +119 -0
- package/dist/cli-core/__tests__/pipeline.test.js.map +1 -0
- package/dist/cli-core/__tests__/project-detect.test.d.ts +1 -0
- package/dist/cli-core/__tests__/project-detect.test.js +92 -0
- package/dist/cli-core/__tests__/project-detect.test.js.map +1 -0
- package/dist/cli-core/__tests__/state-manager.test.d.ts +1 -0
- package/dist/cli-core/__tests__/state-manager.test.js +120 -0
- package/dist/cli-core/__tests__/state-manager.test.js.map +1 -0
- package/dist/cli-core/adapters/claude-code.d.ts +6 -0
- package/dist/cli-core/adapters/claude-code.js +311 -0
- package/dist/cli-core/adapters/claude-code.js.map +1 -0
- package/dist/cli-core/context-generator.d.ts +4 -0
- package/dist/cli-core/context-generator.js +81 -0
- package/dist/cli-core/context-generator.js.map +1 -0
- package/dist/cli-core/dispatcher.d.ts +11 -0
- package/dist/cli-core/dispatcher.js +169 -0
- package/dist/cli-core/dispatcher.js.map +1 -0
- package/dist/cli-core/guard.d.ts +1 -0
- package/dist/cli-core/guard.js +57 -0
- package/dist/cli-core/guard.js.map +1 -0
- package/dist/cli-core/init-manager.d.ts +25 -0
- package/dist/cli-core/init-manager.js +182 -0
- package/dist/cli-core/init-manager.js.map +1 -0
- package/dist/cli-core/pipeline.d.ts +7 -0
- package/dist/cli-core/pipeline.js +79 -0
- package/dist/cli-core/pipeline.js.map +1 -0
- package/dist/cli-core/platform-client.d.ts +19 -0
- package/dist/cli-core/platform-client.js +119 -0
- package/dist/cli-core/platform-client.js.map +1 -0
- package/dist/cli-core/project-detect.d.ts +1 -0
- package/dist/cli-core/project-detect.js +64 -0
- package/dist/cli-core/project-detect.js.map +1 -0
- package/dist/cli-core/state.d.ts +11 -0
- package/dist/cli-core/state.js +106 -0
- package/dist/cli-core/state.js.map +1 -0
- package/dist/cli-core/types.d.ts +141 -0
- package/dist/cli-core/types.js +13 -0
- package/dist/cli-core/types.js.map +1 -0
- package/package.json +33 -0
- package/templates/docs/design.md +41 -0
- package/templates/docs/proposal.md +25 -0
package/README.md
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
# Nova
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<strong>THE AI Workflow is All You Need</strong>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
A thin orchestration shell for AI-assisted software development.<br/>
|
|
9
|
+
<strong>Don't neuter your skills. Orchestrate them.</strong>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## What is Nova?
|
|
15
|
+
|
|
16
|
+
Nova adds **process discipline** to AI-assisted development without restricting
|
|
17
|
+
what your AI can do. It sequences your existing skills through a structured
|
|
18
|
+
5-phase workflow — think of it as a state machine that sits between you and
|
|
19
|
+
your AI tools, ensuring nothing gets skipped and everything gets recorded.
|
|
20
|
+
|
|
21
|
+
### The Core Insight
|
|
22
|
+
|
|
23
|
+
AI coding tools are powerful but undisciplined. Developers jump straight to
|
|
24
|
+
implementation, skip design, forget to review. Nova fixes this not by
|
|
25
|
+
**restricting** your AI skills (the old way), but by **orchestrating** them:
|
|
26
|
+
|
|
27
|
+
| Old Way (V1) | New Way (V2) |
|
|
28
|
+
|---|---|
|
|
29
|
+
| "You are forbidden to write code" (HTML comment) | "Your goal in this phase is to produce a design doc" |
|
|
30
|
+
| Replace real skills with thin 25-line templates | Call real skills (brainstorming, writing-plans, TDD...) in sequence |
|
|
31
|
+
| 5 stub platform adapters nobody uses | 1 adapter for Claude Code — the one you actually use |
|
|
32
|
+
| Remember slash commands for each phase | Just say "start designing" — or type `/nova` |
|
|
33
|
+
|
|
34
|
+
### How It Feels to Use
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
You: "帮我设计一下用户登录模块"
|
|
38
|
+
Nova: → Reads .nova.yaml, checks guards → Calls brainstorming → Calls writing-plans
|
|
39
|
+
→ Generates design.md + 6 tasks → Updates state → "Design complete."
|
|
40
|
+
|
|
41
|
+
You: "继续实现"
|
|
42
|
+
Nova: → Routes each task by type → implementation tasks run TDD → tests pass after each
|
|
43
|
+
→ Records traceId per task → "4/6 done. Continue?"
|
|
44
|
+
|
|
45
|
+
You: "审查一下代码"
|
|
46
|
+
Nova: → Parallel pipeline: code-review + security-review → Report with file:line references
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**No slash commands needed.** Nova understands phase context from `.nova.yaml` and
|
|
50
|
+
invokes the right skills automatically. If you prefer explicit control, `/nova`
|
|
51
|
+
gives you a one-glance overview and suggested next action.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Installation
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm install -g nova-workflow
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Quick Start
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
nova init # Initialize Nova in your project
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Then, inside Claude Code:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
/nova # See where you are and what's next
|
|
71
|
+
|
|
72
|
+
# Or just talk naturally — Nova detects the phase and acts accordingly:
|
|
73
|
+
"帮我做一个用户认证功能"
|
|
74
|
+
"继续实现"
|
|
75
|
+
"审查代码"
|
|
76
|
+
"回退到设计阶段,组件拆分需要调整"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## The Five Phases
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
propose ──→ design ──→ implement ──→ verify ──→ archive
|
|
85
|
+
│ │ │ │ │
|
|
86
|
+
│ brainstorming TDD skill ECC review CLI
|
|
87
|
+
│ writing-plans direct impl pipeline command
|
|
88
|
+
│
|
|
89
|
+
└── /nova-iterate ←── can roll back from any phase
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Each phase has a **clear goal** and a **structured output**. Phase guards prevent
|
|
93
|
+
skipping: you can't implement without a design. You can't verify without a build.
|
|
94
|
+
And you can always iterate back — real development is not a waterfall.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Commands
|
|
99
|
+
|
|
100
|
+
### Skill Commands (inside Claude Code)
|
|
101
|
+
|
|
102
|
+
| Command | What it does |
|
|
103
|
+
|---------|-------------|
|
|
104
|
+
| `/nova` | **One entry point.** Shows progress, suggests next action. |
|
|
105
|
+
| `/nova-propose` | Explore requirements via brainstorming → proposal.md |
|
|
106
|
+
| `/nova-design` | Explore architecture via brainstorming + writing-plans → design.md + YAML tasks |
|
|
107
|
+
| `/nova-implement` | Execute tasks with type routing (implementation / TDD / testing) |
|
|
108
|
+
| `/nova-verify` | Parallel pipeline: code review + security review via ECC skills |
|
|
109
|
+
| `/nova-iterate` | Roll back to a previous phase for iteration |
|
|
110
|
+
|
|
111
|
+
### CLI Commands (in terminal)
|
|
112
|
+
|
|
113
|
+
| Command | What it does |
|
|
114
|
+
|---------|-------------|
|
|
115
|
+
| `nova init` | Initialize Nova: creates `.nova.yaml`, installs skill files |
|
|
116
|
+
| `nova status` | Display phase progress and task completion |
|
|
117
|
+
| `nova archive` | Clean up and finalize |
|
|
118
|
+
| `nova context --task-id <id>` | Print structured TaskContext JSON for a task |
|
|
119
|
+
| `nova guard <from> <to>` | Validate a phase transition |
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Design Philosophy
|
|
124
|
+
|
|
125
|
+
### 1. Orchestrate, Don't Replace
|
|
126
|
+
|
|
127
|
+
Nova does not write a single line of content. It does not come with its own prompt
|
|
128
|
+
templates. It sequences **your** skills — Superpowers for methodology, ECC for
|
|
129
|
+
quality — through a disciplined workflow. Each skill runs at full capability.
|
|
130
|
+
|
|
131
|
+
### 2. Structured Handoff, Not Natural Language
|
|
132
|
+
|
|
133
|
+
The handoff between design and implementation is the moment where most AI workflows
|
|
134
|
+
break down. Nova solves this with `TaskContext` — a structured JSON contract:
|
|
135
|
+
|
|
136
|
+
```json
|
|
137
|
+
{
|
|
138
|
+
"taskId": "build-login",
|
|
139
|
+
"title": "Implement login endpoint",
|
|
140
|
+
"taskType": "implementation",
|
|
141
|
+
"input": {
|
|
142
|
+
"files": [{ "path": "src/login.ts", "action": "create" }],
|
|
143
|
+
"environment": { "language": "TypeScript", "framework": "Express.js" }
|
|
144
|
+
},
|
|
145
|
+
"acceptanceCriteria": ["Returns JWT on success"],
|
|
146
|
+
"guardConditions": { "requireReview": true, "requireTests": true }
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
No ambiguity. No "I think the designer meant...". The implement phase knows exactly
|
|
151
|
+
what to build, which files to touch, and what "done" looks like.
|
|
152
|
+
|
|
153
|
+
### 3. State Machine, Not Wishful Thinking
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
open ──[proposal done]──→ design ──[tasks ready]──→ build
|
|
157
|
+
build ──[all tasks done]──→ verify ──[review passed]──→ archive
|
|
158
|
+
build ←──[iterate]── design verify ←──[iterate]── build
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Forward transitions are **gated** — the guard system enforces preconditions.
|
|
162
|
+
Reverse transitions are **always allowed** — because iteration is real development.
|
|
163
|
+
|
|
164
|
+
### 4. Every Invocation, Tracked
|
|
165
|
+
|
|
166
|
+
Every AI call generates a `traceId`. Every task records its status, output
|
|
167
|
+
artifacts, and completion time. The `.nova.yaml` state file is the single source
|
|
168
|
+
of truth — atomic writes, mutex-guarded, crash-safe.
|
|
169
|
+
|
|
170
|
+
### 5. Convention, Not Coercion
|
|
171
|
+
|
|
172
|
+
Role separation comes from **phase structure**, not from fake security boundaries.
|
|
173
|
+
The design phase says "your goal is a design doc" — that's enough. No HTML comments
|
|
174
|
+
pretending to be access control. No skill neutering. Just clear goals and a state
|
|
175
|
+
machine that keeps you honest.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Architecture
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
src/
|
|
183
|
+
├── cli/ # Terminal commands (5 commands)
|
|
184
|
+
│ ├── index.ts # init, status, archive, context, guard
|
|
185
|
+
│ ├── ui.ts # Spinners, colors
|
|
186
|
+
│ └── error-handler.ts # Unified error boundary
|
|
187
|
+
├── cli-core/ # Business logic
|
|
188
|
+
│ ├── types.ts # Core interfaces (TaskContext, NovaState, etc.)
|
|
189
|
+
│ ├── state.ts # Atomic .nova.yaml state manager (mutex + temp/rename)
|
|
190
|
+
│ ├── guard.ts # Phase transition rule engine (forward + rollback)
|
|
191
|
+
│ ├── dispatcher.ts # Single-agent execution with retry & traceId
|
|
192
|
+
│ ├── context-generator.ts # Task → TaskContext JSON mapper (11 languages)
|
|
193
|
+
│ ├── pipeline.ts # Multi-stage parallel orchestrator
|
|
194
|
+
│ ├── platform-client.ts # Claude Code client
|
|
195
|
+
│ ├── init-manager.ts # Init flow with transactional rollback
|
|
196
|
+
│ ├── project-detect.ts # Auto-detect project type
|
|
197
|
+
│ └── adapters/ # Claude Code command generator
|
|
198
|
+
└── templates/ # Document templates (proposal.md, design.md)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## State File
|
|
204
|
+
|
|
205
|
+
Everything Nova knows lives in `.nova.yaml`:
|
|
206
|
+
|
|
207
|
+
```yaml
|
|
208
|
+
version: 2
|
|
209
|
+
project: my-app
|
|
210
|
+
environment: [claude-code]
|
|
211
|
+
phases:
|
|
212
|
+
open: { status: done, proposal: docs/proposals/proposal.md }
|
|
213
|
+
design: { status: done, designDoc: docs/designs/design.md, tasks: [...] }
|
|
214
|
+
build: { status: in-progress, tasks: { task-1: { status: done, traceId: nova-xxx } } }
|
|
215
|
+
verify: { status: pending }
|
|
216
|
+
archive: { status: pending }
|
|
217
|
+
metadata:
|
|
218
|
+
stateVersion: 12
|
|
219
|
+
lastModified: "2026-05-28T12:00:00.000Z"
|
|
220
|
+
history:
|
|
221
|
+
- { version: 8, change: "Task login-impl completed" }
|
|
222
|
+
- { version: 10, change: "Iterated build→design: component split needs rethinking" }
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Testing
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
Test Suites: 7 passed
|
|
231
|
+
Tests: 41 passed
|
|
232
|
+
|
|
233
|
+
✓ state-manager — load / atomic update / getTask / phase duration
|
|
234
|
+
✓ guard — 4 forward + 4 rollback transitions
|
|
235
|
+
✓ dispatcher — success / retry / max retries
|
|
236
|
+
✓ context-generator — task → TaskContext mapping / 11 languages
|
|
237
|
+
✓ pipeline — success / fail / dependsOn / continue
|
|
238
|
+
✓ project-detect — 11 project type detection
|
|
239
|
+
✓ init-manager — fresh init / force re-init / dir creation / ECC install / templates
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## License
|
|
245
|
+
|
|
246
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const archiveCommand: (...args: any[]) => Promise<void>;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.archiveCommand = void 0;
|
|
40
|
+
const fs = __importStar(require("fs/promises"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
43
|
+
const ui_1 = require("../ui");
|
|
44
|
+
const state_1 = require("../../cli-core/state");
|
|
45
|
+
const guard_1 = require("../../cli-core/guard");
|
|
46
|
+
const error_handler_1 = require("../error-handler");
|
|
47
|
+
exports.archiveCommand = (0, error_handler_1.withErrorHandling)(async (options) => {
|
|
48
|
+
if (options.rollback) {
|
|
49
|
+
const { confirm } = await inquirer_1.default.prompt([{
|
|
50
|
+
type: 'confirm',
|
|
51
|
+
name: 'confirm',
|
|
52
|
+
message: 'Rollback archive phase: reset to pending. Continue?',
|
|
53
|
+
default: false,
|
|
54
|
+
}]);
|
|
55
|
+
if (!confirm) {
|
|
56
|
+
ui_1.ui.info('Cancelled.');
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
await state_1.StateManager.update((s) => {
|
|
60
|
+
s.phases.archive = { status: 'pending' };
|
|
61
|
+
return s;
|
|
62
|
+
});
|
|
63
|
+
ui_1.ui.success('Archive phase rolled back to pending.');
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const passed = await (0, guard_1.guardPhaseTransition)('verify', 'archive');
|
|
67
|
+
if (!passed) {
|
|
68
|
+
ui_1.ui.error('Cannot archive. Complete the verify phase first.');
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
const state = await state_1.StateManager.load();
|
|
72
|
+
const cwd = process.cwd();
|
|
73
|
+
// 合并规格到 docs/specs/ 归档
|
|
74
|
+
const specsDir = path.join(cwd, 'docs', 'specs');
|
|
75
|
+
await fs.mkdir(specsDir, { recursive: true });
|
|
76
|
+
let mergedCount = 0;
|
|
77
|
+
// 归档 proposal
|
|
78
|
+
const proposalSrc = state.phases.open?.proposal;
|
|
79
|
+
if (proposalSrc) {
|
|
80
|
+
const src = path.join(cwd, proposalSrc);
|
|
81
|
+
try {
|
|
82
|
+
const content = await fs.readFile(src, 'utf-8');
|
|
83
|
+
const dest = path.join(specsDir, `proposal-${Date.now()}.md`);
|
|
84
|
+
await fs.writeFile(dest, content);
|
|
85
|
+
mergedCount++;
|
|
86
|
+
}
|
|
87
|
+
catch { /* 源文件不存在则跳过 */ }
|
|
88
|
+
}
|
|
89
|
+
// 归档 design
|
|
90
|
+
const designSrc = state.phases.design?.designDoc;
|
|
91
|
+
if (designSrc) {
|
|
92
|
+
const src = path.join(cwd, designSrc);
|
|
93
|
+
try {
|
|
94
|
+
const content = await fs.readFile(src, 'utf-8');
|
|
95
|
+
const dest = path.join(specsDir, `design-${Date.now()}.md`);
|
|
96
|
+
await fs.writeFile(dest, content);
|
|
97
|
+
mergedCount++;
|
|
98
|
+
}
|
|
99
|
+
catch { /* 源文件不存在则跳过 */ }
|
|
100
|
+
}
|
|
101
|
+
// 归档 verify 结果
|
|
102
|
+
if (state.phases.verify?.pipelineResult) {
|
|
103
|
+
const dest = path.join(specsDir, `verify-result-${Date.now()}.json`);
|
|
104
|
+
await fs.writeFile(dest, JSON.stringify(state.phases.verify.pipelineResult, null, 2));
|
|
105
|
+
mergedCount++;
|
|
106
|
+
}
|
|
107
|
+
// 清理临时文件
|
|
108
|
+
const contextsDir = path.join(cwd, '.nova', 'contexts');
|
|
109
|
+
try {
|
|
110
|
+
const files = await fs.readdir(contextsDir);
|
|
111
|
+
for (const f of files)
|
|
112
|
+
await fs.unlink(path.join(contextsDir, f));
|
|
113
|
+
}
|
|
114
|
+
catch { /* nothing to clean */ }
|
|
115
|
+
await state_1.StateManager.setPhaseField('archive', 'status', 'done');
|
|
116
|
+
ui_1.ui.success('Project archived. All phases complete.');
|
|
117
|
+
ui_1.ui.info(`Merged ${mergedCount} artifact(s) to docs/specs/.`);
|
|
118
|
+
ui_1.ui.info('Temporary context files cleaned up.');
|
|
119
|
+
});
|
|
120
|
+
//# sourceMappingURL=archive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive.js","sourceRoot":"","sources":["../../../src/cli/commands/archive.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const contextCommand: (...args: any[]) => Promise<void>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.contextCommand = void 0;
|
|
4
|
+
const ui_1 = require("../ui");
|
|
5
|
+
const state_1 = require("../../cli-core/state");
|
|
6
|
+
const context_generator_1 = require("../../cli-core/context-generator");
|
|
7
|
+
const error_handler_1 = require("../error-handler");
|
|
8
|
+
exports.contextCommand = (0, error_handler_1.withErrorHandling)(async (options) => {
|
|
9
|
+
if (!options.taskId) {
|
|
10
|
+
ui_1.ui.error('--task-id is required.');
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
const state = await state_1.StateManager.load();
|
|
14
|
+
const tasks = state.phases.design?.tasks || [];
|
|
15
|
+
const task = tasks.find((t) => t.id === options.taskId);
|
|
16
|
+
if (!task) {
|
|
17
|
+
ui_1.ui.error(`Task "${options.taskId}" not found in design phase.`);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
const context = await context_generator_1.ContextGenerator.generateFromTask(task);
|
|
21
|
+
console.log(JSON.stringify(context, null, 2));
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/cli/commands/context.ts"],"names":[],"mappings":";;;AAAA,8BAA2B;AAC3B,gDAAoD;AACpD,wEAAoE;AACpE,oDAAqD;AAExC,QAAA,cAAc,GAAG,IAAA,iCAAiB,EAAC,KAAK,EAAE,OAA4B,EAAE,EAAE;IACrF,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,OAAE,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,oBAAY,CAAC,IAAI,EAAE,CAAC;IACxC,MAAM,KAAK,GAAU,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC;IACtD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAExD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAE,CAAC,KAAK,CAAC,SAAS,OAAO,CAAC,MAAM,8BAA8B,CAAC,CAAC;QAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,oCAAgB,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC9D,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const guardCommand: (...args: any[]) => Promise<void>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.guardCommand = void 0;
|
|
4
|
+
const ui_1 = require("../ui");
|
|
5
|
+
const guard_1 = require("../../cli-core/guard");
|
|
6
|
+
const error_handler_1 = require("../error-handler");
|
|
7
|
+
exports.guardCommand = (0, error_handler_1.withErrorHandling)(async (from, to) => {
|
|
8
|
+
if (!from || !to) {
|
|
9
|
+
ui_1.ui.error('Usage: nova guard <from> <to>');
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
const passed = await (0, guard_1.guardPhaseTransition)(from, to);
|
|
13
|
+
if (passed) {
|
|
14
|
+
ui_1.ui.success(`Guard passed: ${from} → ${to}`);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
ui_1.ui.error(`Guard failed: ${from} → ${to}`);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
//# sourceMappingURL=guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../../src/cli/commands/guard.ts"],"names":[],"mappings":";;;AAAA,8BAA2B;AAC3B,gDAA4D;AAC5D,oDAAqD;AAExC,QAAA,YAAY,GAAG,IAAA,iCAAiB,EAAC,KAAK,EAAE,IAAY,EAAE,EAAU,EAAE,EAAE;IAC/E,IAAI,CAAC,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;QACjB,OAAE,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,IAAA,4BAAoB,EAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACpD,IAAI,MAAM,EAAE,CAAC;QACX,OAAE,CAAC,OAAO,CAAC,iBAAiB,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;IAC9C,CAAC;SAAM,CAAC;QACN,OAAE,CAAC,KAAK,CAAC,iBAAiB,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;QAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const initCommand: (...args: any[]) => Promise<void>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.initCommand = void 0;
|
|
4
|
+
const ui_1 = require("../ui");
|
|
5
|
+
const init_manager_1 = require("../../cli-core/init-manager");
|
|
6
|
+
const error_handler_1 = require("../error-handler");
|
|
7
|
+
exports.initCommand = (0, error_handler_1.withErrorHandling)(async (options) => {
|
|
8
|
+
ui_1.ui.step('Welcome to Nova! Initializing your project...');
|
|
9
|
+
const manager = new init_manager_1.InitManager(process.cwd(), {
|
|
10
|
+
eccPath: options.withEcc,
|
|
11
|
+
force: options.force
|
|
12
|
+
});
|
|
13
|
+
try {
|
|
14
|
+
await manager.run();
|
|
15
|
+
ui_1.ui.success('Nova initialized successfully!');
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
ui_1.ui.error(`Initialization failed: ${err.message}`);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":";;;AAAA,8BAA2B;AAC3B,8DAA0D;AAC1D,oDAAqD;AAExC,QAAA,WAAW,GAAG,IAAA,iCAAiB,EAAC,KAAK,EAAE,OAA8C,EAAE,EAAE;IACpG,OAAE,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,IAAI,0BAAW,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE;QAC7C,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,KAAK,EAAE,OAAO,CAAC,KAAK;KACrB,CAAC,CAAC;IACH,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,GAAG,EAAE,CAAC;QACpB,OAAE,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAE,CAAC,KAAK,CAAC,0BAA0B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const statusCommand: (...args: any[]) => Promise<void>;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.statusCommand = void 0;
|
|
4
|
+
const ui_1 = require("../ui");
|
|
5
|
+
const state_1 = require("../../cli-core/state");
|
|
6
|
+
const error_handler_1 = require("../error-handler");
|
|
7
|
+
const PHASE_ORDER = ['open', 'design', 'build', 'verify', 'archive'];
|
|
8
|
+
const PHASE_LABEL = {
|
|
9
|
+
open: 'propose',
|
|
10
|
+
design: 'design',
|
|
11
|
+
build: 'implement',
|
|
12
|
+
verify: 'verify',
|
|
13
|
+
archive: 'archive',
|
|
14
|
+
};
|
|
15
|
+
const STATUS_ICON = {
|
|
16
|
+
done: '✅',
|
|
17
|
+
'in-progress': '🔄',
|
|
18
|
+
pending: '⬜',
|
|
19
|
+
};
|
|
20
|
+
// 超时阈值(毫秒)
|
|
21
|
+
const STUCK_THRESHOLDS = {
|
|
22
|
+
open: 30 * 60 * 1000, // 30 min
|
|
23
|
+
design: 60 * 60 * 1000, // 1 hour
|
|
24
|
+
build: 120 * 60 * 1000, // 2 hours
|
|
25
|
+
verify: 30 * 60 * 1000, // 30 min
|
|
26
|
+
archive: 15 * 60 * 1000, // 15 min
|
|
27
|
+
};
|
|
28
|
+
const STUCK_MESSAGE = {
|
|
29
|
+
open: 'Proposal has been in progress for a while. Consider running "nova propose --done" or "--rollback".',
|
|
30
|
+
design: 'Design has been in progress for a while. Consider running "nova design --done" or "--rollback".',
|
|
31
|
+
build: 'Implementation has been in progress for a while. Check task status and consider "--rollback" if stuck.',
|
|
32
|
+
verify: 'Verification has been in progress for a while. Consider running "nova verify --rollback" if needed.',
|
|
33
|
+
archive: 'Archive has been in progress. Run "nova archive --done" to finish or "--rollback" to reset.',
|
|
34
|
+
};
|
|
35
|
+
exports.statusCommand = (0, error_handler_1.withErrorHandling)(async () => {
|
|
36
|
+
const state = await state_1.StateManager.load();
|
|
37
|
+
ui_1.ui.step(`Project: ${state.project}`);
|
|
38
|
+
ui_1.ui.info(`Environment: ${state.environment.join(', ') || '(none)'}`);
|
|
39
|
+
ui_1.ui.info('');
|
|
40
|
+
const warnings = [];
|
|
41
|
+
for (const phase of PHASE_ORDER) {
|
|
42
|
+
const data = state.phases[phase] || {};
|
|
43
|
+
const status = data.status || 'pending';
|
|
44
|
+
const icon = STATUS_ICON[status] || '⬜';
|
|
45
|
+
const label = PHASE_LABEL[phase] || phase;
|
|
46
|
+
const extra = [];
|
|
47
|
+
// 耗时统计
|
|
48
|
+
const duration = state_1.StateManager.getPhaseDuration(data);
|
|
49
|
+
if (duration)
|
|
50
|
+
extra.push(duration);
|
|
51
|
+
if (phase === 'build' && data.tasks) {
|
|
52
|
+
const entries = Object.entries(data.tasks);
|
|
53
|
+
const done = entries.filter(([, t]) => t.status === 'done').length;
|
|
54
|
+
extra.push(`tasks: ${done}/${entries.length} done`);
|
|
55
|
+
}
|
|
56
|
+
ui_1.ui.info(` ${icon} ${label}: ${status}${extra.length ? ` (${extra.join(', ')})` : ''}`);
|
|
57
|
+
// 卡住检测
|
|
58
|
+
if (status === 'in-progress' && data.startedAt) {
|
|
59
|
+
const elapsed = Date.now() - new Date(data.startedAt).getTime();
|
|
60
|
+
const threshold = STUCK_THRESHOLDS[phase] || 60 * 60 * 1000;
|
|
61
|
+
if (elapsed > threshold) {
|
|
62
|
+
warnings.push(`${label}: ${STUCK_MESSAGE[phase]}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (warnings.length > 0) {
|
|
67
|
+
ui_1.ui.warn('');
|
|
68
|
+
for (const w of warnings)
|
|
69
|
+
ui_1.ui.warn(w);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function withErrorHandling(fn: (...args: any[]) => Promise<void>): (...args: any[]) => Promise<void>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withErrorHandling = withErrorHandling;
|
|
4
|
+
const ui_1 = require("./ui");
|
|
5
|
+
function withErrorHandling(fn) {
|
|
6
|
+
return async (...args) => {
|
|
7
|
+
try {
|
|
8
|
+
await fn(...args);
|
|
9
|
+
}
|
|
10
|
+
catch (err) {
|
|
11
|
+
ui_1.ui.error(err.message || 'Unknown error');
|
|
12
|
+
if (process.env.DEBUG)
|
|
13
|
+
console.error(err);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=error-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/cli/error-handler.ts"],"names":[],"mappings":";;AAEA,8CAUC;AAZD,6BAA0B;AAE1B,SAAgB,iBAAiB,CAAC,EAAqC;IACrE,OAAO,KAAK,EAAE,GAAG,IAAW,EAAE,EAAE;QAC9B,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QACpB,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAE,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,IAAI,eAAe,CAAC,CAAC;YACzC,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK;gBAAE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const commander_1 = require("commander");
|
|
5
|
+
const init_1 = require("./commands/init");
|
|
6
|
+
const archive_1 = require("./commands/archive");
|
|
7
|
+
const status_1 = require("./commands/status");
|
|
8
|
+
const context_1 = require("./commands/context");
|
|
9
|
+
const guard_1 = require("./commands/guard");
|
|
10
|
+
const program = new commander_1.Command();
|
|
11
|
+
program
|
|
12
|
+
.name('nova')
|
|
13
|
+
.description('Nova: AI workflow orchestration — init, status, archive')
|
|
14
|
+
.version('0.1.0');
|
|
15
|
+
program
|
|
16
|
+
.command('init')
|
|
17
|
+
.option('--with-ecc <path>', 'Path to ECC skills')
|
|
18
|
+
.option('--force', 'Overwrite existing configuration')
|
|
19
|
+
.action(init_1.initCommand);
|
|
20
|
+
program
|
|
21
|
+
.command('archive')
|
|
22
|
+
.option('--rollback', 'Rollback archive phase to pending')
|
|
23
|
+
.action(archive_1.archiveCommand);
|
|
24
|
+
program
|
|
25
|
+
.command('status')
|
|
26
|
+
.action(status_1.statusCommand);
|
|
27
|
+
program
|
|
28
|
+
.command('context')
|
|
29
|
+
.requiredOption('--task-id <id>', 'Task identifier')
|
|
30
|
+
.action(context_1.contextCommand);
|
|
31
|
+
program
|
|
32
|
+
.command('guard <from> <to>')
|
|
33
|
+
.action(guard_1.guardCommand);
|
|
34
|
+
program.parse(process.argv);
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,0CAA8C;AAC9C,gDAAoD;AACpD,8CAAkD;AAClD,gDAAoD;AACpD,4CAAgD;AAEhD,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAC9B,OAAO;KACJ,IAAI,CAAC,MAAM,CAAC;KACZ,WAAW,CAAC,yDAAyD,CAAC;KACtE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,MAAM,CAAC,mBAAmB,EAAE,oBAAoB,CAAC;KACjD,MAAM,CAAC,SAAS,EAAE,kCAAkC,CAAC;KACrD,MAAM,CAAC,kBAAW,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,MAAM,CAAC,YAAY,EAAE,mCAAmC,CAAC;KACzD,MAAM,CAAC,wBAAc,CAAC,CAAC;AAE1B,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,MAAM,CAAC,sBAAa,CAAC,CAAC;AAEzB,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,cAAc,CAAC,gBAAgB,EAAE,iBAAiB,CAAC;KACnD,MAAM,CAAC,wBAAc,CAAC,CAAC;AAE1B,OAAO;KACJ,OAAO,CAAC,mBAAmB,CAAC;KAC5B,MAAM,CAAC,oBAAY,CAAC,CAAC;AAExB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
|
package/dist/cli/ui.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Ora } from 'ora';
|
|
2
|
+
export declare const ui: {
|
|
3
|
+
spinner: (text: string) => Ora;
|
|
4
|
+
success: (text: string) => void;
|
|
5
|
+
error: (text: string) => void;
|
|
6
|
+
warn: (text: string) => void;
|
|
7
|
+
info: (text: string) => void;
|
|
8
|
+
step: (text: string) => void;
|
|
9
|
+
guardResult: (passed: boolean, msg: string) => void;
|
|
10
|
+
};
|
package/dist/cli/ui.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ui = void 0;
|
|
7
|
+
const ora_1 = __importDefault(require("ora"));
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
exports.ui = {
|
|
10
|
+
spinner: (text) => (0, ora_1.default)(text).start(),
|
|
11
|
+
success: (text) => console.log(chalk_1.default.green('✔ ' + text)),
|
|
12
|
+
error: (text) => console.error(chalk_1.default.red('✖ ' + text)),
|
|
13
|
+
warn: (text) => console.warn(chalk_1.default.yellow('⚠ ' + text)),
|
|
14
|
+
info: (text) => console.log(chalk_1.default.blue('ℹ ' + text)),
|
|
15
|
+
step: (text) => console.log(chalk_1.default.cyan('● ' + text)),
|
|
16
|
+
guardResult: (passed, msg) => {
|
|
17
|
+
const icon = passed ? chalk_1.default.green('✅') : chalk_1.default.red('❌');
|
|
18
|
+
console.log(` ${icon} ${msg}`);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=ui.js.map
|