tap-the-sign 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,175 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import {
4
+ FOLLOW_UP_MESSAGE,
5
+ PHASE_DONE,
6
+ PHASE_PLANNING,
7
+ PHASE_PREFLIGHT,
8
+ SENTINEL_DISABLE,
9
+ SENTINEL_ENABLE,
10
+ SENTINEL_STATUS,
11
+ SKILL_MISSING_WARNING,
12
+ } from './constants.mjs';
13
+ import { getEnabledPath } from './paths.mjs';
14
+ import { isThermoSkillInstalled } from './skill-check.mjs';
15
+ import {
16
+ getSessionId,
17
+ readState,
18
+ transitionPhase,
19
+ } from './state.mjs';
20
+
21
+ function readStdin() {
22
+ return fs.readFileSync(0, 'utf8');
23
+ }
24
+
25
+ function isEnabled() {
26
+ return fs.existsSync(getEnabledPath());
27
+ }
28
+
29
+ function isPlanMode(input, host) {
30
+ if (host === 'cursor') {
31
+ return input.composer_mode === 'plan';
32
+ }
33
+ return input.permission_mode === 'plan';
34
+ }
35
+
36
+ function handleToggle(prompt, host) {
37
+ const enabledPath = getEnabledPath();
38
+ const dir = path.dirname(enabledPath);
39
+ fs.mkdirSync(dir, { recursive: true });
40
+
41
+ if (prompt.includes(SENTINEL_ENABLE)) {
42
+ fs.writeFileSync(enabledPath, '1\n');
43
+ return respondToggle(host, 'tap-the-sign hook enabled.');
44
+ }
45
+ if (prompt.includes(SENTINEL_DISABLE)) {
46
+ if (fs.existsSync(enabledPath)) fs.unlinkSync(enabledPath);
47
+ return respondToggle(host, 'tap-the-sign hook disabled.');
48
+ }
49
+ if (prompt.includes(SENTINEL_STATUS)) {
50
+ const status = isEnabled() ? 'enabled' : 'disabled';
51
+ const skill = isThermoSkillInstalled() ? 'installed' : 'missing';
52
+ return respondToggle(
53
+ host,
54
+ `tap-the-sign hook is ${status}. Thermo skill is ${skill}.`,
55
+ );
56
+ }
57
+ return null;
58
+ }
59
+
60
+ function respondToggle(host, message) {
61
+ if (host === 'cursor') {
62
+ return JSON.stringify({ continue: false, user_message: message });
63
+ }
64
+ return JSON.stringify({ decision: 'block', reason: message });
65
+ }
66
+
67
+ function respondEmpty() {
68
+ return '{}';
69
+ }
70
+
71
+ function respondFollowUp(host, message) {
72
+ if (host === 'cursor') {
73
+ return JSON.stringify({ followup_message: message });
74
+ }
75
+ return JSON.stringify({
76
+ decision: 'block',
77
+ reason: message,
78
+ systemMessage: message,
79
+ });
80
+ }
81
+
82
+ function respondWarning(host, warning) {
83
+ console.error(warning);
84
+ if (host === 'cursor') {
85
+ return respondEmpty();
86
+ }
87
+ return JSON.stringify({ systemMessage: warning });
88
+ }
89
+
90
+ export async function runHook({ event, host }) {
91
+ const raw = readStdin();
92
+ let input = {};
93
+ try {
94
+ input = JSON.parse(raw || '{}');
95
+ } catch {
96
+ input = {};
97
+ }
98
+
99
+ const prompt = input.prompt ?? '';
100
+
101
+ const toggleResponse = handleToggle(prompt, host);
102
+ if (toggleResponse) {
103
+ process.stdout.write(toggleResponse);
104
+ return;
105
+ }
106
+
107
+ if (!isEnabled()) {
108
+ process.stdout.write(respondEmpty());
109
+ return;
110
+ }
111
+
112
+ const sessionId = getSessionId(input);
113
+
114
+ if (event === 'arm') {
115
+ if (!isPlanMode(input, host)) {
116
+ process.stdout.write(respondEmpty());
117
+ return;
118
+ }
119
+ transitionPhase(sessionId, PHASE_PLANNING, { host });
120
+ process.stdout.write(respondEmpty());
121
+ return;
122
+ }
123
+
124
+ if (event === 'stop') {
125
+ const status = input.status ?? 'completed';
126
+ if (status !== 'completed') {
127
+ process.stdout.write(respondEmpty());
128
+ return;
129
+ }
130
+
131
+ const state = readState(sessionId);
132
+ const phase = state.phase ?? PHASE_DONE;
133
+
134
+ if (phase === PHASE_PLANNING) {
135
+ if (!isThermoSkillInstalled()) {
136
+ transitionPhase(sessionId, PHASE_DONE);
137
+ process.stdout.write(respondWarning(host, SKILL_MISSING_WARNING));
138
+ return;
139
+ }
140
+ transitionPhase(sessionId, PHASE_PREFLIGHT);
141
+ process.stdout.write(respondFollowUp(host, FOLLOW_UP_MESSAGE));
142
+ return;
143
+ }
144
+
145
+ if (phase === PHASE_PREFLIGHT) {
146
+ transitionPhase(sessionId, PHASE_DONE);
147
+ process.stdout.write(respondEmpty());
148
+ return;
149
+ }
150
+
151
+ process.stdout.write(respondEmpty());
152
+ return;
153
+ }
154
+
155
+ process.stdout.write(respondEmpty());
156
+ }
157
+
158
+ const isDirectRun = process.argv[1]?.includes('run-hook.mjs') ||
159
+ process.argv[1]?.includes('runner.mjs');
160
+
161
+ if (isDirectRun) {
162
+ const args = process.argv.slice(2);
163
+ let event = 'arm';
164
+ let host = 'cursor';
165
+ for (let i = 0; i < args.length; i++) {
166
+ if (args[i] === '--event' && args[i + 1]) event = args[++i];
167
+ if (args[i] === '--host' && args[i + 1]) host = args[++i];
168
+ }
169
+
170
+ runHook({ event, host }).catch((err) => {
171
+ console.error(err);
172
+ process.stdout.write('{}');
173
+ process.exit(1);
174
+ });
175
+ }
@@ -0,0 +1,70 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { SKILL_NAME } from './constants.mjs';
5
+ import { getProjectRoot } from './paths.mjs';
6
+
7
+ function walkForSkill(dir, maxDepth = 6, depth = 0) {
8
+ if (!fs.existsSync(dir) || depth > maxDepth) {
9
+ return null;
10
+ }
11
+
12
+ const skillFile = path.join(
13
+ dir,
14
+ 'skills',
15
+ SKILL_NAME,
16
+ 'SKILL.md',
17
+ );
18
+ if (fs.existsSync(skillFile)) {
19
+ return skillFile;
20
+ }
21
+
22
+ const directSkill = path.join(dir, SKILL_NAME, 'SKILL.md');
23
+ if (fs.existsSync(directSkill)) {
24
+ return directSkill;
25
+ }
26
+
27
+ let entries;
28
+ try {
29
+ entries = fs.readdirSync(dir, { withFileTypes: true });
30
+ } catch {
31
+ return null;
32
+ }
33
+
34
+ for (const entry of entries) {
35
+ if (!entry.isDirectory()) continue;
36
+ if (entry.name === 'node_modules' || entry.name === '.git') continue;
37
+ const found = walkForSkill(path.join(dir, entry.name), maxDepth, depth + 1);
38
+ if (found) return found;
39
+ }
40
+ return null;
41
+ }
42
+
43
+ export function findThermoSkill() {
44
+ const home = os.homedir();
45
+ const projectRoot = getProjectRoot();
46
+
47
+ const searchRoots = [
48
+ path.join(projectRoot, '.agents', 'skills'),
49
+ path.join(projectRoot, '.cursor', 'skills'),
50
+ path.join(projectRoot, '.claude', 'skills'),
51
+ path.join(home, '.cursor', 'skills'),
52
+ path.join(home, '.codex', 'skills'),
53
+ path.join(home, '.cursor', 'plugins'),
54
+ path.join(home, '.claude', 'plugins'),
55
+ path.join(home, '.cursor', 'plugins', 'cache'),
56
+ ];
57
+
58
+ for (const root of searchRoots) {
59
+ const found = walkForSkill(root);
60
+ if (found) {
61
+ return { found: true, path: found };
62
+ }
63
+ }
64
+
65
+ return { found: false, path: null };
66
+ }
67
+
68
+ export function isThermoSkillInstalled() {
69
+ return findThermoSkill().found;
70
+ }
@@ -0,0 +1,48 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import {
4
+ PHASE_DONE,
5
+ PHASE_IDLE,
6
+ PHASE_PLANNING,
7
+ PHASE_PREFLIGHT,
8
+ } from './constants.mjs';
9
+ import { getStateDir } from './paths.mjs';
10
+
11
+ export function getSessionId(input) {
12
+ return (
13
+ input.conversation_id ??
14
+ input.session_id ??
15
+ input.parent_conversation_id ??
16
+ 'unknown'
17
+ );
18
+ }
19
+
20
+ function statePath(sessionId) {
21
+ const safe = sessionId.replace(/[^a-zA-Z0-9._-]/g, '_');
22
+ return path.join(getStateDir(), `${safe}.json`);
23
+ }
24
+
25
+ export function readState(sessionId) {
26
+ const file = statePath(sessionId);
27
+ if (!fs.existsSync(file)) {
28
+ return { phase: PHASE_IDLE };
29
+ }
30
+ try {
31
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
32
+ } catch {
33
+ return { phase: PHASE_IDLE };
34
+ }
35
+ }
36
+
37
+ export function writeState(sessionId, state) {
38
+ const dir = getStateDir();
39
+ fs.mkdirSync(dir, { recursive: true });
40
+ fs.writeFileSync(statePath(sessionId), JSON.stringify(state, null, 2) + '\n');
41
+ }
42
+
43
+ export function transitionPhase(sessionId, phase, extra = {}) {
44
+ const current = readState(sessionId);
45
+ writeState(sessionId, { ...current, phase, ...extra, updatedAt: new Date().toISOString() });
46
+ }
47
+
48
+ export { PHASE_IDLE, PHASE_PLANNING, PHASE_PREFLIGHT, PHASE_DONE };
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env bash
2
+ # Sourced by tap-the-sign hook wrappers.
3
+ HOOKS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
4
+ export TAP_THE_SIGN_ROOT="$HOOKS_DIR"
5
+
6
+ if [[ -n "${TAP_THE_SIGN_GLOBAL:-}" ]]; then
7
+ export TAP_THE_SIGN_GLOBAL=1
8
+ export TAP_THE_SIGN_PROJECT_ROOT="${HOME}"
9
+ elif [[ -n "${CURSOR_PROJECT_DIR:-}" ]]; then
10
+ export TAP_THE_SIGN_PROJECT_ROOT="${CURSOR_PROJECT_DIR}"
11
+ elif [[ -n "${CLAUDE_PROJECT_DIR:-}" ]]; then
12
+ export TAP_THE_SIGN_PROJECT_ROOT="${CLAUDE_PROJECT_DIR}"
13
+ elif [[ -n "${CODEX_PROJECT_DIR:-}" ]]; then
14
+ export TAP_THE_SIGN_PROJECT_ROOT="${CODEX_PROJECT_DIR}"
15
+ elif [[ -f "${HOOKS_DIR}/tap-the-sign.env" ]]; then
16
+ # shellcheck source=/dev/null
17
+ source "${HOOKS_DIR}/tap-the-sign.env"
18
+ elif [[ -f "${HOOKS_DIR}/plan-sandwich.env" ]]; then
19
+ # Legacy env from plan-sandwich installs
20
+ # shellcheck source=/dev/null
21
+ source "${HOOKS_DIR}/plan-sandwich.env"
22
+ else
23
+ export TAP_THE_SIGN_PROJECT_ROOT="$(pwd)"
24
+ fi
25
+
26
+ # Prefer Bun when available (faster cold start); Node 18+ is the fallback.
27
+ if command -v bun >/dev/null 2>&1; then
28
+ export TAP_THE_SIGN_RUNTIME=bun
29
+ else
30
+ export TAP_THE_SIGN_RUNTIME=node
31
+ fi
package/install.bun.sh ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # tap-the-sign Bun installer (from repo clone)
5
+ # Usage: ./install.bun.sh [--global] [--no-claude] [--no-codex]
6
+ #
7
+ # One-liner without cloning (after publish to npm):
8
+ # bunx tap-the-sign install
9
+ # bunx tap-the-sign install-thermo
10
+ # bunx tap-the-sign on
11
+
12
+ REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
13
+ cd "$REPO_ROOT"
14
+
15
+ if ! command -v bun >/dev/null 2>&1; then
16
+ echo "error: Bun is required (https://bun.sh)" >&2
17
+ exit 1
18
+ fi
19
+
20
+ bun scripts/sync-hooks-bin.mjs
21
+ bun src/cli.mjs install "$@"
22
+
23
+ echo ""
24
+ echo "Next steps:"
25
+ echo " bun src/cli.mjs install-thermo"
26
+ echo " bun src/cli.mjs on # or: bunx tap-the-sign on"
27
+ echo " bun src/cli.mjs doctor # verify thermo skill"
package/install.sh ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # tap-the-sign curl installer
5
+ # Usage: curl -fsSL https://raw.githubusercontent.com/your-org/tap-the-sign/main/install.sh | bash
6
+ # or: ./install.sh [--global] [--no-claude] [--no-codex]
7
+
8
+ REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9
+ cd "$REPO_ROOT"
10
+
11
+ RUNTIME=node
12
+ if command -v bun >/dev/null 2>&1; then
13
+ RUNTIME=bun
14
+ elif ! command -v node >/dev/null 2>&1; then
15
+ echo "error: Node.js 18+ or Bun is required" >&2
16
+ echo " Node: https://nodejs.org" >&2
17
+ echo " Bun: https://bun.sh (or use ./install.bun.sh)" >&2
18
+ exit 1
19
+ fi
20
+
21
+ "$RUNTIME" scripts/sync-hooks-bin.mjs
22
+ "$RUNTIME" src/cli.mjs install "$@"
23
+
24
+ echo ""
25
+ echo "Next steps:"
26
+ echo " $RUNTIME src/cli.mjs install-thermo"
27
+ echo " $RUNTIME src/cli.mjs on # or: npx tap-the-sign on / bunx tap-the-sign on"
28
+ echo " $RUNTIME src/cli.mjs doctor # verify thermo skill"
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "tap-the-sign",
3
+ "version": "0.2.0",
4
+ "description": "Auto thermo sign-off after Plan mode plans. Requires thermo-nuclear-code-quality-review skill.",
5
+ "type": "module",
6
+ "bin": {
7
+ "tap-the-sign": "./src/cli.mjs"
8
+ },
9
+ "files": [
10
+ "src/",
11
+ "hooks-bin/",
12
+ "commands/",
13
+ ".cursor-plugin/",
14
+ ".claude-plugin/",
15
+ ".codex-plugin/",
16
+ "hooks/",
17
+ "install.sh",
18
+ "install.bun.sh",
19
+ "scripts/",
20
+ "README.md",
21
+ "docs/",
22
+ "LICENSE"
23
+ ],
24
+ "engines": {
25
+ "node": ">=18",
26
+ "bun": ">=1.0.0"
27
+ },
28
+ "scripts": {
29
+ "prepare": "node scripts/sync-hooks-bin.mjs",
30
+ "sync-runtime": "node scripts/sync-hooks-bin.mjs",
31
+ "test": "node test/smoke.test.mjs",
32
+ "test:bun": "bun test/smoke.test.mjs"
33
+ },
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/your-org/tap-the-sign.git"
37
+ },
38
+ "homepage": "https://github.com/your-org/tap-the-sign#readme",
39
+ "bugs": {
40
+ "url": "https://github.com/your-org/tap-the-sign/issues"
41
+ },
42
+ "license": "MIT",
43
+ "keywords": [
44
+ "cursor",
45
+ "claude-code",
46
+ "codex",
47
+ "hooks",
48
+ "plan-mode",
49
+ "thermonuclear",
50
+ "tap-the-sign"
51
+ ]
52
+ }
@@ -0,0 +1,20 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+
5
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
6
+ const dest = path.join(root, 'hooks-bin');
7
+
8
+ const copies = [
9
+ ['src/hooks/runner.mjs', 'run-hook.mjs'],
10
+ ['src/constants.mjs', 'constants.mjs'],
11
+ ['src/paths.mjs', 'paths.mjs'],
12
+ ['src/state.mjs', 'state.mjs'],
13
+ ['src/skill-check.mjs', 'skill-check.mjs'],
14
+ ];
15
+
16
+ for (const [from, to] of copies) {
17
+ fs.copyFileSync(path.join(root, from), path.join(dest, to));
18
+ }
19
+
20
+ console.log('Synced hook runtime into hooks-bin/');
package/src/cli.mjs ADDED
@@ -0,0 +1,133 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { install } from './install.mjs';
5
+ import { installThermo } from './install-thermo.mjs';
6
+ import { getConfigRoots, getEnabledPath, setInstallScope } from './paths.mjs';
7
+ import { findThermoSkill } from './skill-check.mjs';
8
+ import { uninstall } from './uninstall.mjs';
9
+
10
+ function parseFlags(argv) {
11
+ const flags = {
12
+ global: false,
13
+ cursor: true,
14
+ claude: true,
15
+ codex: true,
16
+ projectRoot: null,
17
+ fix: false,
18
+ };
19
+ for (let i = 0; i < argv.length; i++) {
20
+ const arg = argv[i];
21
+ if (arg === '--global') flags.global = true;
22
+ if (arg === '--project') flags.global = false;
23
+ if (arg === '--no-cursor') flags.cursor = false;
24
+ if (arg === '--no-claude') flags.claude = false;
25
+ if (arg === '--no-codex') flags.codex = false;
26
+ if (arg === '--fix') flags.fix = true;
27
+ if (arg === '--project-root' && argv[i + 1]) {
28
+ flags.projectRoot = argv[++i];
29
+ }
30
+ }
31
+ return flags;
32
+ }
33
+
34
+ function cmdOn(flags) {
35
+ setInstallScope({ global: flags.global, projectRoot: flags.projectRoot });
36
+ const enabled = getEnabledPath();
37
+ fs.mkdirSync(path.dirname(enabled), { recursive: true });
38
+ fs.writeFileSync(enabled, '1\n');
39
+ console.log(`tap-the-sign enabled (${flags.global ? 'global' : 'project'}).`);
40
+ }
41
+
42
+ function cmdOff(flags) {
43
+ setInstallScope({ global: flags.global, projectRoot: flags.projectRoot });
44
+ const enabled = getEnabledPath();
45
+ if (fs.existsSync(enabled)) fs.unlinkSync(enabled);
46
+ console.log(`tap-the-sign disabled (${flags.global ? 'global' : 'project'}).`);
47
+ }
48
+
49
+ function cmdStatus(flags) {
50
+ setInstallScope({ global: flags.global, projectRoot: flags.projectRoot });
51
+ const roots = getConfigRoots();
52
+ const enabled = fs.existsSync(getEnabledPath());
53
+ const skill = findThermoSkill();
54
+ console.log('tap-the-sign status');
55
+ console.log(` scope: ${flags.global ? 'global' : 'project'}`);
56
+ console.log(` project root: ${roots.projectRoot}`);
57
+ console.log(` hook: ${enabled ? 'enabled' : 'disabled'}`);
58
+ console.log(
59
+ ` thermo skill: ${skill.found ? `found at ${skill.path}` : 'NOT FOUND'}`,
60
+ );
61
+ }
62
+
63
+ function cmdDoctor(flags) {
64
+ cmdStatus(flags);
65
+ const skill = findThermoSkill();
66
+ if (!skill.found) {
67
+ console.log('');
68
+ if (flags.fix) {
69
+ const ok = installThermo({ global: flags.global });
70
+ process.exitCode = ok ? 0 : 1;
71
+ return;
72
+ }
73
+ console.log('Action required: install thermo-nuclear-code-quality-review');
74
+ console.log(' tap-the-sign install-thermo');
75
+ console.log(' tap-the-sign doctor --fix');
76
+ console.log(' /add-plugin cursor-team-kit (full plugin + subagent)');
77
+ console.log('Without the skill, planning works but auto pre-flight is skipped.');
78
+ process.exitCode = 1;
79
+ }
80
+ }
81
+
82
+ function cmdInstallThermo(flags) {
83
+ const ok = installThermo({ global: flags.global });
84
+ process.exitCode = ok ? 0 : 1;
85
+ }
86
+
87
+ function printHelp() {
88
+ console.log(`tap-the-sign — thermo sign-off hook for Plan mode
89
+
90
+ Usage:
91
+ tap-the-sign install [--global] [--no-claude] [--no-codex] [--no-cursor]
92
+ tap-the-sign uninstall [--global] [...]
93
+ tap-the-sign install-thermo [--global]
94
+ tap-the-sign on|off|status|doctor [--global] [--fix]
95
+
96
+ Defaults: project-local install, all three IDEs.
97
+ `);
98
+ }
99
+
100
+ const [subcommand, ...rest] = process.argv.slice(2);
101
+ const flags = parseFlags(rest);
102
+
103
+ switch (subcommand) {
104
+ case 'install':
105
+ install(flags);
106
+ console.log('tap-the-sign hooks installed.');
107
+ console.log('Run: tap-the-sign install-thermo');
108
+ console.log('Run: tap-the-sign on');
109
+ console.log('Run: tap-the-sign doctor');
110
+ break;
111
+ case 'uninstall':
112
+ uninstall(flags);
113
+ console.log('tap-the-sign hooks uninstalled.');
114
+ break;
115
+ case 'install-thermo':
116
+ cmdInstallThermo(flags);
117
+ break;
118
+ case 'on':
119
+ cmdOn(flags);
120
+ break;
121
+ case 'off':
122
+ cmdOff(flags);
123
+ break;
124
+ case 'status':
125
+ cmdStatus(flags);
126
+ break;
127
+ case 'doctor':
128
+ cmdDoctor(flags);
129
+ break;
130
+ default:
131
+ printHelp();
132
+ if (subcommand) process.exitCode = 1;
133
+ }
@@ -0,0 +1,33 @@
1
+ export const SKILL_NAME = 'thermo-nuclear-code-quality-review';
2
+
3
+ export const SENTINEL_ENABLE = '<!-- TAP_THE_SIGN_ENABLE -->';
4
+ export const SENTINEL_DISABLE = '<!-- TAP_THE_SIGN_DISABLE -->';
5
+ export const SENTINEL_STATUS = '<!-- TAP_THE_SIGN_STATUS -->';
6
+
7
+ export const PHASE_IDLE = 'idle';
8
+ export const PHASE_PLANNING = 'planning';
9
+ export const PHASE_PREFLIGHT = 'preflight';
10
+ export const PHASE_DONE = 'done';
11
+
12
+ export const TAP_THE_SIGN_MARKER = '_tapTheSign';
13
+ export const LEGACY_MARKERS = ['_planSandwich', TAP_THE_SIGN_MARKER];
14
+
15
+ export const FOLLOW_UP_MESSAGE = `@thermo-nuclear-code-quality-review
16
+
17
+ Read and apply the full rubric from the thermo-nuclear-code-quality-review skill
18
+ (code judo, 1k-line rule, spaghetti growth, HIGH/MID/LOW bar) to **this plan**
19
+ (not a diff yet).
20
+
21
+ Will this pass the next thermonuclear code review with no new items (especially HIGH or MID)?
22
+ Did you find all the code judo opportunities?
23
+ What changes would you make to improve confidence to high that this plan would pass
24
+ thermonuclear code review cleanly?
25
+ Include a **Thermonuclear pre-flight** section with this assessment in the plan.
26
+ Be careful to not introduce any blocker higher than LOW and checking three times
27
+ (three separate passes) for code judo opportunities.
28
+ On Pass 3: Thermo-nuclear subagent on final diff; zero HIGH/MID.`;
29
+
30
+ export const SKILL_MISSING_WARNING =
31
+ 'tap-the-sign: thermo-nuclear-code-quality-review skill not found. ' +
32
+ 'Run: tap-the-sign install-thermo (or /add-plugin cursor-team-kit). ' +
33
+ 'Skipping auto pre-flight follow-up.';