safeword 0.6.9 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{check-OYYSYHFP.js → check-QGZJ62PY.js} +73 -57
- package/dist/check-QGZJ62PY.js.map +1 -0
- package/dist/{chunk-ZS3Z3Q37.js → chunk-QPO3C3FP.js} +285 -65
- package/dist/chunk-QPO3C3FP.js.map +1 -0
- package/dist/{chunk-LNSEDZIW.js → chunk-YMLVQC4V.js} +159 -152
- package/dist/chunk-YMLVQC4V.js.map +1 -0
- package/dist/cli.js +6 -6
- package/dist/{diff-325TIZ63.js → diff-654SSCFQ.js} +51 -53
- package/dist/diff-654SSCFQ.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/{reset-ZGJIKMUW.js → reset-IU6AIT7C.js} +3 -3
- package/dist/{setup-GAMXTFM2.js → setup-5IQ4KV2M.js} +17 -20
- package/dist/setup-5IQ4KV2M.js.map +1 -0
- package/dist/{sync-BFMXZEHM.js → sync-YBQEISFI.js} +8 -26
- package/dist/sync-YBQEISFI.js.map +1 -0
- package/dist/{upgrade-X4GREJXN.js → upgrade-RRTWEQIP.js} +3 -3
- package/package.json +1 -1
- package/templates/SAFEWORD.md +52 -15
- package/templates/commands/architecture.md +1 -1
- package/templates/commands/lint.md +1 -0
- package/templates/commands/quality-review.md +1 -1
- package/templates/cursor/rules/safeword-core.mdc +5 -0
- package/templates/doc-templates/architecture-template.md +1 -1
- package/templates/doc-templates/task-spec-template.md +151 -0
- package/templates/doc-templates/ticket-template.md +2 -4
- package/templates/guides/architecture-guide.md +2 -2
- package/templates/guides/code-philosophy.md +1 -1
- package/templates/guides/context-files-guide.md +3 -3
- package/templates/guides/design-doc-guide.md +2 -2
- package/templates/guides/development-workflow.md +2 -2
- package/templates/guides/learning-extraction.md +9 -9
- package/templates/guides/tdd-best-practices.md +39 -38
- package/templates/guides/test-definitions-guide.md +15 -14
- package/templates/hooks/cursor/after-file-edit.sh +66 -0
- package/templates/hooks/cursor/stop.sh +50 -0
- package/templates/hooks/post-tool-lint.sh +19 -5
- package/templates/hooks/prompt-questions.sh +1 -1
- package/templates/hooks/session-lint-check.sh +1 -1
- package/templates/hooks/session-verify-agents.sh +1 -1
- package/templates/hooks/session-version.sh +1 -1
- package/templates/hooks/stop-quality.sh +1 -1
- package/templates/markdownlint-cli2.jsonc +18 -19
- package/templates/scripts/bisect-test-pollution.sh +87 -0
- package/templates/scripts/bisect-zombie-processes.sh +129 -0
- package/templates/scripts/lint-md.sh +16 -0
- package/templates/skills/safeword-quality-reviewer/SKILL.md +3 -3
- package/templates/skills/safeword-systematic-debugger/SKILL.md +246 -0
- package/templates/skills/safeword-tdd-enforcer/SKILL.md +221 -0
- package/dist/check-OYYSYHFP.js.map +0 -1
- package/dist/chunk-LNSEDZIW.js.map +0 -1
- package/dist/chunk-ZS3Z3Q37.js.map +0 -1
- package/dist/diff-325TIZ63.js.map +0 -1
- package/dist/setup-GAMXTFM2.js.map +0 -1
- package/dist/sync-BFMXZEHM.js.map +0 -1
- /package/dist/{reset-ZGJIKMUW.js.map → reset-IU6AIT7C.js.map} +0 -0
- /package/dist/{upgrade-X4GREJXN.js.map → upgrade-RRTWEQIP.js.map} +0 -0
|
@@ -9,18 +9,43 @@ import {
|
|
|
9
9
|
reconcile,
|
|
10
10
|
success,
|
|
11
11
|
warn
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-YMLVQC4V.js";
|
|
13
13
|
import {
|
|
14
14
|
SAFEWORD_SCHEMA,
|
|
15
15
|
exists,
|
|
16
16
|
readFileSafe
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-QPO3C3FP.js";
|
|
18
18
|
import {
|
|
19
19
|
VERSION
|
|
20
20
|
} from "./chunk-ORQHKDT2.js";
|
|
21
21
|
|
|
22
22
|
// src/commands/check.ts
|
|
23
23
|
import { join } from "path";
|
|
24
|
+
function findMissingFiles(cwd, actions) {
|
|
25
|
+
const issues = [];
|
|
26
|
+
for (const action of actions) {
|
|
27
|
+
if (action.type === "write" && !exists(join(cwd, action.path))) {
|
|
28
|
+
issues.push(`Missing: ${action.path}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return issues;
|
|
32
|
+
}
|
|
33
|
+
function findMissingPatches(cwd, actions) {
|
|
34
|
+
const issues = [];
|
|
35
|
+
for (const action of actions) {
|
|
36
|
+
if (action.type !== "text-patch") continue;
|
|
37
|
+
const fullPath = join(cwd, action.path);
|
|
38
|
+
if (!exists(fullPath)) {
|
|
39
|
+
issues.push(`${action.path} file missing`);
|
|
40
|
+
} else {
|
|
41
|
+
const content = readFileSafe(fullPath) ?? "";
|
|
42
|
+
if (action.definition && !content.includes(action.definition.marker)) {
|
|
43
|
+
issues.push(`${action.path} missing safeword link`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return issues;
|
|
48
|
+
}
|
|
24
49
|
async function checkLatestVersion(timeout = 3e3) {
|
|
25
50
|
try {
|
|
26
51
|
const controller = new AbortController();
|
|
@@ -53,32 +78,11 @@ async function checkHealth(cwd) {
|
|
|
53
78
|
const projectVersion = readFileSafe(versionPath)?.trim() ?? null;
|
|
54
79
|
const ctx = createProjectContext(cwd);
|
|
55
80
|
const result = await reconcile(SAFEWORD_SCHEMA, "upgrade", ctx, { dryRun: true });
|
|
56
|
-
const issues = [
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (!exists(fullPath)) {
|
|
62
|
-
issues.push(`Missing: ${action.path}`);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
const textPatchActions = result.actions.filter((a) => a.type === "text-patch");
|
|
67
|
-
for (const action of textPatchActions) {
|
|
68
|
-
if (action.type === "text-patch") {
|
|
69
|
-
const fullPath = join(cwd, action.path);
|
|
70
|
-
if (!exists(fullPath)) {
|
|
71
|
-
issues.push(`${action.path} file missing`);
|
|
72
|
-
} else {
|
|
73
|
-
const content = readFileSafe(fullPath) ?? "";
|
|
74
|
-
if (!content.includes(action.definition.marker)) {
|
|
75
|
-
issues.push(`${action.path} missing safeword link`);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
const settingsPath = join(cwd, ".claude", "settings.json");
|
|
81
|
-
if (!exists(settingsPath)) {
|
|
81
|
+
const issues = [
|
|
82
|
+
...findMissingFiles(cwd, result.actions),
|
|
83
|
+
...findMissingPatches(cwd, result.actions)
|
|
84
|
+
];
|
|
85
|
+
if (!exists(join(cwd, ".claude", "settings.json"))) {
|
|
82
86
|
issues.push("Missing: .claude/settings.json");
|
|
83
87
|
}
|
|
84
88
|
return {
|
|
@@ -91,59 +95,71 @@ async function checkHealth(cwd) {
|
|
|
91
95
|
missingPackages: result.packagesToInstall
|
|
92
96
|
};
|
|
93
97
|
}
|
|
94
|
-
async function
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
info("Not configured. Run `safeword setup` to initialize.");
|
|
98
|
+
async function reportUpdateStatus(health) {
|
|
99
|
+
info("\nChecking for updates...");
|
|
100
|
+
const latestVersion = await checkLatestVersion();
|
|
101
|
+
if (!latestVersion) {
|
|
102
|
+
warn("Couldn't check for updates (offline?)");
|
|
100
103
|
return;
|
|
101
104
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if (
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (latestVersion) {
|
|
108
|
-
health.latestVersion = latestVersion;
|
|
109
|
-
health.updateAvailable = isNewerVersion(health.cliVersion, latestVersion);
|
|
110
|
-
if (health.updateAvailable) {
|
|
111
|
-
warn(`Update available: v${latestVersion}`);
|
|
112
|
-
info("Run `npm install -g safeword` to upgrade");
|
|
113
|
-
} else {
|
|
114
|
-
success("CLI is up to date");
|
|
115
|
-
}
|
|
116
|
-
} else {
|
|
117
|
-
warn("Couldn't check for updates (offline?)");
|
|
118
|
-
}
|
|
105
|
+
health.latestVersion = latestVersion;
|
|
106
|
+
health.updateAvailable = isNewerVersion(health.cliVersion, latestVersion);
|
|
107
|
+
if (health.updateAvailable) {
|
|
108
|
+
warn(`Update available: v${latestVersion}`);
|
|
109
|
+
info("Run `npm install -g safeword` to upgrade");
|
|
119
110
|
} else {
|
|
120
|
-
|
|
111
|
+
success("CLI is up to date");
|
|
121
112
|
}
|
|
122
|
-
|
|
113
|
+
}
|
|
114
|
+
function reportVersionMismatch(health) {
|
|
115
|
+
if (!health.projectVersion) return;
|
|
116
|
+
if (isNewerVersion(health.cliVersion, health.projectVersion)) {
|
|
123
117
|
warn(`Project config (v${health.projectVersion}) is newer than CLI (v${health.cliVersion})`);
|
|
124
118
|
info("Consider upgrading the CLI");
|
|
125
|
-
} else if (
|
|
119
|
+
} else if (isNewerVersion(health.projectVersion, health.cliVersion)) {
|
|
126
120
|
info(`
|
|
127
121
|
Upgrade available for project config`);
|
|
128
122
|
info(
|
|
129
123
|
`Run \`safeword upgrade\` to update from v${health.projectVersion} to v${health.cliVersion}`
|
|
130
124
|
);
|
|
131
125
|
}
|
|
126
|
+
}
|
|
127
|
+
function reportHealthSummary(health) {
|
|
132
128
|
if (health.issues.length > 0) {
|
|
133
129
|
header("Issues Found");
|
|
134
130
|
for (const issue of health.issues) {
|
|
135
131
|
warn(issue);
|
|
136
132
|
}
|
|
137
133
|
info("\nRun `safeword upgrade` to repair configuration");
|
|
138
|
-
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (health.missingPackages.length > 0) {
|
|
139
137
|
header("Missing Packages");
|
|
140
138
|
info(`${health.missingPackages.length} linting packages not installed`);
|
|
141
139
|
info("Run `safeword sync` to install missing packages");
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
success("\nConfiguration is healthy");
|
|
143
|
+
}
|
|
144
|
+
async function check(options) {
|
|
145
|
+
const cwd = process.cwd();
|
|
146
|
+
header("Safeword Health Check");
|
|
147
|
+
const health = await checkHealth(cwd);
|
|
148
|
+
if (!health.configured) {
|
|
149
|
+
info("Not configured. Run `safeword setup` to initialize.");
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
keyValue("Safeword CLI", `v${health.cliVersion}`);
|
|
153
|
+
keyValue("Project config", health.projectVersion ? `v${health.projectVersion}` : "unknown");
|
|
154
|
+
if (options.offline) {
|
|
155
|
+
info("\nSkipped update check (offline mode)");
|
|
142
156
|
} else {
|
|
143
|
-
|
|
157
|
+
await reportUpdateStatus(health);
|
|
144
158
|
}
|
|
159
|
+
reportVersionMismatch(health);
|
|
160
|
+
reportHealthSummary(health);
|
|
145
161
|
}
|
|
146
162
|
export {
|
|
147
163
|
check
|
|
148
164
|
};
|
|
149
|
-
//# sourceMappingURL=check-
|
|
165
|
+
//# sourceMappingURL=check-QGZJ62PY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/check.ts"],"sourcesContent":["/**\n * Check command - Verify project health and configuration\n *\n * Uses reconcile() with dryRun to detect missing files and configuration issues.\n */\n\nimport { join } from 'node:path';\nimport { VERSION } from '../version.js';\nimport { exists, readFileSafe } from '../utils/fs.js';\nimport { info, success, warn, header, keyValue } from '../utils/output.js';\nimport { isNewerVersion } from '../utils/version.js';\nimport { createProjectContext } from '../utils/context.js';\nimport { reconcile } from '../reconcile.js';\nimport { SAFEWORD_SCHEMA } from '../schema.js';\n\nexport interface CheckOptions {\n offline?: boolean;\n}\n\n/** Check for missing files from write actions */\nfunction findMissingFiles(cwd: string, actions: { type: string; path: string }[]): string[] {\n const issues: string[] = [];\n for (const action of actions) {\n if (action.type === 'write' && !exists(join(cwd, action.path))) {\n issues.push(`Missing: ${action.path}`);\n }\n }\n return issues;\n}\n\n/** Check for missing text patch markers */\nfunction findMissingPatches(\n cwd: string,\n actions: { type: string; path: string; definition?: { marker: string } }[],\n): string[] {\n const issues: string[] = [];\n for (const action of actions) {\n if (action.type !== 'text-patch') continue;\n\n const fullPath = join(cwd, action.path);\n if (!exists(fullPath)) {\n issues.push(`${action.path} file missing`);\n } else {\n const content = readFileSafe(fullPath) ?? '';\n if (action.definition && !content.includes(action.definition.marker)) {\n issues.push(`${action.path} missing safeword link`);\n }\n }\n }\n return issues;\n}\n\ninterface HealthStatus {\n configured: boolean;\n projectVersion: string | null;\n cliVersion: string;\n updateAvailable: boolean;\n latestVersion: string | null;\n issues: string[];\n missingPackages: string[];\n}\n\n/**\n * Check for latest version from npm (with timeout)\n */\nasync function checkLatestVersion(timeout = 3000): Promise<string | null> {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n const response = await fetch('https://registry.npmjs.org/safeword/latest', {\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) return null;\n\n const data = (await response.json()) as { version?: string };\n return data.version ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Check project configuration health using reconcile dryRun\n */\nasync function checkHealth(cwd: string): Promise<HealthStatus> {\n const safewordDir = join(cwd, '.safeword');\n\n // Check if configured\n if (!exists(safewordDir)) {\n return {\n configured: false,\n projectVersion: null,\n cliVersion: VERSION,\n updateAvailable: false,\n latestVersion: null,\n issues: [],\n missingPackages: [],\n };\n }\n\n // Read project version\n const versionPath = join(safewordDir, 'version');\n const projectVersion = readFileSafe(versionPath)?.trim() ?? null;\n\n // Use reconcile with dryRun to detect issues\n const ctx = createProjectContext(cwd);\n const result = await reconcile(SAFEWORD_SCHEMA, 'upgrade', ctx, { dryRun: true });\n\n // Collect issues from write actions and text patches\n const issues: string[] = [\n ...findMissingFiles(cwd, result.actions),\n ...findMissingPatches(cwd, result.actions),\n ];\n\n // Check for missing .claude/settings.json\n if (!exists(join(cwd, '.claude', 'settings.json'))) {\n issues.push('Missing: .claude/settings.json');\n }\n\n return {\n configured: true,\n projectVersion,\n cliVersion: VERSION,\n updateAvailable: false,\n latestVersion: null,\n issues,\n missingPackages: result.packagesToInstall,\n };\n}\n\n/** Check for CLI updates and report status */\nasync function reportUpdateStatus(health: HealthStatus): Promise<void> {\n info('\\nChecking for updates...');\n const latestVersion = await checkLatestVersion();\n\n if (!latestVersion) {\n warn(\"Couldn't check for updates (offline?)\");\n return;\n }\n\n health.latestVersion = latestVersion;\n health.updateAvailable = isNewerVersion(health.cliVersion, latestVersion);\n\n if (health.updateAvailable) {\n warn(`Update available: v${latestVersion}`);\n info('Run `npm install -g safeword` to upgrade');\n } else {\n success('CLI is up to date');\n }\n}\n\n/** Compare project version vs CLI version and report */\nfunction reportVersionMismatch(health: HealthStatus): void {\n if (!health.projectVersion) return;\n\n if (isNewerVersion(health.cliVersion, health.projectVersion)) {\n warn(`Project config (v${health.projectVersion}) is newer than CLI (v${health.cliVersion})`);\n info('Consider upgrading the CLI');\n } else if (isNewerVersion(health.projectVersion, health.cliVersion)) {\n info(`\\nUpgrade available for project config`);\n info(\n `Run \\`safeword upgrade\\` to update from v${health.projectVersion} to v${health.cliVersion}`,\n );\n }\n}\n\n/** Report issues or success */\nfunction reportHealthSummary(health: HealthStatus): void {\n if (health.issues.length > 0) {\n header('Issues Found');\n for (const issue of health.issues) {\n warn(issue);\n }\n info('\\nRun `safeword upgrade` to repair configuration');\n return;\n }\n\n if (health.missingPackages.length > 0) {\n header('Missing Packages');\n info(`${health.missingPackages.length} linting packages not installed`);\n info('Run `safeword sync` to install missing packages');\n return;\n }\n\n success('\\nConfiguration is healthy');\n}\n\nexport async function check(options: CheckOptions): Promise<void> {\n const cwd = process.cwd();\n\n header('Safeword Health Check');\n\n const health = await checkHealth(cwd);\n\n // Not configured\n if (!health.configured) {\n info('Not configured. Run `safeword setup` to initialize.');\n return;\n }\n\n // Show versions\n keyValue('Safeword CLI', `v${health.cliVersion}`);\n keyValue('Project config', health.projectVersion ? `v${health.projectVersion}` : 'unknown');\n\n // Check for updates (unless offline)\n if (options.offline) {\n info('\\nSkipped update check (offline mode)');\n } else {\n await reportUpdateStatus(health);\n }\n\n reportVersionMismatch(health);\n reportHealthSummary(health);\n}\n"],"mappings":"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","names":[]}
|