@iamk77/skill-checklist 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.
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getBuiltin = getBuiltin;
4
+ exports.listBuiltins = listBuiltins;
5
+ const frontmatter_js_1 = require("./frontmatter.js");
6
+ const name_format_js_1 = require("./name-format.js");
7
+ const description_js_1 = require("./description.js");
8
+ const no_secrets_js_1 = require("./no-secrets.js");
9
+ const file_refs_js_1 = require("./file-refs.js");
10
+ const has_checklist_js_1 = require("./has-checklist.js");
11
+ const line_count_js_1 = require("./line-count.js");
12
+ const BUILTINS = {
13
+ 'frontmatter': frontmatter_js_1.frontmatterCheck,
14
+ 'name-format': name_format_js_1.nameFormatCheck,
15
+ 'description-present': description_js_1.descriptionPresentCheck,
16
+ 'description-length': description_js_1.descriptionLengthCheck,
17
+ 'no-secrets': no_secrets_js_1.noSecretsCheck,
18
+ 'file-refs': file_refs_js_1.fileRefsCheck,
19
+ 'has-checklist': has_checklist_js_1.hasChecklistCheck,
20
+ 'line-count': line_count_js_1.lineCountCheck,
21
+ };
22
+ function getBuiltin(name) {
23
+ return BUILTINS[name];
24
+ }
25
+ function listBuiltins() {
26
+ return Object.keys(BUILTINS);
27
+ }
@@ -0,0 +1,51 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.lineCountCheck = lineCountCheck;
37
+ const fs = __importStar(require("node:fs"));
38
+ const path = __importStar(require("node:path"));
39
+ const MAX_LINES = 500;
40
+ async function lineCountCheck(targetPath) {
41
+ const filePath = path.resolve(targetPath, 'SKILL.md');
42
+ if (!fs.existsSync(filePath)) {
43
+ return { status: 'fail', message: 'SKILL.md not found' };
44
+ }
45
+ const content = fs.readFileSync(filePath, 'utf-8');
46
+ const count = content.split('\n').length;
47
+ if (count > MAX_LINES) {
48
+ return { status: 'fail', message: `${count} lines, exceeds ${MAX_LINES} limit` };
49
+ }
50
+ return { status: 'pass', message: `${count} lines` };
51
+ }
@@ -0,0 +1,65 @@
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.nameFormatCheck = nameFormatCheck;
40
+ const fs = __importStar(require("node:fs"));
41
+ const path = __importStar(require("node:path"));
42
+ const gray_matter_1 = __importDefault(require("gray-matter"));
43
+ const NAME_RE = /^[a-z0-9-]+$/;
44
+ const MAX_LENGTH = 64;
45
+ async function nameFormatCheck(targetPath) {
46
+ const filePath = path.resolve(targetPath, 'SKILL.md');
47
+ if (!fs.existsSync(filePath)) {
48
+ return { status: 'fail', message: 'SKILL.md not found' };
49
+ }
50
+ const { data } = (0, gray_matter_1.default)(fs.readFileSync(filePath, 'utf-8'));
51
+ const name = data.name;
52
+ if (name === undefined || name === null || name === '') {
53
+ return { status: 'pass', message: 'name field not set (will use directory name)' };
54
+ }
55
+ if (typeof name !== 'string') {
56
+ return { status: 'fail', message: 'name must be a string' };
57
+ }
58
+ if (!NAME_RE.test(name)) {
59
+ return { status: 'fail', message: `invalid characters: "${name}"` };
60
+ }
61
+ if (name.length > MAX_LENGTH) {
62
+ return { status: 'fail', message: `${name.length}/${MAX_LENGTH} chars` };
63
+ }
64
+ return { status: 'pass', message: `"${name}", ${name.length} chars` };
65
+ }
@@ -0,0 +1,85 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.noSecretsCheck = noSecretsCheck;
37
+ const fs = __importStar(require("node:fs"));
38
+ const path = __importStar(require("node:path"));
39
+ // High-confidence standalone token shapes. These are always flagged when matched.
40
+ const TOKEN_PATTERNS = [
41
+ { name: 'AWS Access Key', re: /AKIA[0-9A-Z]{16}/ },
42
+ { name: 'Private Key', re: /-----BEGIN (?:RSA |EC |DSA |OPENSSH |PGP )?PRIVATE KEY-----/ },
43
+ { name: 'GitHub Token', re: /gh[pousr]_[a-zA-Z0-9]{20,}/ },
44
+ { name: 'GitHub Fine-grained Token', re: /github_pat_[a-zA-Z0-9_]{20,}/ },
45
+ { name: 'npm Token', re: /npm_[a-zA-Z0-9]{20,}/ },
46
+ { name: 'Slack Token', re: /xox[baprs]-[a-zA-Z0-9-]{10,}/ },
47
+ { name: 'OpenAI Key', re: /sk-[a-zA-Z0-9]{20,}/ },
48
+ { name: 'Google API Key', re: /AIza[0-9A-Za-z_\-]{35}/ },
49
+ ];
50
+ // Generic `key = value` assignments. Flagged only when the value does not look
51
+ // like a documentation placeholder (e.g. YOUR_TOKEN, <api-key>, changeme).
52
+ const ASSIGNMENT_PATTERNS = [
53
+ { name: 'API Key assignment', re: /(?:api[_-]?key|apikey)\s*[:=]\s*['"]?([^\s'"]{20,})/i },
54
+ { name: 'Token/Secret assignment', re: /(?:token|secret|password|passwd|pwd)\s*[:=]\s*['"]?([^\s'"]{8,})/i },
55
+ ];
56
+ const PLACEHOLDER_RE = /^(?:[<{].*[>}]|\.{3,}|x{3,}|your[_-]|my[_-]|changeme|placeholder|replace|example|todo|\$\{|env\.|process\.env)/i;
57
+ function isPlaceholder(value) {
58
+ return PLACEHOLDER_RE.test(value) || /^[A-Z][A-Z0-9_]+$/.test(value); // ALL_CAPS_PLACEHOLDER
59
+ }
60
+ async function noSecretsCheck(targetPath) {
61
+ const filePath = path.resolve(targetPath, 'SKILL.md');
62
+ if (!fs.existsSync(filePath)) {
63
+ return { status: 'fail', message: 'SKILL.md not found' };
64
+ }
65
+ const lines = fs.readFileSync(filePath, 'utf-8').split('\n');
66
+ const findings = [];
67
+ for (let i = 0; i < lines.length; i++) {
68
+ const line = lines[i];
69
+ for (const pattern of TOKEN_PATTERNS) {
70
+ if (pattern.re.test(line)) {
71
+ findings.push(`L${i + 1}: ${pattern.name}`);
72
+ }
73
+ }
74
+ for (const pattern of ASSIGNMENT_PATTERNS) {
75
+ const m = pattern.re.exec(line);
76
+ if (m && !isPlaceholder(m[1])) {
77
+ findings.push(`L${i + 1}: ${pattern.name}`);
78
+ }
79
+ }
80
+ }
81
+ if (findings.length > 0) {
82
+ return { status: 'fail', message: findings.join(', ') };
83
+ }
84
+ return { status: 'pass', message: 'no secret patterns detected' };
85
+ }
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkCommand = checkCommand;
4
+ const loader_js_1 = require("../loader.js");
5
+ const state_js_1 = require("../state.js");
6
+ const resolver_js_1 = require("../resolver.js");
7
+ const formatter_js_1 = require("../formatter.js");
8
+ function checkCommand(phaseArg, itemId, options) {
9
+ const cwd = (0, resolver_js_1.resolveDir)(options.dir);
10
+ try {
11
+ const config = (0, loader_js_1.loadChecklist)(cwd);
12
+ const state = (0, state_js_1.loadState)(cwd);
13
+ const phaseIndex = (0, resolver_js_1.findPhaseIndex)(config, phaseArg);
14
+ const gate = (0, resolver_js_1.gatePriorPhases)(config, phaseIndex, state);
15
+ if (!gate.passed) {
16
+ console.error((0, formatter_js_1.formatGateFailure)(gate.failedPhase, gate.failedPhaseIndex));
17
+ process.exit(1);
18
+ }
19
+ const phase = config.phases[phaseIndex];
20
+ const item = phase.checks.find(c => c.id === itemId);
21
+ if (!item) {
22
+ const available = phase.checks.map(c => c.id).join(', ');
23
+ console.error(`item "${itemId}" not found in phase "${phase.name}". available: ${available}`);
24
+ process.exit(1);
25
+ }
26
+ if (item.verify) {
27
+ console.error(`"${itemId}" has a verify rule — it is mechanical, not manual. run: checklist verify ${phaseArg}`);
28
+ process.exit(1);
29
+ }
30
+ (0, state_js_1.setItemResult)(state, phaseIndex, itemId, { status: 'pass', message: 'confirmed' });
31
+ (0, state_js_1.saveState)(cwd, state);
32
+ console.log((0, formatter_js_1.formatCheckConfirm)(phaseIndex, itemId));
33
+ }
34
+ catch (e) {
35
+ console.error(e instanceof Error ? e.message : String(e));
36
+ process.exit(1);
37
+ }
38
+ }
@@ -0,0 +1,67 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.initCommand = initCommand;
37
+ const fs = __importStar(require("node:fs"));
38
+ const path = __importStar(require("node:path"));
39
+ const loader_js_1 = require("../loader.js");
40
+ const state_js_1 = require("../state.js");
41
+ const formatter_js_1 = require("../formatter.js");
42
+ const resolver_js_1 = require("../resolver.js");
43
+ const STATE_FILE = '.checklist.state.json';
44
+ function initCommand(dir, options) {
45
+ // init accepts the dir both positionally (`init <dir>`) and via the uniform
46
+ // --dir flag; reject a conflicting combination rather than silently using one.
47
+ if (dir && options?.dir && path.resolve(dir) !== path.resolve(options.dir)) {
48
+ console.error(`conflicting target dir: positional "${dir}" vs --dir "${options.dir}"`);
49
+ process.exit(1);
50
+ }
51
+ const targetDir = dir || (0, resolver_js_1.resolveDir)(options?.dir);
52
+ try {
53
+ const config = (0, loader_js_1.loadChecklist)(targetDir);
54
+ const stateExists = fs.existsSync(path.resolve(targetDir, STATE_FILE));
55
+ if (stateExists && !options?.force) {
56
+ console.error(`state file exists in ${targetDir}. use --force to clear and reinitialize`);
57
+ process.exit(1);
58
+ }
59
+ (0, state_js_1.clearState)(targetDir);
60
+ (0, resolver_js_1.writeActivePointer)(targetDir);
61
+ console.log((0, formatter_js_1.formatInit)(config, stateExists));
62
+ }
63
+ catch (e) {
64
+ console.error(e instanceof Error ? e.message : String(e));
65
+ process.exit(1);
66
+ }
67
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.phasesCommand = phasesCommand;
4
+ const loader_js_1 = require("../loader.js");
5
+ const formatter_js_1 = require("../formatter.js");
6
+ const resolver_js_1 = require("../resolver.js");
7
+ function phasesCommand(options) {
8
+ const targetDir = (0, resolver_js_1.resolveDir)(options?.dir);
9
+ try {
10
+ const config = (0, loader_js_1.loadChecklist)(targetDir);
11
+ console.log((0, formatter_js_1.formatPhases)(config));
12
+ }
13
+ catch (e) {
14
+ console.error(e instanceof Error ? e.message : String(e));
15
+ process.exit(1);
16
+ }
17
+ }
@@ -0,0 +1,63 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.resetCommand = resetCommand;
37
+ const fs = __importStar(require("node:fs"));
38
+ const path = __importStar(require("node:path"));
39
+ const state_js_1 = require("../state.js");
40
+ const resolver_js_1 = require("../resolver.js");
41
+ const CONFIG_FILE = '.checklist.yml';
42
+ // End-of-run cleanup. Symmetric with `init`: clears this skill's state file and
43
+ // drops the global active pointer when it points here, so nothing is left
44
+ // lingering after a checklist session completes.
45
+ //
46
+ // `reset` is destructive, so — unlike the read-only fall-through in resolveDir —
47
+ // it must NOT act on a directory the user never named. Every other command is
48
+ // implicitly guarded by loadChecklist (which throws on a missing .checklist.yml);
49
+ // reset has no such call, so it guards explicitly here. Without this, a bare
50
+ // `checklist reset`/`done` with no --dir/env/pointer would resolve to cwd and
51
+ // delete an unrelated project's .checklist.state.json.
52
+ function resetCommand(options) {
53
+ const targetDir = (0, resolver_js_1.resolveDir)(options?.dir);
54
+ if (!fs.existsSync(path.join(targetDir, CONFIG_FILE))) {
55
+ console.error(`no active checklist to reset in ${targetDir}. pass --dir <skill-dir>`);
56
+ process.exit(1);
57
+ return; // ensure the destructive ops below never run even if exit is stubbed
58
+ }
59
+ (0, state_js_1.clearState)(targetDir);
60
+ const pointerCleared = (0, resolver_js_1.clearActivePointer)(targetDir);
61
+ const pointerNote = pointerCleared ? ' and active pointer' : '';
62
+ console.log(`checklist reset: cleared state${pointerNote} for ${targetDir}`);
63
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.showCommand = showCommand;
4
+ const loader_js_1 = require("../loader.js");
5
+ const state_js_1 = require("../state.js");
6
+ const resolver_js_1 = require("../resolver.js");
7
+ const formatter_js_1 = require("../formatter.js");
8
+ async function showCommand(phaseArg, options) {
9
+ const cwd = (0, resolver_js_1.resolveDir)(options?.dir);
10
+ const targetPath = options?.path || cwd;
11
+ try {
12
+ const config = (0, loader_js_1.loadChecklist)(cwd);
13
+ const state = (0, state_js_1.loadState)(cwd);
14
+ if (!phaseArg) {
15
+ console.log((0, formatter_js_1.formatOverview)(config, state));
16
+ return;
17
+ }
18
+ const phaseIndex = (0, resolver_js_1.findPhaseIndex)(config, phaseArg);
19
+ const gate = (0, resolver_js_1.gatePriorPhases)(config, phaseIndex, state);
20
+ if (!gate.passed) {
21
+ console.error((0, formatter_js_1.formatGateFailure)(gate.failedPhase, gate.failedPhaseIndex));
22
+ process.exit(1);
23
+ }
24
+ const result = await (0, resolver_js_1.runPhase)(config.phases[phaseIndex], phaseIndex, cwd, targetPath);
25
+ console.log((0, formatter_js_1.formatPhaseShow)(result, state, config.phases.length));
26
+ }
27
+ catch (e) {
28
+ console.error(e instanceof Error ? e.message : String(e));
29
+ process.exit(1);
30
+ }
31
+ }
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.verifyCommand = verifyCommand;
4
+ const loader_js_1 = require("../loader.js");
5
+ const state_js_1 = require("../state.js");
6
+ const resolver_js_1 = require("../resolver.js");
7
+ const formatter_js_1 = require("../formatter.js");
8
+ async function verifyCommand(phaseArg, options) {
9
+ const cwd = (0, resolver_js_1.resolveDir)(options.dir);
10
+ const targetPath = options.path || cwd;
11
+ try {
12
+ const config = (0, loader_js_1.loadChecklist)(cwd);
13
+ const state = (0, state_js_1.loadState)(cwd);
14
+ const phaseIndex = (0, resolver_js_1.findPhaseIndex)(config, phaseArg);
15
+ const gate = (0, resolver_js_1.gatePriorPhases)(config, phaseIndex, state);
16
+ if (!gate.passed) {
17
+ console.error((0, formatter_js_1.formatGateFailure)(gate.failedPhase, gate.failedPhaseIndex));
18
+ process.exit(1);
19
+ }
20
+ const result = await (0, resolver_js_1.runPhase)(config.phases[phaseIndex], phaseIndex, cwd, targetPath);
21
+ for (const c of result.checks) {
22
+ if (c.kind === 'mechanical' && c.result) {
23
+ // Record the CURRENT result, pass or fail — so a check that was green on
24
+ // an earlier verify and has since regressed overwrites its stale pass and
25
+ // the gate (isItemChecked === 'pass') sees current reality, instead of a
26
+ // failing re-verify silently leaving the old pass (and the gate) standing.
27
+ (0, state_js_1.setItemResult)(state, phaseIndex, c.item.id, c.result);
28
+ }
29
+ }
30
+ (0, state_js_1.saveState)(cwd, state);
31
+ console.log((0, formatter_js_1.formatVerifyResult)(result, state, config.phases.length));
32
+ if (result.mechanicalPassed < result.mechanicalTotal) {
33
+ process.exit(1);
34
+ }
35
+ }
36
+ catch (e) {
37
+ console.error(e instanceof Error ? e.message : String(e));
38
+ process.exit(1);
39
+ }
40
+ }
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatInit = formatInit;
4
+ exports.formatOverview = formatOverview;
5
+ exports.formatPhaseShow = formatPhaseShow;
6
+ exports.formatVerifyResult = formatVerifyResult;
7
+ exports.formatCheckConfirm = formatCheckConfirm;
8
+ exports.formatGateFailure = formatGateFailure;
9
+ exports.formatPhases = formatPhases;
10
+ const state_js_1 = require("./state.js");
11
+ function padDots(left, right, width = 50) {
12
+ const dotsCount = width - left.length - right.length;
13
+ if (dotsCount < 3)
14
+ return `${left} .. ${right}`;
15
+ return `${left} ${'.'.repeat(dotsCount)} ${right}`;
16
+ }
17
+ function formatInit(config, cleared) {
18
+ const total = config.phases.length;
19
+ const phaseList = config.phases
20
+ .map((p, i) => ` ${i}: ${p.name} (${p.checks.length} checks)`)
21
+ .join('\n');
22
+ const header = cleared
23
+ ? `checklist ready, ${total} phases (previous state cleared)`
24
+ : `checklist ready, ${total} phases`;
25
+ return `${header}\n${phaseList}`;
26
+ }
27
+ function formatOverview(config, state) {
28
+ let currentPhase = -1;
29
+ const lines = config.phases.map((phase, i) => {
30
+ const ids = phase.checks.map(c => c.id);
31
+ const complete = (0, state_js_1.isPhaseComplete)(state, i, ids);
32
+ const { done, total } = (0, state_js_1.phaseProgress)(state, i, ids);
33
+ let status;
34
+ if (complete) {
35
+ status = '[x] passed';
36
+ }
37
+ else if (done > 0) {
38
+ status = `[ ] ${done}/${total}`;
39
+ if (currentPhase === -1)
40
+ currentPhase = i;
41
+ }
42
+ else {
43
+ status = '[ ] pending';
44
+ if (currentPhase === -1)
45
+ currentPhase = i;
46
+ }
47
+ return `PHASE ${i}: ${phase.name.toUpperCase().padEnd(20)} ${status}`;
48
+ });
49
+ const allDone = config.phases.every((phase, i) => (0, state_js_1.isPhaseComplete)(state, i, phase.checks.map(c => c.id)));
50
+ if (allDone) {
51
+ lines.push('', 'all phases passed');
52
+ }
53
+ else {
54
+ lines.push('', `current phase: PHASE ${currentPhase}`);
55
+ }
56
+ return lines.join('\n');
57
+ }
58
+ function formatPhaseShow(result, state, totalPhases) {
59
+ const header = `PHASE ${result.phaseIndex}: ${result.phaseName.toUpperCase()}`;
60
+ const items = result.checks.map((c, i) => {
61
+ const checked = (0, state_js_1.isItemChecked)(state, result.phaseIndex, c.item.id);
62
+ const mark = checked ? '[x]' : '[ ]';
63
+ const num = `${i + 1}.`;
64
+ const line = `${num} ${mark} ${padDots(c.item.id, c.item.description)}`;
65
+ if (checked) {
66
+ return line;
67
+ }
68
+ if (c.kind === 'manual') {
69
+ return `${line}\n -> [manual confirmation required]`;
70
+ }
71
+ if (c.result) {
72
+ const reading = c.result.status === 'error'
73
+ ? `[ERROR] ${c.result.message}`
74
+ : `[reading] ${c.result.message}`;
75
+ return `${line}\n -> ${reading}`;
76
+ }
77
+ return line;
78
+ }).join('\n');
79
+ const ids = result.checks.map(c => c.item.id);
80
+ const { done, total } = (0, state_js_1.phaseProgress)(state, result.phaseIndex, ids);
81
+ const lines = [header, '', items, ''];
82
+ if (done === total) {
83
+ const isLast = totalPhases !== undefined && result.phaseIndex >= totalPhases - 1;
84
+ lines.push(isLast
85
+ ? `PHASE ${result.phaseIndex} passed — all phases complete, run \`checklist done\``
86
+ : `PHASE ${result.phaseIndex} passed, proceed to PHASE ${result.phaseIndex + 1}`);
87
+ }
88
+ else {
89
+ lines.push(`${done}/${total} completed`);
90
+ }
91
+ return lines.join('\n');
92
+ }
93
+ function formatVerifyResult(result, state, totalPhases) {
94
+ const header = `PHASE ${result.phaseIndex}: ${result.phaseName.toUpperCase()}`;
95
+ const items = result.checks.map((c, i) => {
96
+ const num = `${i + 1}.`;
97
+ if (c.kind === 'manual') {
98
+ const checked = (0, state_js_1.isItemChecked)(state, result.phaseIndex, c.item.id);
99
+ if (checked) {
100
+ return `${num} [x] ${padDots(c.item.id, 'confirmed')}`;
101
+ }
102
+ return `${num} [ ] ${padDots(c.item.id, c.item.description)}\n -> run: checklist check ${result.phaseIndex} ${c.item.id}`;
103
+ }
104
+ const passed = c.result?.status === 'pass';
105
+ const mark = passed ? '[x]' : '[ ]';
106
+ const suffix = passed ? 'PASS' : `FAIL: ${c.result?.message || 'unknown'}`;
107
+ return `${num} ${mark} ${padDots(c.item.id, suffix)}`;
108
+ }).join('\n');
109
+ const lines = [header, '', items, ''];
110
+ if (result.mechanicalTotal > 0) {
111
+ lines.push(`mechanical: ${result.mechanicalPassed}/${result.mechanicalTotal} passed`);
112
+ }
113
+ if (result.manualCount > 0) {
114
+ const manualChecked = result.checks
115
+ .filter(c => c.kind === 'manual' && (0, state_js_1.isItemChecked)(state, result.phaseIndex, c.item.id))
116
+ .length;
117
+ const remaining = result.manualCount - manualChecked;
118
+ if (remaining > 0) {
119
+ lines.push(`manual: ${remaining} pending`);
120
+ }
121
+ }
122
+ // Explicit verdict so `verify` (the gate command) states pass/proceed itself,
123
+ // instead of requiring a follow-up `show`.
124
+ const ids = result.checks.map(c => c.item.id);
125
+ const { done, total } = (0, state_js_1.phaseProgress)(state, result.phaseIndex, ids);
126
+ // The verify verdict must reflect THIS run, not just stored progress: never
127
+ // announce "verified, proceed" when a mechanical check failed on this run,
128
+ // even if stored state still carries an earlier (now-stale) pass.
129
+ const mechanicalOk = result.mechanicalPassed === result.mechanicalTotal;
130
+ if (mechanicalOk && done === total) {
131
+ const isLast = totalPhases !== undefined && result.phaseIndex >= totalPhases - 1;
132
+ lines.push(isLast
133
+ ? `PHASE ${result.phaseIndex} verified — all phases complete, run \`checklist done\``
134
+ : `PHASE ${result.phaseIndex} verified, proceed to PHASE ${result.phaseIndex + 1}`);
135
+ }
136
+ return lines.join('\n');
137
+ }
138
+ function formatCheckConfirm(phaseIndex, itemId) {
139
+ return `[x] ${itemId} .. confirmed`;
140
+ }
141
+ function formatGateFailure(failedPhase, failedIndex) {
142
+ return `gate blocked: PHASE ${failedIndex} (${failedPhase}) incomplete`;
143
+ }
144
+ function formatPhases(config) {
145
+ return config.phases
146
+ .map((p, i) => `${i}: ${p.name} (${p.checks.length} checks)`)
147
+ .join('\n');
148
+ }