create-harness-vibe-coding 0.8.4 → 0.8.5
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/package.json
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: wf-remove
|
|
3
|
-
description: Use for /wf-remove in Claude Code, $wf-remove or /skills wf-remove in Codex, or any request to uninstall Harness safely.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# WF Remove Adapter
|
|
7
|
-
|
|
1
|
+
---
|
|
2
|
+
name: wf-remove
|
|
3
|
+
description: Use for /wf-remove in Claude Code, $wf-remove or /skills wf-remove in Codex, or any request to uninstall Harness safely.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# WF Remove Adapter
|
|
7
|
+
|
|
8
8
|
## Invocation
|
|
9
9
|
|
|
10
10
|
- Claude Code: use `/wf-remove` or select the `wf-remove` skill.
|
|
11
11
|
- Codex CLI or IDE: use `$wf-remove` or `/skills` then choose `wf-remove`.
|
|
12
|
+
- User-facing removal is the slash/skill command. The Node commands below are
|
|
13
|
+
agent-internal execution steps; do not ask the user to copy/paste them unless
|
|
14
|
+
the agent has no shell/tool access.
|
|
12
15
|
|
|
13
16
|
## Load
|
|
14
17
|
|
|
@@ -17,21 +20,31 @@ description: Use for /wf-remove in Claude Code, $wf-remove or /skills wf-remove
|
|
|
17
20
|
|
|
18
21
|
## Flow
|
|
19
22
|
|
|
20
|
-
1.
|
|
21
|
-
plan.
|
|
22
|
-
2. Auto-remove only SAFE files that still match stored checksums
|
|
23
|
+
1. On plain `/wf-remove`, run `node Harness/scripts/wf-remove.mjs --json` for
|
|
24
|
+
the machine-readable plan, then run the safe default apply command yourself.
|
|
25
|
+
2. Auto-remove only SAFE files that still match stored checksums or exact
|
|
26
|
+
built-in Harness discovery files recognized by the script.
|
|
23
27
|
3. Ask the user before every MODIFIED or uncertain file.
|
|
24
28
|
4. Preserve USER DATA by default. For an explicit thorough uninstall, use
|
|
25
29
|
`--purge-user-data` (alias `--purge`); add `--keep-tasks` when the user wants task records
|
|
26
30
|
retained while project-fact Harness docs are removed.
|
|
27
|
-
5. Run the script, not manual deletes:
|
|
31
|
+
5. Run the script yourself, not manual deletes and not user-side command copy:
|
|
28
32
|
- safe default: `node Harness/scripts/wf-remove.mjs --apply --yes`
|
|
29
33
|
- thorough but keep tasks: `node Harness/scripts/wf-remove.mjs --apply --yes --purge-user-data --keep-tasks`
|
|
30
34
|
- exact modified decisions: add `--delete-modified <path>` for each
|
|
31
35
|
user-approved MODIFIED file.
|
|
36
|
+
6. After apply, verify residual discovery folders:
|
|
37
|
+
- `.claude/agents`
|
|
38
|
+
- `.claude/skills`
|
|
39
|
+
- `.claude/commands`
|
|
40
|
+
- `.claude/rules`
|
|
41
|
+
- `.agents/skills`
|
|
42
|
+
- `.codex`
|
|
43
|
+
Built-in Harness files in these locations should be gone. Custom user skills
|
|
44
|
+
or user-owned files may remain and must be reported, not blindly deleted.
|
|
32
45
|
|
|
33
46
|
## Return
|
|
34
47
|
|
|
35
48
|
Report SAFE removals, MODIFIED keep/delete decisions, preserved USER DATA,
|
|
36
|
-
PURGE removals, directory cleanup,
|
|
37
|
-
status, and `git status` guidance.
|
|
49
|
+
PURGE removals, directory cleanup, `.claude` / `.agents` / `.codex` residual
|
|
50
|
+
status, `.harness-version` status, and `git status` guidance.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"generator": "0.8.
|
|
3
|
-
"generated": "2026-07-
|
|
2
|
+
"generator": "0.8.5",
|
|
3
|
+
"generated": "2026-07-02T10:09:05.492Z",
|
|
4
4
|
"options": [],
|
|
5
5
|
"autoCheck": true,
|
|
6
6
|
"source": "https://raw.githubusercontent.com/zingspark/create-harness-vibe-coding/main/templates/common/",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
".agents/skills/wf-learn/SKILL.md": "sha256-7f3e1ee0aa83cbb76707698d0c26b703ad5c74b2df95a7dc4d751939a4ba05b2",
|
|
13
13
|
".agents/skills/wf-max/SKILL.md": "sha256-9b37cc3385f6d1a285b617169e91fbf71ffec76135b7b46ec1de2fe94ca220da",
|
|
14
14
|
".agents/skills/wf-readme/SKILL.md": "sha256-4d34ee3b6b305fa2581f5d8cb31e9152759f3df8bf8fa08efbb43782f128bdcd",
|
|
15
|
-
".agents/skills/wf-remove/SKILL.md": "sha256-
|
|
15
|
+
".agents/skills/wf-remove/SKILL.md": "sha256-21ebef1a1fa8645d094c8ceeca78b33f036b6c42cda6db8be425d38d9e91af75",
|
|
16
16
|
".agents/skills/wf-review/SKILL.md": "sha256-cc6d536ec6de25546a0ba96e686f195da50ed11bc03763a76ef46d77243d3537",
|
|
17
17
|
".agents/skills/wf-update/SKILL.md": "sha256-d57cd89e271b2af63b6a1264af552a30f8d44959cf4782b42f0ab082a90be9cf",
|
|
18
18
|
".agents/skills/wf/SKILL.md": "sha256-70766bd2cb02bc489b5cc021797af62596a005d444a026abb511054a1a820a67",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
".claude/skills/wf-learn/SKILL.md": "sha256-7f3e1ee0aa83cbb76707698d0c26b703ad5c74b2df95a7dc4d751939a4ba05b2",
|
|
43
43
|
".claude/skills/wf-max/SKILL.md": "sha256-9b37cc3385f6d1a285b617169e91fbf71ffec76135b7b46ec1de2fe94ca220da",
|
|
44
44
|
".claude/skills/wf-readme/SKILL.md": "sha256-4d34ee3b6b305fa2581f5d8cb31e9152759f3df8bf8fa08efbb43782f128bdcd",
|
|
45
|
-
".claude/skills/wf-remove/SKILL.md": "sha256-
|
|
45
|
+
".claude/skills/wf-remove/SKILL.md": "sha256-21ebef1a1fa8645d094c8ceeca78b33f036b6c42cda6db8be425d38d9e91af75",
|
|
46
46
|
".claude/skills/wf-review/SKILL.md": "sha256-cc6d536ec6de25546a0ba96e686f195da50ed11bc03763a76ef46d77243d3537",
|
|
47
47
|
".claude/skills/wf-update/SKILL.md": "sha256-d57cd89e271b2af63b6a1264af552a30f8d44959cf4782b42f0ab082a90be9cf",
|
|
48
48
|
".claude/skills/wf/SKILL.md": "sha256-70766bd2cb02bc489b5cc021797af62596a005d444a026abb511054a1a820a67",
|
|
@@ -70,8 +70,8 @@
|
|
|
70
70
|
"Harness/lifecycle.md": "sha256-a2d025e52f3b4412d8439083aca0d2cf7a4458ad0e30de4fc6465f990379190f",
|
|
71
71
|
"Harness/research/README.md": "sha256-956c154df01cb9376972eb8b88bb3be0fe4e2dda802a72457c0126e3476fa755",
|
|
72
72
|
"Harness/scripts/scan-clean.mjs": "sha256-7f693faf762c9c8e7657143d651f7c8369ed4823f18babe21daec58a55025593",
|
|
73
|
-
"Harness/scripts/validate-harness.mjs": "sha256-
|
|
74
|
-
"Harness/scripts/wf-remove.mjs": "sha256-
|
|
73
|
+
"Harness/scripts/validate-harness.mjs": "sha256-31dc33729034656d24ec163ff310164e2fc77289212b2278ab4a2f3d4b9294dc",
|
|
74
|
+
"Harness/scripts/wf-remove.mjs": "sha256-944e5da9dc1abcfb8f410bca743c3f5fbee2bc74d09b97e04ceaaf53da0cb9f1",
|
|
75
75
|
"Harness/scripts/wf-update-check.mjs": "sha256-d14ce08f4c05ba118362a56a4b7d5965b114bc2b15a023c08e21d57f32b2cf93",
|
|
76
76
|
"Harness/subagents.md": "sha256-16255092bab9011bb67359b4399d27ab292c14a717e67123e8a76e40e8669661",
|
|
77
77
|
"Harness/templates/ACCEPTANCE.template.md": "sha256-394a6c08b155b1d121f1d51da774f7988bdb891224c6d5f2ca2c131e8c95ffb3",
|
|
@@ -541,6 +541,9 @@ requireText('Harness/templates/TEST_PLAN.template.md', 'syntax-only checks', 'te
|
|
|
541
541
|
requireText('.claude/skills/tdd/SKILL.md', 'Harness/ACCEPTANCE_PROTOCOL.md', 'tdd skill loads acceptance protocol');
|
|
542
542
|
requireText('.claude/skills/tdd/SKILL.md', 'Harness/HARNESS_BRIDGE.md', 'tdd skill loads harness bridge');
|
|
543
543
|
requireText('.claude/skills/tdd/SKILL.md', 'No syntax-only acceptance', 'tdd skill forbids syntax-only acceptance');
|
|
544
|
+
requireText('.claude/skills/wf-remove/SKILL.md', 'User-facing removal is the slash/skill command', 'wf-remove slash command is user-facing');
|
|
545
|
+
requireText('.claude/skills/wf-remove/SKILL.md', 'agent-internal execution steps', 'wf-remove script commands are agent-internal');
|
|
546
|
+
requireText('.claude/skills/wf-remove/SKILL.md', 'verify residual discovery folders', 'wf-remove residual discovery verification');
|
|
544
547
|
requireText('.claude/agents/tdd-guide.md', 'Browser Acceptance Rules', 'tdd-guide browser acceptance rules');
|
|
545
548
|
requireText('.claude/agents/tdd-guide.md', 'real user actions', 'tdd-guide real user action requirement');
|
|
546
549
|
requireText('.claude/agents/test-writer.md', 'Harness/ACCEPTANCE_PROTOCOL.md', 'test-writer loads acceptance protocol');
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* wf-remove.mjs
|
|
3
|
+
* wf-remove.mjs �?Safely remove Harness framework files.
|
|
4
4
|
*
|
|
5
5
|
* Classifies all Harness-owned files into:
|
|
6
|
-
* SAFE
|
|
7
|
-
* MODIFIED
|
|
8
|
-
* USER
|
|
6
|
+
* SAFE �?framework files matching stored checksums �?auto-remove
|
|
7
|
+
* MODIFIED �?framework files edited by user �?MUST confirm
|
|
8
|
+
* USER �?user data files �?NEVER remove
|
|
9
9
|
*
|
|
10
10
|
* Usage:
|
|
11
11
|
* node Harness/scripts/wf-remove.mjs # dry-run: show plan
|
|
@@ -23,12 +23,12 @@ import { resolve, dirname, join, sep } from 'path';
|
|
|
23
23
|
import { fileURLToPath } from 'url';
|
|
24
24
|
import { createInterface } from 'readline';
|
|
25
25
|
|
|
26
|
-
const
|
|
26
|
+
const SCRIPT_FILE = fileURLToPath(import.meta.url);
|
|
27
|
+
const __dirname = dirname(SCRIPT_FILE);
|
|
28
|
+
const SCRIPT_ROOT = resolve(__dirname, '..', '..');
|
|
27
29
|
const ROOT = process.env.WF_ROOT
|
|
28
30
|
? resolve(process.env.WF_ROOT)
|
|
29
|
-
:
|
|
30
|
-
? process.cwd()
|
|
31
|
-
: resolve(__dirname, '..', '..'));
|
|
31
|
+
: SCRIPT_ROOT;
|
|
32
32
|
const VERSION_FILE = resolve(ROOT, 'Harness', '.harness-version');
|
|
33
33
|
|
|
34
34
|
// ── Classification ─────────────────────────────────────────────────
|
|
@@ -45,7 +45,7 @@ const HARNESS_PREFIXES = [
|
|
|
45
45
|
'tests/.gitkeep',
|
|
46
46
|
];
|
|
47
47
|
|
|
48
|
-
/** Files the user owns
|
|
48
|
+
/** Files the user owns �?NEVER remove. Consistent with wf-update-check PRESERVE_PATTERNS. */
|
|
49
49
|
const USER_DATA_PATTERNS = [
|
|
50
50
|
/^Harness\/PROGRESS\.md$/,
|
|
51
51
|
/^Harness\/tasks\//,
|
|
@@ -97,14 +97,67 @@ function isPurgeableHarnessData(file, { keepTasks }) {
|
|
|
97
97
|
if (keepTasks && /^Harness\/tasks\//.test(file) && !isFrameworkTaskFile(file)) return false;
|
|
98
98
|
return PURGEABLE_HARNESS_DATA_PATTERNS.some(p => p.test(file));
|
|
99
99
|
}
|
|
100
|
-
|
|
101
|
-
/** Framework files that should always exist (not part of removal). */
|
|
102
|
-
const KEEP_FRAMEWORK = new Set([
|
|
103
|
-
'Harness/.harness-version',
|
|
104
|
-
]);
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
100
|
+
|
|
101
|
+
/** Framework files that should always exist (not part of removal). */
|
|
102
|
+
const KEEP_FRAMEWORK = new Set([
|
|
103
|
+
'Harness/.harness-version',
|
|
104
|
+
]);
|
|
105
|
+
|
|
106
|
+
const BUILT_IN_AGENT_NAMES = [
|
|
107
|
+
'architect-manager',
|
|
108
|
+
'architect',
|
|
109
|
+
'context-master',
|
|
110
|
+
'debugger',
|
|
111
|
+
'docs-researcher',
|
|
112
|
+
'explore-manager',
|
|
113
|
+
'implement-manager',
|
|
114
|
+
'implementer',
|
|
115
|
+
'memory-master',
|
|
116
|
+
'planner',
|
|
117
|
+
'researcher',
|
|
118
|
+
'review-manager',
|
|
119
|
+
'reviewer',
|
|
120
|
+
'tdd-guide',
|
|
121
|
+
'test-writer',
|
|
122
|
+
'verifier',
|
|
123
|
+
];
|
|
124
|
+
|
|
125
|
+
const BUILT_IN_SKILL_NAMES = [
|
|
126
|
+
'browser-e2e',
|
|
127
|
+
'github-pr-review',
|
|
128
|
+
'python-backend',
|
|
129
|
+
'subagent-orchestrator',
|
|
130
|
+
'tdd',
|
|
131
|
+
'ts-react-frontend',
|
|
132
|
+
'ui-ux-review',
|
|
133
|
+
'wf',
|
|
134
|
+
'wf-auto',
|
|
135
|
+
'wf-auto-spark',
|
|
136
|
+
'wf-browser',
|
|
137
|
+
'wf-learn',
|
|
138
|
+
'wf-max',
|
|
139
|
+
'wf-readme',
|
|
140
|
+
'wf-remove',
|
|
141
|
+
'wf-review',
|
|
142
|
+
'wf-update',
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
const KNOWN_FRAMEWORK_FILES = new Set([
|
|
146
|
+
...BUILT_IN_AGENT_NAMES.map(name => `.claude/agents/${name}.md`),
|
|
147
|
+
...BUILT_IN_SKILL_NAMES.flatMap(name => [
|
|
148
|
+
`.claude/skills/${name}/SKILL.md`,
|
|
149
|
+
`.agents/skills/${name}/SKILL.md`,
|
|
150
|
+
]),
|
|
151
|
+
'.claude/commands/wf-help.md',
|
|
152
|
+
'.claude/rules/ecc/common.md',
|
|
153
|
+
]);
|
|
154
|
+
|
|
155
|
+
function isKnownFrameworkFile(file) {
|
|
156
|
+
return KNOWN_FRAMEWORK_FILES.has(file);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Directories to clean up if empty after file removal. */
|
|
160
|
+
const CLEANUP_DIRS = [
|
|
108
161
|
'.claude/agents',
|
|
109
162
|
'.claude/skills/wf-auto',
|
|
110
163
|
'.claude/skills/wf-browser',
|
|
@@ -251,7 +304,7 @@ function removeEmptyDirs(startDir) {
|
|
|
251
304
|
|
|
252
305
|
async function askUser(question) {
|
|
253
306
|
if (!process.stdin.isTTY) {
|
|
254
|
-
console.log(' (non-interactive
|
|
307
|
+
console.log(' (non-interactive �?defaulting to KEEP)');
|
|
255
308
|
return 'k';
|
|
256
309
|
}
|
|
257
310
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -300,8 +353,9 @@ async function main() {
|
|
|
300
353
|
addFilesUnder(allFiles, dir, scanIssues);
|
|
301
354
|
}
|
|
302
355
|
|
|
303
|
-
// Add framework files that might not be in checksums (newer additions)
|
|
356
|
+
// Add framework files that might not be in checksums (newer additions)
|
|
304
357
|
const extraPatterns = [
|
|
358
|
+
...KNOWN_FRAMEWORK_FILES,
|
|
305
359
|
'.claude/skills/wf/SKILL.md',
|
|
306
360
|
'.agents/skills/wf/SKILL.md',
|
|
307
361
|
'.claude/skills/tdd/SKILL.md',
|
|
@@ -323,9 +377,9 @@ async function main() {
|
|
|
323
377
|
}
|
|
324
378
|
|
|
325
379
|
// 2. Classify every file
|
|
326
|
-
const safe = []; // SAFE
|
|
327
|
-
const modified = []; // MODIFIED
|
|
328
|
-
const user = []; // USER
|
|
380
|
+
const safe = []; // SAFE �?matches checksum, auto-remove
|
|
381
|
+
const modified = []; // MODIFIED �?user edited, must confirm
|
|
382
|
+
const user = []; // USER �?never remove
|
|
329
383
|
const skipped = []; // File not on disk, traversal rejected, or framework-keep
|
|
330
384
|
const purge = []; // Explicitly requested Harness user-data removal
|
|
331
385
|
skipped.push(...scanIssues);
|
|
@@ -347,13 +401,13 @@ async function main() {
|
|
|
347
401
|
});
|
|
348
402
|
continue;
|
|
349
403
|
}
|
|
350
|
-
user.push({ file, reason: 'user data
|
|
404
|
+
user.push({ file, reason: 'user data �?NEVER removed' });
|
|
351
405
|
continue;
|
|
352
406
|
}
|
|
353
407
|
|
|
354
408
|
// Only allow deletion of files under harness-owned prefixes
|
|
355
409
|
if (!isHarnessOwned(canonical)) {
|
|
356
|
-
user.push({ file, reason: 'outside harness prefix
|
|
410
|
+
user.push({ file, reason: 'outside harness prefix �?NEVER removed' });
|
|
357
411
|
continue;
|
|
358
412
|
}
|
|
359
413
|
|
|
@@ -366,15 +420,24 @@ async function main() {
|
|
|
366
420
|
skipped.push({ file, reason: 'not on disk' });
|
|
367
421
|
continue;
|
|
368
422
|
}
|
|
369
|
-
|
|
370
|
-
const currentHash = sha256File(diskPath);
|
|
371
|
-
const storedHash = storedChecksums[file];
|
|
372
|
-
|
|
373
|
-
if (!storedHash) {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
423
|
+
|
|
424
|
+
const currentHash = sha256File(diskPath);
|
|
425
|
+
const storedHash = storedChecksums[file];
|
|
426
|
+
|
|
427
|
+
if (!storedHash) {
|
|
428
|
+
if (isKnownFrameworkFile(canonical)) {
|
|
429
|
+
safe.push({
|
|
430
|
+
file,
|
|
431
|
+
currentHash,
|
|
432
|
+
storedHash: currentHash,
|
|
433
|
+
reason: 'known framework file missing from legacy checksums',
|
|
434
|
+
});
|
|
435
|
+
} else {
|
|
436
|
+
modified.push({ file, currentHash, storedHash: 'none', reason: 'not in checksums' });
|
|
437
|
+
}
|
|
438
|
+
} else if (currentHash === storedHash) {
|
|
439
|
+
safe.push({ file, currentHash, storedHash });
|
|
440
|
+
} else {
|
|
378
441
|
modified.push({ file, currentHash, storedHash, reason: 'user modified' });
|
|
379
442
|
}
|
|
380
443
|
}
|
|
@@ -385,7 +448,7 @@ async function main() {
|
|
|
385
448
|
const settingsHash = sha256File(settingsFile);
|
|
386
449
|
const storedSettingsHash = storedChecksums['.claude/settings.json'];
|
|
387
450
|
if (storedSettingsHash && settingsHash !== storedSettingsHash) {
|
|
388
|
-
// User modified settings
|
|
451
|
+
// User modified settings �?move to modified
|
|
389
452
|
// Remove from safe if it was there
|
|
390
453
|
const idx = safe.findIndex(s => s.file === '.claude/settings.json');
|
|
391
454
|
if (idx >= 0) {
|
|
@@ -429,16 +492,16 @@ async function main() {
|
|
|
429
492
|
return;
|
|
430
493
|
}
|
|
431
494
|
|
|
432
|
-
console.log('\n🧹 WF-REMOVE
|
|
495
|
+
console.log('\n🧹 WF-REMOVE �?Harness framework removal plan\n');
|
|
433
496
|
|
|
434
497
|
if (safe.length > 0) {
|
|
435
|
-
console.log(
|
|
436
|
-
for (const s of safe) console.log(`
|
|
498
|
+
console.log(`�?SAFE (${safe.length} files �?auto-remove, unmodified framework):`);
|
|
499
|
+
for (const s of safe) console.log(` �?${s.file}`);
|
|
437
500
|
console.log('');
|
|
438
501
|
}
|
|
439
502
|
|
|
440
503
|
if (modified.length > 0) {
|
|
441
|
-
console.log(
|
|
504
|
+
console.log(`�?MODIFIED (${modified.length} files �?REQUIRE CONFIRMATION):`);
|
|
442
505
|
for (const m of modified) {
|
|
443
506
|
console.log(` ? ${m.file} [${m.reason}]`);
|
|
444
507
|
}
|
|
@@ -446,8 +509,8 @@ async function main() {
|
|
|
446
509
|
}
|
|
447
510
|
|
|
448
511
|
if (user.length > 0) {
|
|
449
|
-
console.log(`🔒 USER DATA (${user.length} files
|
|
450
|
-
for (const u of user) console.log(`
|
|
512
|
+
console.log(`🔒 USER DATA (${user.length} files �?NEVER removed):`);
|
|
513
|
+
for (const u of user) console.log(` �?${u.file} [${u.reason}]`);
|
|
451
514
|
console.log('');
|
|
452
515
|
}
|
|
453
516
|
|
|
@@ -464,17 +527,17 @@ async function main() {
|
|
|
464
527
|
return;
|
|
465
528
|
}
|
|
466
529
|
|
|
467
|
-
// 4. Apply
|
|
530
|
+
// 4. Apply �?remove SAFE files automatically (rehash before unlink)
|
|
468
531
|
let safeRemoved = 0;
|
|
469
532
|
let safeFailed = 0;
|
|
470
533
|
for (const s of safe) {
|
|
471
534
|
const diskPath = safePath(s.file);
|
|
472
|
-
if (!diskPath) { console.error(`
|
|
535
|
+
if (!diskPath) { console.error(` �?Traversal rejected: ${s.file}`); safeFailed++; continue; }
|
|
473
536
|
if (!existsSync(diskPath)) continue;
|
|
474
537
|
// Re-verify hash hasn't changed since classification
|
|
475
538
|
const currentHash = sha256File(diskPath);
|
|
476
539
|
if (currentHash !== s.storedHash) {
|
|
477
|
-
console.log(`
|
|
540
|
+
console.log(` �?Skipped (modified since classification): ${s.file}`);
|
|
478
541
|
safeFailed++;
|
|
479
542
|
continue;
|
|
480
543
|
}
|
|
@@ -482,13 +545,13 @@ async function main() {
|
|
|
482
545
|
unlinkSync(diskPath);
|
|
483
546
|
safeRemoved++;
|
|
484
547
|
} catch (e) {
|
|
485
|
-
console.error(`
|
|
548
|
+
console.error(` �?Failed to remove: ${s.file} �?${e.message}`);
|
|
486
549
|
safeFailed++;
|
|
487
550
|
}
|
|
488
551
|
}
|
|
489
|
-
console.log(
|
|
552
|
+
console.log(`�?Removed ${safeRemoved} safe files.`);
|
|
490
553
|
|
|
491
|
-
// 5. Handle MODIFIED files
|
|
554
|
+
// 5. Handle MODIFIED files �?prompt user
|
|
492
555
|
let modifiedRemoved = 0;
|
|
493
556
|
let modifiedKept = 0;
|
|
494
557
|
let modifiedFailed = 0;
|
|
@@ -508,7 +571,7 @@ async function main() {
|
|
|
508
571
|
}
|
|
509
572
|
if (yes) {
|
|
510
573
|
// Non-interactive mode: skip all modified
|
|
511
|
-
console.log(`
|
|
574
|
+
console.log(` �?Skipped (modified): ${m.file}`);
|
|
512
575
|
modifiedKept++;
|
|
513
576
|
continue;
|
|
514
577
|
}
|
|
@@ -520,17 +583,17 @@ async function main() {
|
|
|
520
583
|
const answer = await askUser(' Choose [d/k]: ');
|
|
521
584
|
if (answer === 'd' || answer === 'delete') {
|
|
522
585
|
const diskPath = safePath(m.file);
|
|
523
|
-
if (!diskPath) { console.error(`
|
|
586
|
+
if (!diskPath) { console.error(` �?Traversal rejected: ${m.file}`); modifiedFailed++; continue; }
|
|
524
587
|
try {
|
|
525
588
|
unlinkSync(diskPath);
|
|
526
|
-
console.log(`
|
|
589
|
+
console.log(` �?Deleted: ${m.file}`);
|
|
527
590
|
modifiedRemoved++;
|
|
528
591
|
} catch (e) {
|
|
529
|
-
console.error(`
|
|
592
|
+
console.error(` �?Failed: ${m.file} �?${e.message}`);
|
|
530
593
|
modifiedFailed++;
|
|
531
594
|
}
|
|
532
595
|
} else {
|
|
533
|
-
console.log(`
|
|
596
|
+
console.log(` �?Kept: ${m.file}`);
|
|
534
597
|
modifiedKept++;
|
|
535
598
|
}
|
|
536
599
|
}
|
|
@@ -591,7 +654,7 @@ async function main() {
|
|
|
591
654
|
}
|
|
592
655
|
} else if (!existsSync(harPath) || (existsSync(harPath) && readdirSync(harPath).filter(f => f !== '.harness-version').length === 0)) {
|
|
593
656
|
unlinkSync(VERSION_FILE);
|
|
594
|
-
console.log('
|
|
657
|
+
console.log('�?Removed .harness-version (Harness directory empty).');
|
|
595
658
|
}
|
|
596
659
|
}
|
|
597
660
|
|
|
@@ -610,7 +673,7 @@ async function main() {
|
|
|
610
673
|
if (pruned > 0) {
|
|
611
674
|
versionData.checksums = checksums;
|
|
612
675
|
writeFileSync(VERSION_FILE, JSON.stringify(versionData, null, 2) + '\n', 'utf-8');
|
|
613
|
-
console.log(
|
|
676
|
+
console.log(`�?Pruned ${pruned} stale checksum(s) from .harness-version.`);
|
|
614
677
|
}
|
|
615
678
|
}
|
|
616
679
|
|
|
@@ -624,7 +687,7 @@ async function main() {
|
|
|
624
687
|
// Strip the harness section: everything from "## 1. Harness Binding" to the next "## "
|
|
625
688
|
const cleaned = content.replace(/## 1\. Harness Binding[\s\S]*?(?=## 2\.)/, '');
|
|
626
689
|
writeFileSync(claudePath, cleaned, 'utf-8');
|
|
627
|
-
console.log('
|
|
690
|
+
console.log('�?Stripped Harness binding section from CLAUDE.md.');
|
|
628
691
|
}
|
|
629
692
|
}
|
|
630
693
|
}
|