@kamilmarzynski/scifi 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/LICENSE +21 -0
- package/README.md +232 -0
- package/dist/skills/sf-bug/manifest.d.ts +2 -0
- package/dist/skills/sf-bug/manifest.js +6 -0
- package/dist/skills/sf-bug/manifest.js.map +1 -0
- package/dist/skills/sf-change/manifest.d.ts +2 -0
- package/dist/skills/sf-change/manifest.js +6 -0
- package/dist/skills/sf-change/manifest.js.map +1 -0
- package/dist/skills/sf-code-review/manifest.d.ts +2 -0
- package/dist/skills/sf-code-review/manifest.js +5 -0
- package/dist/skills/sf-code-review/manifest.js.map +1 -0
- package/dist/skills/sf-continue/manifest.d.ts +2 -0
- package/dist/skills/sf-continue/manifest.js +6 -0
- package/dist/skills/sf-continue/manifest.js.map +1 -0
- package/dist/skills/sf-feature/manifest.d.ts +2 -0
- package/dist/skills/sf-feature/manifest.js +6 -0
- package/dist/skills/sf-feature/manifest.js.map +1 -0
- package/dist/skills/sf-fix/manifest.d.ts +2 -0
- package/dist/skills/sf-fix/manifest.js +6 -0
- package/dist/skills/sf-fix/manifest.js.map +1 -0
- package/dist/skills/sf-handover/manifest.d.ts +2 -0
- package/dist/skills/sf-handover/manifest.js +5 -0
- package/dist/skills/sf-handover/manifest.js.map +1 -0
- package/dist/skills/sf-implement/manifest.d.ts +2 -0
- package/dist/skills/sf-implement/manifest.js +6 -0
- package/dist/skills/sf-implement/manifest.js.map +1 -0
- package/dist/skills/sf-plan/manifest.d.ts +2 -0
- package/dist/skills/sf-plan/manifest.js +6 -0
- package/dist/skills/sf-plan/manifest.js.map +1 -0
- package/dist/skills/sf-plan-review/manifest.d.ts +2 -0
- package/dist/skills/sf-plan-review/manifest.js +5 -0
- package/dist/skills/sf-plan-review/manifest.js.map +1 -0
- package/dist/skills/sf-receiving-review/manifest.d.ts +2 -0
- package/dist/skills/sf-receiving-review/manifest.js +5 -0
- package/dist/skills/sf-receiving-review/manifest.js.map +1 -0
- package/dist/skills/sf-spec-review/manifest.d.ts +2 -0
- package/dist/skills/sf-spec-review/manifest.js +5 -0
- package/dist/skills/sf-spec-review/manifest.js.map +1 -0
- package/dist/skills/sf-tdd/manifest.d.ts +2 -0
- package/dist/skills/sf-tdd/manifest.js +5 -0
- package/dist/skills/sf-tdd/manifest.js.map +1 -0
- package/dist/skills/sf-verification/manifest.d.ts +2 -0
- package/dist/skills/sf-verification/manifest.js +5 -0
- package/dist/skills/sf-verification/manifest.js.map +1 -0
- package/dist/src/cli/commands/bug.d.ts +2 -0
- package/dist/src/cli/commands/bug.js +58 -0
- package/dist/src/cli/commands/bug.js.map +1 -0
- package/dist/src/cli/commands/finish.d.ts +2 -0
- package/dist/src/cli/commands/finish.js +43 -0
- package/dist/src/cli/commands/finish.js.map +1 -0
- package/dist/src/cli/commands/fix.d.ts +2 -0
- package/dist/src/cli/commands/fix.js +60 -0
- package/dist/src/cli/commands/fix.js.map +1 -0
- package/dist/src/cli/commands/init.d.ts +2 -0
- package/dist/src/cli/commands/init.js +92 -0
- package/dist/src/cli/commands/init.js.map +1 -0
- package/dist/src/cli/commands/list.d.ts +2 -0
- package/dist/src/cli/commands/list.js +52 -0
- package/dist/src/cli/commands/list.js.map +1 -0
- package/dist/src/cli/commands/plan-ready.d.ts +2 -0
- package/dist/src/cli/commands/plan-ready.js +27 -0
- package/dist/src/cli/commands/plan-ready.js.map +1 -0
- package/dist/src/cli/commands/plan.d.ts +2 -0
- package/dist/src/cli/commands/plan.js +43 -0
- package/dist/src/cli/commands/plan.js.map +1 -0
- package/dist/src/cli/commands/spec-ready.d.ts +2 -0
- package/dist/src/cli/commands/spec-ready.js +27 -0
- package/dist/src/cli/commands/spec-ready.js.map +1 -0
- package/dist/src/cli/commands/spec.d.ts +2 -0
- package/dist/src/cli/commands/spec.js +46 -0
- package/dist/src/cli/commands/spec.js.map +1 -0
- package/dist/src/cli/commands/start.d.ts +2 -0
- package/dist/src/cli/commands/start.js +27 -0
- package/dist/src/cli/commands/start.js.map +1 -0
- package/dist/src/cli/commands/status.d.ts +2 -0
- package/dist/src/cli/commands/status.js +62 -0
- package/dist/src/cli/commands/status.js.map +1 -0
- package/dist/src/cli/commands/task.d.ts +2 -0
- package/dist/src/cli/commands/task.js +64 -0
- package/dist/src/cli/commands/task.js.map +1 -0
- package/dist/src/cli/commands/worktree.d.ts +2 -0
- package/dist/src/cli/commands/worktree.js +33 -0
- package/dist/src/cli/commands/worktree.js.map +1 -0
- package/dist/src/cli/index.d.ts +3 -0
- package/dist/src/cli/index.js +106 -0
- package/dist/src/cli/index.js.map +1 -0
- package/dist/src/core/bugs/create.d.ts +13 -0
- package/dist/src/core/bugs/create.js +28 -0
- package/dist/src/core/bugs/create.js.map +1 -0
- package/dist/src/core/bugs/frontmatter.d.ts +7 -0
- package/dist/src/core/bugs/frontmatter.js +65 -0
- package/dist/src/core/bugs/frontmatter.js.map +1 -0
- package/dist/src/core/bugs/id.d.ts +1 -0
- package/dist/src/core/bugs/id.js +4 -0
- package/dist/src/core/bugs/id.js.map +1 -0
- package/dist/src/core/bugs/paths.d.ts +2 -0
- package/dist/src/core/bugs/paths.js +8 -0
- package/dist/src/core/bugs/paths.js.map +1 -0
- package/dist/src/core/bugs/types.d.ts +12 -0
- package/dist/src/core/bugs/types.js +3 -0
- package/dist/src/core/bugs/types.js.map +1 -0
- package/dist/src/core/fixes/create.d.ts +11 -0
- package/dist/src/core/fixes/create.js +43 -0
- package/dist/src/core/fixes/create.js.map +1 -0
- package/dist/src/core/fixes/frontmatter.d.ts +7 -0
- package/dist/src/core/fixes/frontmatter.js +50 -0
- package/dist/src/core/fixes/frontmatter.js.map +1 -0
- package/dist/src/core/fixes/id.d.ts +1 -0
- package/dist/src/core/fixes/id.js +4 -0
- package/dist/src/core/fixes/id.js.map +1 -0
- package/dist/src/core/fixes/list.d.ts +8 -0
- package/dist/src/core/fixes/list.js +43 -0
- package/dist/src/core/fixes/list.js.map +1 -0
- package/dist/src/core/fixes/paths.d.ts +2 -0
- package/dist/src/core/fixes/paths.js +9 -0
- package/dist/src/core/fixes/paths.js.map +1 -0
- package/dist/src/core/fixes/transition.d.ts +9 -0
- package/dist/src/core/fixes/transition.js +26 -0
- package/dist/src/core/fixes/transition.js.map +1 -0
- package/dist/src/core/fixes/types.d.ts +9 -0
- package/dist/src/core/fixes/types.js +2 -0
- package/dist/src/core/fixes/types.js.map +1 -0
- package/dist/src/core/init/config.d.ts +6 -0
- package/dist/src/core/init/config.js +18 -0
- package/dist/src/core/init/config.js.map +1 -0
- package/dist/src/core/init/install-skills.d.ts +8 -0
- package/dist/src/core/init/install-skills.js +14 -0
- package/dist/src/core/init/install-skills.js.map +1 -0
- package/dist/src/core/init/prompt-harness.d.ts +8 -0
- package/dist/src/core/init/prompt-harness.js +19 -0
- package/dist/src/core/init/prompt-harness.js.map +1 -0
- package/dist/src/core/init/scaffold.d.ts +5 -0
- package/dist/src/core/init/scaffold.js +91 -0
- package/dist/src/core/init/scaffold.js.map +1 -0
- package/dist/src/core/init/types.d.ts +5 -0
- package/dist/src/core/init/types.js +2 -0
- package/dist/src/core/init/types.js.map +1 -0
- package/dist/src/core/output/emit.d.ts +8 -0
- package/dist/src/core/output/emit.js +50 -0
- package/dist/src/core/output/emit.js.map +1 -0
- package/dist/src/core/output/errors.d.ts +14 -0
- package/dist/src/core/output/errors.js +36 -0
- package/dist/src/core/output/errors.js.map +1 -0
- package/dist/src/core/output/index.d.ts +4 -0
- package/dist/src/core/output/index.js +4 -0
- package/dist/src/core/output/index.js.map +1 -0
- package/dist/src/core/output/tty.d.ts +1 -0
- package/dist/src/core/output/tty.js +4 -0
- package/dist/src/core/output/tty.js.map +1 -0
- package/dist/src/core/package-root.d.ts +1 -0
- package/dist/src/core/package-root.js +18 -0
- package/dist/src/core/package-root.js.map +1 -0
- package/dist/src/core/skills/catalog.d.ts +6 -0
- package/dist/src/core/skills/catalog.js +69 -0
- package/dist/src/core/skills/catalog.js.map +1 -0
- package/dist/src/core/skills/harness/adapter.d.ts +15 -0
- package/dist/src/core/skills/harness/adapter.js +31 -0
- package/dist/src/core/skills/harness/adapter.js.map +1 -0
- package/dist/src/core/skills/harness/claude-code.d.ts +2 -0
- package/dist/src/core/skills/harness/claude-code.js +37 -0
- package/dist/src/core/skills/harness/claude-code.js.map +1 -0
- package/dist/src/core/skills/harness/register-defaults.d.ts +1 -0
- package/dist/src/core/skills/harness/register-defaults.js +4 -0
- package/dist/src/core/skills/harness/register-defaults.js.map +1 -0
- package/dist/src/core/skills/harness/registry.d.ts +3 -0
- package/dist/src/core/skills/harness/registry.js +22 -0
- package/dist/src/core/skills/harness/registry.js.map +1 -0
- package/dist/src/core/skills/types.d.ts +18 -0
- package/dist/src/core/skills/types.js +9 -0
- package/dist/src/core/skills/types.js.map +1 -0
- package/dist/src/core/slugify.d.ts +2 -0
- package/dist/src/core/slugify.js +13 -0
- package/dist/src/core/slugify.js.map +1 -0
- package/dist/src/core/specs/create.d.ts +11 -0
- package/dist/src/core/specs/create.js +35 -0
- package/dist/src/core/specs/create.js.map +1 -0
- package/dist/src/core/specs/id.d.ts +1 -0
- package/dist/src/core/specs/id.js +4 -0
- package/dist/src/core/specs/id.js.map +1 -0
- package/dist/src/core/specs/lifecycle.d.ts +17 -0
- package/dist/src/core/specs/lifecycle.js +97 -0
- package/dist/src/core/specs/lifecycle.js.map +1 -0
- package/dist/src/core/specs/list.d.ts +6 -0
- package/dist/src/core/specs/list.js +43 -0
- package/dist/src/core/specs/list.js.map +1 -0
- package/dist/src/core/specs/metadata.d.ts +3 -0
- package/dist/src/core/specs/metadata.js +13 -0
- package/dist/src/core/specs/metadata.js.map +1 -0
- package/dist/src/core/specs/paths.d.ts +3 -0
- package/dist/src/core/specs/paths.js +13 -0
- package/dist/src/core/specs/paths.js.map +1 -0
- package/dist/src/core/specs/plan-session.d.ts +18 -0
- package/dist/src/core/specs/plan-session.js +24 -0
- package/dist/src/core/specs/plan-session.js.map +1 -0
- package/dist/src/core/specs/transition.d.ts +8 -0
- package/dist/src/core/specs/transition.js +33 -0
- package/dist/src/core/specs/transition.js.map +1 -0
- package/dist/src/core/specs/types.d.ts +17 -0
- package/dist/src/core/specs/types.js +8 -0
- package/dist/src/core/specs/types.js.map +1 -0
- package/dist/src/core/specs/worktree.d.ts +10 -0
- package/dist/src/core/specs/worktree.js +32 -0
- package/dist/src/core/specs/worktree.js.map +1 -0
- package/dist/src/core/tasks/frontmatter.d.ts +7 -0
- package/dist/src/core/tasks/frontmatter.js +53 -0
- package/dist/src/core/tasks/frontmatter.js.map +1 -0
- package/dist/src/core/tasks/list.d.ts +2 -0
- package/dist/src/core/tasks/list.js +18 -0
- package/dist/src/core/tasks/list.js.map +1 -0
- package/dist/src/core/tasks/paths.d.ts +2 -0
- package/dist/src/core/tasks/paths.js +11 -0
- package/dist/src/core/tasks/paths.js.map +1 -0
- package/dist/src/core/tasks/transition.d.ts +8 -0
- package/dist/src/core/tasks/transition.js +30 -0
- package/dist/src/core/tasks/transition.js.map +1 -0
- package/dist/src/core/tasks/types.d.ts +8 -0
- package/dist/src/core/tasks/types.js +2 -0
- package/dist/src/core/tasks/types.js.map +1 -0
- package/package.json +67 -0
- package/skills/sf-bug/DISPATCH-CODE-REVIEW.md +22 -0
- package/skills/sf-bug/body.md +117 -0
- package/skills/sf-bug/manifest.ts +8 -0
- package/skills/sf-change/body.md +178 -0
- package/skills/sf-change/manifest.ts +8 -0
- package/skills/sf-code-review/body.md +155 -0
- package/skills/sf-code-review/manifest.ts +7 -0
- package/skills/sf-continue/body.md +90 -0
- package/skills/sf-continue/manifest.ts +8 -0
- package/skills/sf-feature/ADR-TEMPLATE.md +16 -0
- package/skills/sf-feature/DISPATCH-SPEC-REVIEW.md +16 -0
- package/skills/sf-feature/SPEC-TEMPLATE.md +37 -0
- package/skills/sf-feature/body.md +145 -0
- package/skills/sf-feature/manifest.ts +8 -0
- package/skills/sf-fix/DISPATCH-CODE-REVIEW.md +25 -0
- package/skills/sf-fix/body.md +174 -0
- package/skills/sf-fix/manifest.ts +8 -0
- package/skills/sf-handover/body.md +67 -0
- package/skills/sf-handover/manifest.ts +7 -0
- package/skills/sf-implement/DISPATCH-CODE-REVIEW.md +19 -0
- package/skills/sf-implement/DISPATCH-HANDOVER.md +19 -0
- package/skills/sf-implement/DISPATCH-IMPLEMENTER.md +36 -0
- package/skills/sf-implement/body.md +147 -0
- package/skills/sf-implement/manifest.ts +8 -0
- package/skills/sf-plan/ADR-TEMPLATE.md +16 -0
- package/skills/sf-plan/DESIGN-TEMPLATE.md +54 -0
- package/skills/sf-plan/DISPATCH-PLAN-REVIEW.md +17 -0
- package/skills/sf-plan/TASK-TEMPLATE.md +30 -0
- package/skills/sf-plan/body.md +162 -0
- package/skills/sf-plan/manifest.ts +8 -0
- package/skills/sf-plan-review/body.md +90 -0
- package/skills/sf-plan-review/manifest.ts +7 -0
- package/skills/sf-receiving-review/body.md +73 -0
- package/skills/sf-receiving-review/manifest.ts +7 -0
- package/skills/sf-spec-review/body.md +83 -0
- package/skills/sf-spec-review/manifest.ts +7 -0
- package/skills/sf-tdd/body.md +120 -0
- package/skills/sf-tdd/manifest.ts +7 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { relative } from 'node:path';
|
|
2
|
+
import { cwd } from 'node:process';
|
|
3
|
+
import { createFix } from '../../core/fixes/create.js';
|
|
4
|
+
import { updateFixStatus } from '../../core/fixes/transition.js';
|
|
5
|
+
import { emitError, emitSuccess, jsonMode } from '../../core/output/index.js';
|
|
6
|
+
function createTimestamp() {
|
|
7
|
+
return new Date().toISOString();
|
|
8
|
+
}
|
|
9
|
+
export function registerFixCommand(program) {
|
|
10
|
+
const fix = program.command('fix').description('Manage fixes within a feature');
|
|
11
|
+
fix
|
|
12
|
+
.command('create')
|
|
13
|
+
.description("Create a fix inside a feature's fixes/ directory (blocks finish until resolved)")
|
|
14
|
+
.argument('<description>', 'short description of the fix')
|
|
15
|
+
.requiredOption('--feature <slug>', 'feature slug to attach this fix to')
|
|
16
|
+
.option('--json', 'output as structured JSON')
|
|
17
|
+
.action(async (description, options, command) => {
|
|
18
|
+
const json = jsonMode(command);
|
|
19
|
+
try {
|
|
20
|
+
const projectRoot = cwd();
|
|
21
|
+
const result = await createFix({
|
|
22
|
+
projectRoot,
|
|
23
|
+
description,
|
|
24
|
+
featureSlug: options.feature,
|
|
25
|
+
now: createTimestamp(),
|
|
26
|
+
});
|
|
27
|
+
const path = relative(projectRoot, result.filePath);
|
|
28
|
+
emitSuccess({ action: 'fix-create', id: result.id, description, feature: options.feature, path }, json, [
|
|
29
|
+
`Fix created: ${result.id}`,
|
|
30
|
+
` Description: ${description}`,
|
|
31
|
+
` Feature: ${options.feature}`,
|
|
32
|
+
` Path: ${path}`,
|
|
33
|
+
]);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
emitError(error, json);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
registerTransitionSubcommand(fix, 'resolve', 'resolved', 'Mark a fix as resolved');
|
|
40
|
+
registerTransitionSubcommand(fix, 'wont-fix', 'wont-fix', 'Mark a fix as wont-fix');
|
|
41
|
+
}
|
|
42
|
+
function registerTransitionSubcommand(fix, name, targetStatus, description) {
|
|
43
|
+
fix
|
|
44
|
+
.command(name)
|
|
45
|
+
.description(description)
|
|
46
|
+
.argument('<slug>', 'feature folder slug')
|
|
47
|
+
.argument('<id>', 'fix id (e.g. FIX-0001)')
|
|
48
|
+
.option('--json', 'output as structured JSON')
|
|
49
|
+
.action(async (slug, id, _options, command) => {
|
|
50
|
+
const json = jsonMode(command);
|
|
51
|
+
try {
|
|
52
|
+
const result = await updateFixStatus(cwd(), slug, id, targetStatus);
|
|
53
|
+
emitSuccess({ action: `fix-${name}`, ...result }, json, `fix ${result.id} (feature: ${result.featureSlug}): ${result.previousStatus} → ${result.newStatus}`);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
emitError(error, json);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=fix.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fix.js","sourceRoot":"","sources":["../../../../src/cli/commands/fix.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { cwd, stdin, stdout } from 'node:process';
|
|
2
|
+
import { createInterface } from 'node:readline/promises';
|
|
3
|
+
import { writeConfig } from '../../core/init/config.js';
|
|
4
|
+
import { installSkills } from '../../core/init/install-skills.js';
|
|
5
|
+
import { resolveHarness } from '../../core/init/prompt-harness.js';
|
|
6
|
+
import { scaffoldInit } from '../../core/init/scaffold.js';
|
|
7
|
+
import { emitError, emitSuccess, isInteractive, jsonMode, ScifiError, } from '../../core/output/index.js';
|
|
8
|
+
import { findPackageRoot } from '../../core/package-root.js';
|
|
9
|
+
import { HarnessNotImplementedError, InvalidHarnessError, KNOWN_HARNESS_IDS, } from '../../core/skills/harness/adapter.js';
|
|
10
|
+
import { getAdapter } from '../../core/skills/harness/registry.js';
|
|
11
|
+
const BOOTSTRAP_FILES = ['CONTEXT.md'];
|
|
12
|
+
export function registerInitCommand(program) {
|
|
13
|
+
program
|
|
14
|
+
.command('init')
|
|
15
|
+
.description('Initialize scifi in the current repository')
|
|
16
|
+
.option('--harness <id>', 'harness adapter to install skills for')
|
|
17
|
+
.option('--yes', 'skip prompts and use defaults')
|
|
18
|
+
.option('--json', 'output as structured JSON')
|
|
19
|
+
.action(async (options, command) => {
|
|
20
|
+
const json = jsonMode(command);
|
|
21
|
+
try {
|
|
22
|
+
const projectRoot = cwd();
|
|
23
|
+
const packageRoot = findPackageRoot(import.meta.url);
|
|
24
|
+
if (options.harness === undefined && options.yes !== true && !isInteractive()) {
|
|
25
|
+
throw new ScifiError('INVALID_ARGUMENT', 'harness selection requires --harness <id> when running non-interactively.', { hint: `Available harnesses: ${KNOWN_HARNESS_IDS.join(', ')}.` });
|
|
26
|
+
}
|
|
27
|
+
const harness = await resolveHarness({
|
|
28
|
+
flag: options.harness,
|
|
29
|
+
yes: options.yes === true,
|
|
30
|
+
ask: askInteractively,
|
|
31
|
+
});
|
|
32
|
+
// Validate the adapter is implemented before touching the filesystem.
|
|
33
|
+
getAdapter(harness);
|
|
34
|
+
await scaffoldInit({ projectRoot, harness });
|
|
35
|
+
const skills = await installSkills({ projectRoot, harness, packageRoot });
|
|
36
|
+
await writeConfig({ projectRoot, harness });
|
|
37
|
+
emitSuccess({
|
|
38
|
+
action: 'init',
|
|
39
|
+
root: 'docs/scifi',
|
|
40
|
+
harness,
|
|
41
|
+
files: BOOTSTRAP_FILES,
|
|
42
|
+
skills,
|
|
43
|
+
}, json, [
|
|
44
|
+
`scifi initialized successfully.`,
|
|
45
|
+
` Root: docs/scifi`,
|
|
46
|
+
` Harness: ${harness}`,
|
|
47
|
+
` Files: ${BOOTSTRAP_FILES.join(', ')}`,
|
|
48
|
+
` Skills: ${skills.join(', ')}`,
|
|
49
|
+
``,
|
|
50
|
+
`Next: read docs/scifi/CONTEXT.md,`,
|
|
51
|
+
`then create a spec with \`scifi spec <slug> --title "Your Feature"\``,
|
|
52
|
+
]);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
emitError(normalizeInitError(error), json);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function normalizeInitError(error) {
|
|
60
|
+
if (error instanceof InvalidHarnessError || error instanceof HarnessNotImplementedError) {
|
|
61
|
+
return new ScifiError('INVALID_ARGUMENT', error.message, {
|
|
62
|
+
hint: `Available harnesses: ${KNOWN_HARNESS_IDS.join(', ')}.`,
|
|
63
|
+
cause: error,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return error;
|
|
67
|
+
}
|
|
68
|
+
async function askInteractively(choices) {
|
|
69
|
+
const rl = createInterface({ input: stdin, output: stdout });
|
|
70
|
+
try {
|
|
71
|
+
const numbered = choices.map((id, index) => ` ${index + 1}) ${id}`).join('\n');
|
|
72
|
+
const prompt = `Pick a harness:\n${numbered}\nEnter number (default 1): `;
|
|
73
|
+
const answer = (await rl.question(prompt)).trim();
|
|
74
|
+
if (answer === '') {
|
|
75
|
+
const first = choices[0];
|
|
76
|
+
if (first === undefined) {
|
|
77
|
+
throw new Error('No harness choices available');
|
|
78
|
+
}
|
|
79
|
+
return first;
|
|
80
|
+
}
|
|
81
|
+
const index = Number.parseInt(answer, 10) - 1;
|
|
82
|
+
const picked = choices[index];
|
|
83
|
+
if (picked === undefined) {
|
|
84
|
+
return answer;
|
|
85
|
+
}
|
|
86
|
+
return picked;
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
rl.close();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { cwd } from 'node:process';
|
|
2
|
+
import { listOpenFixes } from '../../core/fixes/list.js';
|
|
3
|
+
import { emitError, emitList, jsonMode } from '../../core/output/index.js';
|
|
4
|
+
import { listFeatures } from '../../core/specs/list.js';
|
|
5
|
+
import { FEATURE_STATUS_VALUES } from '../../core/specs/types.js';
|
|
6
|
+
export function registerListCommand(program) {
|
|
7
|
+
program
|
|
8
|
+
.command('list')
|
|
9
|
+
.description('List all features')
|
|
10
|
+
.option('--status <status>', 'filter by lifecycle status')
|
|
11
|
+
.option('--json', 'output as structured JSON (NDJSON)')
|
|
12
|
+
.action(async (options, command) => {
|
|
13
|
+
const json = jsonMode(command);
|
|
14
|
+
try {
|
|
15
|
+
const projectRoot = cwd();
|
|
16
|
+
const statusFilter = options.status !== undefined &&
|
|
17
|
+
FEATURE_STATUS_VALUES.includes(options.status)
|
|
18
|
+
? options.status
|
|
19
|
+
: undefined;
|
|
20
|
+
const listOptions = { projectRoot };
|
|
21
|
+
if (statusFilter !== undefined) {
|
|
22
|
+
listOptions.status = statusFilter;
|
|
23
|
+
}
|
|
24
|
+
const features = await listFeatures(listOptions);
|
|
25
|
+
const rows = await Promise.all(features.map(async (feature) => {
|
|
26
|
+
const openFixes = await listOpenFixes(projectRoot, feature.slug);
|
|
27
|
+
return {
|
|
28
|
+
slug: feature.slug,
|
|
29
|
+
status: feature.status,
|
|
30
|
+
openFixes: openFixes.length,
|
|
31
|
+
title: feature.title ?? '',
|
|
32
|
+
};
|
|
33
|
+
}));
|
|
34
|
+
const humanLines = [
|
|
35
|
+
['SLUG', 'STATUS', 'OPEN FIXES', 'TITLE'].join('\t'),
|
|
36
|
+
...rows.map((row) => [
|
|
37
|
+
row.slug,
|
|
38
|
+
row.status,
|
|
39
|
+
row.openFixes > 0
|
|
40
|
+
? `${row.openFixes} open fix${row.openFixes === 1 ? '' : 'es'}`
|
|
41
|
+
: '-',
|
|
42
|
+
row.title,
|
|
43
|
+
].join('\t')),
|
|
44
|
+
];
|
|
45
|
+
emitList(rows, json, humanLines);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
emitError(error, json);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../../src/cli/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,mBAAmB,CAAC;SAChC,MAAM,CAAC,mBAAmB,EAAE,4BAA4B,CAAC;SACzD,MAAM,CAAC,QAAQ,EAAE,oCAAoC,CAAC;SACtD,MAAM,CAAC,KAAK,EAAE,OAA4C,EAAE,OAAgB,EAAE,EAAE;QAC/E,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC;YAC1B,MAAM,YAAY,GAChB,OAAO,CAAC,MAAM,KAAK,SAAS;gBAC3B,qBAA2C,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;gBACnE,CAAC,CAAE,OAAO,CAAC,MAAwB;gBACnC,CAAC,CAAC,SAAS,CAAC;YAEhB,MAAM,WAAW,GAAG,EAAE,WAAW,EAAE,CAAC;YACpC,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;gBAC9B,WAA0C,CAAC,MAAM,GAAG,YAAY,CAAC;YACpE,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC;YAEjD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,GAAG,CAC5B,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;gBAC7B,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;gBACjE,OAAO;oBACL,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,SAAS,EAAE,SAAS,CAAC,MAAM;oBAC3B,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;iBAC3B,CAAC;YACJ,CAAC,CAAC,CACH,CAAC;YAEF,MAAM,UAAU,GAAG;gBACjB,CAAC,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;gBACpD,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAClB;oBACE,GAAG,CAAC,IAAI;oBACR,GAAG,CAAC,MAAM;oBACV,GAAG,CAAC,SAAS,GAAG,CAAC;wBACf,CAAC,CAAC,GAAG,GAAG,CAAC,SAAS,YAAY,GAAG,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE;wBAC/D,CAAC,CAAC,GAAG;oBACP,GAAG,CAAC,KAAK;iBACV,CAAC,IAAI,CAAC,IAAI,CAAC,CACb;aACF,CAAC;YAEF,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACzB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { cwd } from 'node:process';
|
|
2
|
+
import { emitError, emitSuccess, jsonMode } from '../../core/output/index.js';
|
|
3
|
+
import { updateFeatureStatus } from '../../core/specs/transition.js';
|
|
4
|
+
function createTimestamp() {
|
|
5
|
+
return new Date().toISOString();
|
|
6
|
+
}
|
|
7
|
+
export function registerPlanReadyCommand(program) {
|
|
8
|
+
program
|
|
9
|
+
.command('plan-ready')
|
|
10
|
+
.description('Mark a feature as plan-ready (validates design.md and tasks/ exist)')
|
|
11
|
+
.argument('<slug>', 'feature folder slug')
|
|
12
|
+
.option('--json', 'output as structured JSON')
|
|
13
|
+
.action(async (slug, _options, command) => {
|
|
14
|
+
const json = jsonMode(command);
|
|
15
|
+
try {
|
|
16
|
+
const result = await updateFeatureStatus(cwd(), slug, 'plan-ready', createTimestamp());
|
|
17
|
+
emitSuccess({ action: 'plan-ready', ...result }, json, [
|
|
18
|
+
`feature ${result.slug}: ${result.previousStatus} → ${result.newStatus}`,
|
|
19
|
+
` Timestamp: ${result.timestamp}`,
|
|
20
|
+
]);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
emitError(error, json);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=plan-ready.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-ready.js","sourceRoot":"","sources":["../../../../src/cli/commands/plan-ready.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAErE,SAAS,eAAe;IACtB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,OAAgB;IACvD,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CAAC,qEAAqE,CAAC;SAClF,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAC;SACzC,MAAM,CAAC,QAAQ,EAAE,2BAA2B,CAAC;SAC7C,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,QAAiB,EAAE,OAAgB,EAAE,EAAE;QAClE,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,eAAe,EAAE,CAAC,CAAC;YACvF,WAAW,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,EAAE,EAAE,IAAI,EAAE;gBACrD,WAAW,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,cAAc,MAAM,MAAM,CAAC,SAAS,EAAE;gBACxE,gBAAgB,MAAM,CAAC,SAAS,EAAE;aACnC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACzB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { cwd } from 'node:process';
|
|
2
|
+
import { emitError, emitSuccess, jsonMode } from '../../core/output/index.js';
|
|
3
|
+
import { inspectPlanSession } from '../../core/specs/plan-session.js';
|
|
4
|
+
export function registerPlanCommand(program) {
|
|
5
|
+
program
|
|
6
|
+
.command('plan')
|
|
7
|
+
.description('Open a planning session for a spec-ready feature (reports plan progress)')
|
|
8
|
+
.argument('<slug>', 'feature folder slug')
|
|
9
|
+
.option('--json', 'output as structured JSON')
|
|
10
|
+
.action(async (slug, _options, command) => {
|
|
11
|
+
const json = jsonMode(command);
|
|
12
|
+
try {
|
|
13
|
+
const session = await inspectPlanSession(cwd(), slug);
|
|
14
|
+
const guidance = session.state === 'ready-to-plan'
|
|
15
|
+
? [
|
|
16
|
+
'No design.md or tasks yet — start the plan from scratch.',
|
|
17
|
+
`Next: write design.md and tasks/, then run \`scifi plan-ready ${session.slug}\`.`,
|
|
18
|
+
]
|
|
19
|
+
: session.state === 'in-progress'
|
|
20
|
+
? [
|
|
21
|
+
'Planning already started but is incomplete.',
|
|
22
|
+
` design.md: ${session.designExists ? 'present' : 'missing'}`,
|
|
23
|
+
` tasks: ${session.taskFileCount} file${session.taskFileCount === 1 ? '' : 's'}`,
|
|
24
|
+
'Continue where it left off, or rewrite from scratch if the approach changed.',
|
|
25
|
+
]
|
|
26
|
+
: [
|
|
27
|
+
'This feature is already planned (status is past spec-ready).',
|
|
28
|
+
` design.md: ${session.designExists ? 'present' : 'missing'}`,
|
|
29
|
+
` tasks: ${session.taskFileCount} file${session.taskFileCount === 1 ? '' : 's'}`,
|
|
30
|
+
'Ask the user whether to continue refining the existing plan or start over.',
|
|
31
|
+
];
|
|
32
|
+
emitSuccess({ action: 'plan', ...session }, json, [
|
|
33
|
+
`feature ${session.slug}: ${session.status} (plan ${session.state})`,
|
|
34
|
+
'',
|
|
35
|
+
...guidance,
|
|
36
|
+
]);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
emitError(error, json);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../../src/cli/commands/plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAEtE,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,0EAA0E,CAAC;SACvF,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAC;SACzC,MAAM,CAAC,QAAQ,EAAE,2BAA2B,CAAC;SAC7C,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,QAAiB,EAAE,OAAgB,EAAE,EAAE;QAClE,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;YAEtD,MAAM,QAAQ,GACZ,OAAO,CAAC,KAAK,KAAK,eAAe;gBAC/B,CAAC,CAAC;oBACE,0DAA0D;oBAC1D,iEAAiE,OAAO,CAAC,IAAI,KAAK;iBACnF;gBACH,CAAC,CAAC,OAAO,CAAC,KAAK,KAAK,aAAa;oBAC/B,CAAC,CAAC;wBACE,6CAA6C;wBAC7C,gBAAgB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE;wBAC9D,gBAAgB,OAAO,CAAC,aAAa,QAAQ,OAAO,CAAC,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE;wBACrF,8EAA8E;qBAC/E;oBACH,CAAC,CAAC;wBACE,8DAA8D;wBAC9D,gBAAgB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE;wBAC9D,gBAAgB,OAAO,CAAC,aAAa,QAAQ,OAAO,CAAC,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE;wBACrF,4EAA4E;qBAC7E,CAAC;YAEV,WAAW,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,EAAE,IAAI,EAAE;gBAChD,WAAW,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM,UAAU,OAAO,CAAC,KAAK,GAAG;gBACpE,EAAE;gBACF,GAAG,QAAQ;aACZ,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACzB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { cwd } from 'node:process';
|
|
2
|
+
import { emitError, emitSuccess, jsonMode } from '../../core/output/index.js';
|
|
3
|
+
import { updateFeatureStatus } from '../../core/specs/transition.js';
|
|
4
|
+
function createTimestamp() {
|
|
5
|
+
return new Date().toISOString();
|
|
6
|
+
}
|
|
7
|
+
export function registerSpecReadyCommand(program) {
|
|
8
|
+
program
|
|
9
|
+
.command('spec-ready')
|
|
10
|
+
.description('Mark a feature as spec-ready (validates spec.md exists)')
|
|
11
|
+
.argument('<slug>', 'feature folder slug')
|
|
12
|
+
.option('--json', 'output as structured JSON')
|
|
13
|
+
.action(async (slug, _options, command) => {
|
|
14
|
+
const json = jsonMode(command);
|
|
15
|
+
try {
|
|
16
|
+
const result = await updateFeatureStatus(cwd(), slug, 'spec-ready', createTimestamp());
|
|
17
|
+
emitSuccess({ action: 'spec-ready', ...result }, json, [
|
|
18
|
+
`feature ${result.slug}: ${result.previousStatus} → ${result.newStatus}`,
|
|
19
|
+
` Timestamp: ${result.timestamp}`,
|
|
20
|
+
]);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
emitError(error, json);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=spec-ready.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-ready.js","sourceRoot":"","sources":["../../../../src/cli/commands/spec-ready.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAErE,SAAS,eAAe;IACtB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,OAAgB;IACvD,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CAAC,yDAAyD,CAAC;SACtE,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAC;SACzC,MAAM,CAAC,QAAQ,EAAE,2BAA2B,CAAC;SAC7C,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,QAAiB,EAAE,OAAgB,EAAE,EAAE;QAClE,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,eAAe,EAAE,CAAC,CAAC;YACvF,WAAW,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,EAAE,EAAE,IAAI,EAAE;gBACrD,WAAW,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,cAAc,MAAM,MAAM,CAAC,SAAS,EAAE;gBACxE,gBAAgB,MAAM,CAAC,SAAS,EAAE;aACnC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACzB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { relative } from 'node:path';
|
|
2
|
+
import { cwd } from 'node:process';
|
|
3
|
+
import { emitError, emitSuccess, jsonMode } from '../../core/output/index.js';
|
|
4
|
+
import { createFeature } from '../../core/specs/create.js';
|
|
5
|
+
function createTimestamp() {
|
|
6
|
+
return new Date().toISOString();
|
|
7
|
+
}
|
|
8
|
+
export function registerSpecCommand(program) {
|
|
9
|
+
program
|
|
10
|
+
.command('spec')
|
|
11
|
+
.description('Create a scifi-managed feature container')
|
|
12
|
+
.argument('<slug>', 'feature folder slug')
|
|
13
|
+
.option('--title <title>', 'display title for the feature')
|
|
14
|
+
.option('--json', 'output as structured JSON')
|
|
15
|
+
.action(async (slug, options, command) => {
|
|
16
|
+
const json = jsonMode(command);
|
|
17
|
+
try {
|
|
18
|
+
const projectRoot = cwd();
|
|
19
|
+
const result = await createFeature({
|
|
20
|
+
projectRoot,
|
|
21
|
+
slug,
|
|
22
|
+
...(options.title !== undefined && { title: options.title }),
|
|
23
|
+
now: createTimestamp(),
|
|
24
|
+
});
|
|
25
|
+
const path = relative(projectRoot, result.featureDirectoryPath);
|
|
26
|
+
const metadataPath = relative(projectRoot, result.metadataPath);
|
|
27
|
+
emitSuccess({
|
|
28
|
+
action: 'spec',
|
|
29
|
+
slug,
|
|
30
|
+
path,
|
|
31
|
+
status: 'created',
|
|
32
|
+
metadataPath,
|
|
33
|
+
}, json, [
|
|
34
|
+
`Feature created: ${slug}`,
|
|
35
|
+
` Path: ${path}`,
|
|
36
|
+
` Status: created`,
|
|
37
|
+
``,
|
|
38
|
+
`Next: write spec.md, then run \`scifi spec-ready ${slug}\``,
|
|
39
|
+
]);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
emitError(error, json);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../../../../src/cli/commands/spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE3D,SAAS,eAAe;IACtB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,0CAA0C,CAAC;SACvD,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAC;SACzC,MAAM,CAAC,iBAAiB,EAAE,+BAA+B,CAAC;SAC1D,MAAM,CAAC,QAAQ,EAAE,2BAA2B,CAAC;SAC7C,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,OAA2C,EAAE,OAAgB,EAAE,EAAE;QAC5F,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC;YAC1B,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC;gBACjC,WAAW;gBACX,IAAI;gBACJ,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;gBAC5D,GAAG,EAAE,eAAe,EAAE;aACvB,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,oBAAoB,CAAC,CAAC;YAChE,MAAM,YAAY,GAAG,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;YAEhE,WAAW,CACT;gBACE,MAAM,EAAE,MAAM;gBACd,IAAI;gBACJ,IAAI;gBACJ,MAAM,EAAE,SAAS;gBACjB,YAAY;aACb,EACD,IAAI,EACJ;gBACE,oBAAoB,IAAI,EAAE;gBAC1B,aAAa,IAAI,EAAE;gBACnB,mBAAmB;gBACnB,EAAE;gBACF,oDAAoD,IAAI,IAAI;aAC7D,CACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACzB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { cwd } from 'node:process';
|
|
2
|
+
import { emitError, emitSuccess, jsonMode } from '../../core/output/index.js';
|
|
3
|
+
import { updateFeatureStatus } from '../../core/specs/transition.js';
|
|
4
|
+
function createTimestamp() {
|
|
5
|
+
return new Date().toISOString();
|
|
6
|
+
}
|
|
7
|
+
export function registerStartCommand(program) {
|
|
8
|
+
program
|
|
9
|
+
.command('start')
|
|
10
|
+
.description('Mark a feature as in-progress (requires plan-ready status)')
|
|
11
|
+
.argument('<slug>', 'feature folder slug')
|
|
12
|
+
.option('--json', 'output as structured JSON')
|
|
13
|
+
.action(async (slug, _options, command) => {
|
|
14
|
+
const json = jsonMode(command);
|
|
15
|
+
try {
|
|
16
|
+
const result = await updateFeatureStatus(cwd(), slug, 'in-progress', createTimestamp());
|
|
17
|
+
emitSuccess({ action: 'start', ...result }, json, [
|
|
18
|
+
`feature ${result.slug}: ${result.previousStatus} → ${result.newStatus}`,
|
|
19
|
+
` Timestamp: ${result.timestamp}`,
|
|
20
|
+
]);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
emitError(error, json);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../../../src/cli/commands/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAErE,SAAS,eAAe;IACtB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,4DAA4D,CAAC;SACzE,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAC;SACzC,MAAM,CAAC,QAAQ,EAAE,2BAA2B,CAAC;SAC7C,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,QAAiB,EAAE,OAAgB,EAAE,EAAE;QAClE,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,eAAe,EAAE,CAAC,CAAC;YACxF,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,EAAE,IAAI,EAAE;gBAChD,WAAW,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,cAAc,MAAM,MAAM,CAAC,SAAS,EAAE;gBACxE,gBAAgB,MAAM,CAAC,SAAS,EAAE;aACnC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACzB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { cwd } from 'node:process';
|
|
2
|
+
import { listFixes } from '../../core/fixes/list.js';
|
|
3
|
+
import { emitError, emitSuccess, jsonMode } from '../../core/output/index.js';
|
|
4
|
+
import { inspectFeatureLifecycle } from '../../core/specs/lifecycle.js';
|
|
5
|
+
import { listTasks } from '../../core/tasks/list.js';
|
|
6
|
+
export function registerStatusCommand(program) {
|
|
7
|
+
program
|
|
8
|
+
.command('status')
|
|
9
|
+
.description('Show lifecycle status and artifact inventory for a feature')
|
|
10
|
+
.argument('<slug>', 'feature folder slug')
|
|
11
|
+
.option('--json', 'output as structured JSON')
|
|
12
|
+
.action(async (slug, _options, command) => {
|
|
13
|
+
const json = jsonMode(command);
|
|
14
|
+
try {
|
|
15
|
+
const projectRoot = cwd();
|
|
16
|
+
const lifecycle = await inspectFeatureLifecycle(projectRoot, slug);
|
|
17
|
+
const tasks = await listTasks(projectRoot, slug);
|
|
18
|
+
const fixes = await listFixes(projectRoot, slug);
|
|
19
|
+
const { metadata, artifacts } = lifecycle;
|
|
20
|
+
const data = {
|
|
21
|
+
slug: metadata.slug,
|
|
22
|
+
...(metadata.title !== undefined && { title: metadata.title }),
|
|
23
|
+
status: metadata.status,
|
|
24
|
+
...(metadata.branch !== undefined && { branch: metadata.branch }),
|
|
25
|
+
...(metadata.worktreePath !== undefined && { worktree: metadata.worktreePath }),
|
|
26
|
+
artifacts: {
|
|
27
|
+
spec: artifacts.specExists,
|
|
28
|
+
design: artifacts.designExists,
|
|
29
|
+
taskCount: artifacts.taskFileCount,
|
|
30
|
+
},
|
|
31
|
+
tasks: tasks.map((task) => ({ slug: task.slug, status: task.status })),
|
|
32
|
+
fixes: fixes.map((fix) => ({
|
|
33
|
+
id: fix.id,
|
|
34
|
+
slug: fix.slug,
|
|
35
|
+
status: fix.status,
|
|
36
|
+
})),
|
|
37
|
+
};
|
|
38
|
+
const title = metadata.title !== undefined ? ` (${metadata.title})` : '';
|
|
39
|
+
const humanLines = [
|
|
40
|
+
`slug: ${metadata.slug}${title}`,
|
|
41
|
+
`status: ${metadata.status}`,
|
|
42
|
+
...(metadata.branch !== undefined ? [`branch: ${metadata.branch}`] : []),
|
|
43
|
+
...(metadata.worktreePath !== undefined ? [`worktree: ${metadata.worktreePath}`] : []),
|
|
44
|
+
``,
|
|
45
|
+
`spec.md: ${artifacts.specExists ? 'present' : 'missing'}`,
|
|
46
|
+
`design.md: ${artifacts.designExists ? 'present' : 'missing'}`,
|
|
47
|
+
`tasks: ${artifacts.taskFileCount} file${artifacts.taskFileCount === 1 ? '' : 's'}`,
|
|
48
|
+
...(tasks.length > 0
|
|
49
|
+
? ['', ...tasks.map((task) => ` ${task.slug}\t${task.status}`)]
|
|
50
|
+
: []),
|
|
51
|
+
...(fixes.length > 0
|
|
52
|
+
? ['', 'fixes:', ...fixes.map((fix) => ` ${fix.id} ${fix.status} ${fix.slug}`)]
|
|
53
|
+
: []),
|
|
54
|
+
];
|
|
55
|
+
emitSuccess(data, json, humanLines);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
emitError(error, json);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//# 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,64 @@
|
|
|
1
|
+
import { cwd } from 'node:process';
|
|
2
|
+
import { emitError, emitList, emitSuccess, jsonMode } from '../../core/output/index.js';
|
|
3
|
+
import { listTasks } from '../../core/tasks/list.js';
|
|
4
|
+
import { updateTaskStatus } from '../../core/tasks/transition.js';
|
|
5
|
+
export function registerTaskCommand(program) {
|
|
6
|
+
const task = program.command('task').description('Manage tasks within a feature');
|
|
7
|
+
task
|
|
8
|
+
.command('list')
|
|
9
|
+
.description('List all tasks for a feature with their status')
|
|
10
|
+
.argument('<slug>', 'feature folder slug')
|
|
11
|
+
.option('--json', 'output as structured JSON (NDJSON)')
|
|
12
|
+
.action(async (slug, _options, command) => {
|
|
13
|
+
const json = jsonMode(command);
|
|
14
|
+
try {
|
|
15
|
+
const tasks = await listTasks(cwd(), slug);
|
|
16
|
+
const rows = tasks.map((t) => ({
|
|
17
|
+
slug: t.slug,
|
|
18
|
+
status: t.status,
|
|
19
|
+
dependsOn: t.dependsOn,
|
|
20
|
+
}));
|
|
21
|
+
const humanLines = [
|
|
22
|
+
['TASK', 'STATUS', 'DEPENDS-ON'].join('\t'),
|
|
23
|
+
...rows.map((row) => [row.slug, row.status, row.dependsOn.join(',')].join('\t')),
|
|
24
|
+
];
|
|
25
|
+
emitList(rows, json, humanLines);
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
emitError(error, json);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
task
|
|
32
|
+
.command('start')
|
|
33
|
+
.description('Mark a task as in-progress')
|
|
34
|
+
.argument('<slug>', 'feature folder slug')
|
|
35
|
+
.argument('<task>', 'task slug')
|
|
36
|
+
.option('--json', 'output as structured JSON')
|
|
37
|
+
.action(async (slug, taskSlug, _options, command) => {
|
|
38
|
+
const json = jsonMode(command);
|
|
39
|
+
try {
|
|
40
|
+
const result = await updateTaskStatus(cwd(), slug, taskSlug, 'in-progress');
|
|
41
|
+
emitSuccess({ action: 'task-start', ...result }, json, `task ${result.taskSlug} (feature: ${result.featureSlug}): ${result.previousStatus} → ${result.newStatus}`);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
emitError(error, json);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
task
|
|
48
|
+
.command('done')
|
|
49
|
+
.description('Mark a task as done (requires task to be in-progress)')
|
|
50
|
+
.argument('<slug>', 'feature folder slug')
|
|
51
|
+
.argument('<task>', 'task slug')
|
|
52
|
+
.option('--json', 'output as structured JSON')
|
|
53
|
+
.action(async (slug, taskSlug, _options, command) => {
|
|
54
|
+
const json = jsonMode(command);
|
|
55
|
+
try {
|
|
56
|
+
const result = await updateTaskStatus(cwd(), slug, taskSlug, 'done');
|
|
57
|
+
emitSuccess({ action: 'task-done', ...result }, json, `task ${result.taskSlug} (feature: ${result.featureSlug}): ${result.previousStatus} → ${result.newStatus}`);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
emitError(error, json);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=task.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task.js","sourceRoot":"","sources":["../../../../src/cli/commands/task.ts"],"names":[],"mappings":"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"}
|