harness-everything 0.2.1 → 0.2.2
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/README.md +1 -1
- package/build-multi-agent-system/SKILL.md +68 -68
- package/create-agent-launcher/SKILL.md +48 -48
- package/docs/architecture.md +2 -2
- package/docs/workflows/build-multi-agent-system.md +62 -62
- package/docs/workflows/create-agent-launcher.md +62 -62
- package/docs/workflows/environment-detection.md +63 -63
- package/docs/workflows/eval-harness.md +57 -57
- package/docs/workflows/fable-discipline.md +59 -59
- package/docs/workflows/fable-mode.md +32 -32
- package/docs/workflows/git-commit.md +62 -62
- package/docs/workflows/grill-me.md +62 -62
- package/docs/workflows/grill-with-docs.md +62 -62
- package/docs/workflows/improve-codebase-architecture.md +60 -60
- package/docs/workflows/repo-docs.md +59 -59
- package/docs/workflows/rewrite-commits.md +60 -60
- package/docs/workflows/security-review.md +58 -58
- package/docs/workflows/self-evolve.md +59 -59
- package/docs/workflows/tdd.md +39 -39
- package/docs/workflows/todo-driven-workflow.md +36 -36
- package/docs/workflows/using-git-worktrees.md +63 -63
- package/docs/workflows/verification-loop.md +69 -69
- package/docs/workflows/verify-before-claim.md +60 -60
- package/docs/workflows/zoom-out.md +62 -62
- package/environment-detection/SKILL.md +77 -77
- package/eval-framework/behavioral-test.js +105 -105
- package/eval-framework/mechanism-test.js +251 -251
- package/eval-harness/SKILL.md +59 -59
- package/fable-discipline/SKILL.md +38 -38
- package/fable-mode/SKILL.md +51 -51
- package/git-commit/SKILL.md +55 -55
- package/grill-me/SKILL.md +36 -36
- package/grill-with-docs/SKILL.md +99 -99
- package/harness-everything/SKILL.md +141 -141
- package/harness-everything/examples/README.md +9 -9
- package/harness-everything/examples/todo-workflow.md +22 -22
- package/harness-everything/scripts/todo-cli.js +157 -157
- package/harness-everything/scripts/verify-gate.js +31 -31
- package/hooks/scripts/atomic-commit-check.js +68 -68
- package/hooks/scripts/context-compact.js +114 -114
- package/hooks/scripts/lib/platforms/claude.js +132 -42
- package/hooks/scripts/lib/platforms/codex.js +96 -46
- package/hooks/scripts/lib/platforms/continue.js +73 -41
- package/hooks/scripts/lib/platforms/copilot.js +91 -41
- package/hooks/scripts/lib/platforms/cursor.js +71 -41
- package/hooks/scripts/lib/platforms/hermes.js +25 -0
- package/hooks/scripts/rule-of-3.js +176 -176
- package/improve-codebase-architecture/SKILL.md +44 -44
- package/install-cognitive-os/SKILL.md +95 -95
- package/package.json +1 -1
- package/repo-docs/SKILL.md +45 -45
- package/rewrite-commits/SKILL.md +32 -32
- package/scripts/installer.js +57 -200
- package/scripts/lib/advisory-text.js +163 -163
- package/scripts/lib/claude-hooks.js +71 -71
- package/scripts/lib/manifest.js +82 -82
- package/scripts/lib/prompts.js +241 -241
- package/scripts/lib/skills.js +174 -172
- package/scripts/lib/workspace.js +28 -28
- package/security-review/SKILL.md +510 -510
- package/self-evolve/SKILL.md +54 -54
- package/skill-creator/SKILL.md +91 -91
- package/skill-creator/references/testing-workflow.md +32 -32
- package/skill-style/SKILL.md +48 -48
- package/tdd/SKILL.md +53 -53
- package/todo-driven-workflow/SKILL.md +54 -54
- package/using-git-worktrees/SKILL.md +161 -161
- package/verification-loop/SKILL.md +138 -138
- package/verify-before-claim/SKILL.md +86 -86
- package/zoom-out/SKILL.md +90 -90
package/scripts/installer.js
CHANGED
|
@@ -216,113 +216,40 @@ async function main() {
|
|
|
216
216
|
console.log(`Installing Harness OS to ${isGlobal ? 'Global Home' : 'Local Workspace'}`);
|
|
217
217
|
console.log("-------------------------------------------------");
|
|
218
218
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
advisory.injectAdvisoryText(targetFile, '# Copilot Instructions', '.github/copilot-instructions.md');
|
|
234
|
-
} else {
|
|
235
|
-
try {
|
|
236
|
-
const promptsDir = getUserPromptsDir();
|
|
237
|
-
if (!fs.existsSync(promptsDir)) {
|
|
238
|
-
fs.mkdirSync(promptsDir, { recursive: true });
|
|
239
|
-
}
|
|
240
|
-
const vscodeInstFile = path.join(promptsDir, 'harness.instructions.md');
|
|
241
|
-
fs.writeFileSync(vscodeInstFile, advisory.buildCopilotGlobalContent(), 'utf8');
|
|
242
|
-
console.log(` ✅ Installed global Copilot instructions to VS Code: ${vscodeInstFile}`);
|
|
243
|
-
} catch (err) {
|
|
244
|
-
console.warn(` ⚠️ Failed to write VS Code user prompts folder: ${err.message}`);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
// Codex
|
|
249
|
-
if (targets.codex) {
|
|
250
|
-
if (!isGlobal) {
|
|
251
|
-
const targetFile = path.join(targetWorkspaceRoot, 'AGENTS.md');
|
|
252
|
-
advisory.injectAdvisoryText(targetFile, '# AGENTS.md', 'AGENTS.md');
|
|
253
|
-
} else {
|
|
254
|
-
try {
|
|
255
|
-
const promptsDir = getUserPromptsDir();
|
|
256
|
-
if (!fs.existsSync(promptsDir)) {
|
|
257
|
-
fs.mkdirSync(promptsDir, { recursive: true });
|
|
258
|
-
}
|
|
259
|
-
const vscodeAgentFile = path.join(promptsDir, 'harness.agent.md');
|
|
260
|
-
fs.writeFileSync(vscodeAgentFile, advisory.buildCodexGlobalContent(), 'utf8');
|
|
261
|
-
console.log(` ✅ Installed global Codex agent to VS Code: ${vscodeAgentFile}`);
|
|
262
|
-
} catch (err) {
|
|
263
|
-
console.warn(` ⚠️ Failed to write VS Code user prompts folder: ${err.message}`);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
// Continue.dev
|
|
268
|
-
if (targets.continue) {
|
|
269
|
-
const targetFile = isGlobal ? path.join(userHome, '.continue', 'rules', 'harness.md') : path.join(workspaceRoot, '.continue', 'rules', 'harness.md');
|
|
270
|
-
advisory.installContinueRule(targetFile, isGlobal ? '~/.continue/rules/harness.md' : '.continue/rules/harness.md');
|
|
271
|
-
}
|
|
272
|
-
// Hermes Agent (reads .hermes.md/AGENTS.md/CLAUDE.md/.cursorrules from the
|
|
273
|
-
// project it's launched in - project scope only, no documented global
|
|
274
|
-
// equivalent, so --global is a documented no-op here rather than a guess).
|
|
275
|
-
if (targets.hermes) {
|
|
276
|
-
if (!isGlobal) {
|
|
277
|
-
const targetFile = path.join(targetWorkspaceRoot, '.hermes.md');
|
|
278
|
-
advisory.injectAdvisoryText(targetFile, '# .hermes.md', '.hermes.md');
|
|
279
|
-
} else {
|
|
280
|
-
console.log(` ℹ️ Hermes Agent has no documented global instructions file (it reads .hermes.md from the current project directory only) - skipping global install for --hermes.`);
|
|
219
|
+
for (const platform of platformModules) {
|
|
220
|
+
if (targets[platform.name] && typeof platform.install === 'function') {
|
|
221
|
+
platform.install({
|
|
222
|
+
isGlobal,
|
|
223
|
+
targetWorkspaceRoot,
|
|
224
|
+
harnessSourceDir,
|
|
225
|
+
packageVersion,
|
|
226
|
+
getUserPromptsDir,
|
|
227
|
+
advisory,
|
|
228
|
+
claudeHooks,
|
|
229
|
+
manifest,
|
|
230
|
+
userHome,
|
|
231
|
+
workspaceRoot
|
|
232
|
+
});
|
|
281
233
|
}
|
|
282
234
|
}
|
|
283
235
|
|
|
284
236
|
// Install chosen skills. Every platform's skills stay at that platform's
|
|
285
|
-
// own native location (unchanged) EXCEPT Claude, which
|
|
286
|
-
//
|
|
287
|
-
// Every platform still gets its own harness-everything/manifest.json so
|
|
288
|
-
// "what did we install here" is always precisely answerable per platform.
|
|
237
|
+
// own native location (unchanged) EXCEPT Claude, which has its copy under
|
|
238
|
+
// .claude/skills/. Each platform's manifest.json tracks its own.
|
|
289
239
|
if (chosenSkills.length > 0) {
|
|
290
240
|
const targetDirs = [];
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
path: path.join(manifest.getHarnessDir(claudeDir), 'skills'),
|
|
303
|
-
label: '.claude/harness-everything/skills/',
|
|
304
|
-
manifestPath: manifest.getManifestPath(claudeDir),
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
if (targets.cursor) {
|
|
308
|
-
const cursorDir = path.join(workspaceRoot, '.cursor');
|
|
309
|
-
targetDirs.push({ path: path.join(cursorDir, 'skills'), label: '.cursor/skills/', manifestPath: manifest.getManifestPath(cursorDir) });
|
|
310
|
-
}
|
|
311
|
-
if (targets.copilot) {
|
|
312
|
-
const githubDir = path.join(workspaceRoot, '.github');
|
|
313
|
-
targetDirs.push({ path: path.join(githubDir, 'skills'), label: '.github/skills/', manifestPath: manifest.getManifestPath(githubDir) });
|
|
314
|
-
}
|
|
315
|
-
if (targets.codex) {
|
|
316
|
-
const codexDir = path.join(workspaceRoot, '.codex');
|
|
317
|
-
targetDirs.push({ path: path.join(codexDir, 'skills'), label: '.codex/skills/', manifestPath: manifest.getManifestPath(codexDir) });
|
|
318
|
-
}
|
|
319
|
-
if (targets.continue) {
|
|
320
|
-
const continueDir = path.join(workspaceRoot, '.continue');
|
|
321
|
-
targetDirs.push({ path: path.join(continueDir, 'skills'), label: '.continue/skills/', manifestPath: manifest.getManifestPath(continueDir) });
|
|
241
|
+
const addedPaths = new Set();
|
|
242
|
+
for (const platform of platformModules) {
|
|
243
|
+
// If it's a global install, gather all configured/selected platforms or defaults
|
|
244
|
+
if (targets[platform.name] || (isGlobal && (targets.claude || targets.cursor || targets.copilot || targets.codex || targets.continue || targets.hermes))) {
|
|
245
|
+
if (typeof platform.getSkillsTarget === 'function') {
|
|
246
|
+
const tgt = platform.getSkillsTarget({ workspaceRoot, userHome, isGlobal, manifest });
|
|
247
|
+
if (tgt && tgt.path && !addedPaths.has(tgt.path)) {
|
|
248
|
+
targetDirs.push(tgt);
|
|
249
|
+
addedPaths.add(tgt.path);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
322
252
|
}
|
|
323
|
-
// Hermes has no documented project-level skills directory - its skills
|
|
324
|
-
// system is per-profile only (~/.hermes/skills/), which the isGlobal
|
|
325
|
-
// branch above already covers via the shared global harness-everything/ target.
|
|
326
253
|
}
|
|
327
254
|
|
|
328
255
|
console.log(`\nInstalling Harness skills:`);
|
|
@@ -357,61 +284,6 @@ async function main() {
|
|
|
357
284
|
console.log("=================================================");
|
|
358
285
|
}
|
|
359
286
|
|
|
360
|
-
function installClaudeHooks({ isGlobal, targetWorkspaceRoot }) {
|
|
361
|
-
const claudeDir = isGlobal ? path.join(userHome, '.claude') : path.join(targetWorkspaceRoot, '.claude');
|
|
362
|
-
if (!fs.existsSync(claudeDir)) {
|
|
363
|
-
fs.mkdirSync(claudeDir, { recursive: true });
|
|
364
|
-
console.log(` Created ${isGlobal ? '~/.claude' : '.claude'} directory`);
|
|
365
|
-
}
|
|
366
|
-
const claudeSettingsFile = path.join(claudeDir, 'settings.json');
|
|
367
|
-
let claudeConfig = {};
|
|
368
|
-
if (fs.existsSync(claudeSettingsFile)) {
|
|
369
|
-
try {
|
|
370
|
-
claudeConfig = JSON.parse(fs.readFileSync(claudeSettingsFile, 'utf8'));
|
|
371
|
-
} catch (e) {
|
|
372
|
-
console.warn(` ⚠️ Existing ${isGlobal ? '~' : ''}/.claude/settings.json is malformed, creating fresh one.`);
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
const resolvedHooks = resolveSourceHooks();
|
|
377
|
-
claudeHooks.mergeHarnessHooks(claudeConfig, resolvedHooks);
|
|
378
|
-
|
|
379
|
-
fs.writeFileSync(claudeSettingsFile, JSON.stringify(claudeConfig, null, 2), 'utf8');
|
|
380
|
-
console.log(` ✅ Configured Claude Code hooks safely in ${isGlobal ? '~' : ''}/.claude/settings.json`);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
// Resolves the source hooks.json into absolute script paths and stamps each
|
|
384
|
-
// entry with which package/version/author installed it (informational -
|
|
385
|
-
// removal itself still keys off the `harness:` id prefix alone).
|
|
386
|
-
function resolveSourceHooks() {
|
|
387
|
-
const sourceHooksFile = path.join(harnessSourceDir, 'hooks', 'hooks.json');
|
|
388
|
-
if (!fs.existsSync(sourceHooksFile)) {
|
|
389
|
-
throw new Error(`Harness source hooks definition not found at: ${sourceHooksFile}`);
|
|
390
|
-
}
|
|
391
|
-
const sourceHooksObj = JSON.parse(fs.readFileSync(sourceHooksFile, 'utf8'));
|
|
392
|
-
|
|
393
|
-
const resolvedHooks = {};
|
|
394
|
-
for (const [hookType, hookList] of Object.entries(sourceHooksObj.hooks || {})) {
|
|
395
|
-
resolvedHooks[hookType] = hookList.map(hookItem => {
|
|
396
|
-
const cloned = JSON.parse(JSON.stringify(hookItem));
|
|
397
|
-
if (cloned.hooks) {
|
|
398
|
-
cloned.hooks = cloned.hooks.map(h => {
|
|
399
|
-
if (h.type === 'command' && h.command) {
|
|
400
|
-
h.command = h.command.replace(/^node\s+"?([^"\s]+)"?/, (m, scriptPath) => {
|
|
401
|
-
const abs = path.isAbsolute(scriptPath) ? scriptPath : path.join(harnessSourceDir, scriptPath);
|
|
402
|
-
return `node "${abs}"`;
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
return h;
|
|
406
|
-
});
|
|
407
|
-
}
|
|
408
|
-
cloned.harness = { package: manifest.PACKAGE_NAME, version: packageVersion, author: manifest.HARNESS_AUTHOR };
|
|
409
|
-
return cloned;
|
|
410
|
-
});
|
|
411
|
-
}
|
|
412
|
-
return resolvedHooks;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
287
|
async function runUninstall({ hasYesFlag, args, isInteractive }) {
|
|
416
288
|
const localHarnessDirs = platformModules
|
|
417
289
|
.filter(p => typeof p.getHarnessDir === 'function')
|
|
@@ -524,36 +396,30 @@ async function runUninstall({ hasYesFlag, args, isInteractive }) {
|
|
|
524
396
|
console.log("Uninstalling Harness OS from Local Workspace...");
|
|
525
397
|
console.log("-------------------------------------------------");
|
|
526
398
|
|
|
527
|
-
const localSettingsFile = path.join(workspaceRoot, '.claude', 'settings.json');
|
|
528
|
-
claudeHooks.removeHarnessHooks(localSettingsFile);
|
|
529
|
-
|
|
530
|
-
// Clear each platform's own runtime hook-state. Manifest + any remaining
|
|
531
|
-
// skills are a separate, opt-in concern handled by the skills-removal
|
|
532
|
-
// step below, so the harness-everything/ dir itself isn't swept here yet
|
|
533
|
-
// - manifest.json (deleted only once its skills list empties out) may
|
|
534
|
-
// still be sitting in it at this point. The final sweep near the end of
|
|
535
|
-
// this function catches it once skill removal has actually run.
|
|
536
399
|
for (const platform of platformModules) {
|
|
537
|
-
if (typeof platform.
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
400
|
+
if (typeof platform.uninstall === 'function') {
|
|
401
|
+
platform.uninstall({
|
|
402
|
+
removeLocal: true,
|
|
403
|
+
removeGlobal: false,
|
|
404
|
+
workspaceRoot,
|
|
405
|
+
userHome,
|
|
406
|
+
getUserPromptsDir,
|
|
407
|
+
cleanEmptyDirs,
|
|
408
|
+
claudeHooks
|
|
409
|
+
});
|
|
542
410
|
}
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
advisory.removeAdvisoryText(path.join(workspaceRoot, '.cursorrules'));
|
|
546
|
-
advisory.removeAdvisoryText(path.join(workspaceRoot, '.github', 'copilot-instructions.md'));
|
|
547
|
-
advisory.removeAdvisoryText(path.join(workspaceRoot, 'AGENTS.md'));
|
|
548
|
-
advisory.removeAdvisoryText(path.join(workspaceRoot, '.hermes.md'));
|
|
549
411
|
|
|
550
|
-
|
|
551
|
-
|
|
412
|
+
if (typeof platform.getStateDir === 'function') {
|
|
413
|
+
const stateDir = platform.getStateDir(workspaceRoot);
|
|
414
|
+
if (fs.existsSync(stateDir)) {
|
|
415
|
+
fs.rmSync(stateDir, { recursive: true, force: true });
|
|
416
|
+
console.log(` ✅ Removed local ${path.relative(workspaceRoot, stateDir).replace(/\\/g, '/')}/ directory`);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
552
420
|
|
|
553
421
|
// One-time migration cleanup: earlier versions used a self-invented
|
|
554
422
|
// top-level .harness/ directory for Claude's manifest + skill copies.
|
|
555
|
-
// It was never shared with anything else in the workspace, so - unlike
|
|
556
|
-
// every other removal in this file - it's always safe to wipe wholesale.
|
|
557
423
|
const legacyHarnessDir = path.join(workspaceRoot, '.harness');
|
|
558
424
|
if (fs.existsSync(legacyHarnessDir)) {
|
|
559
425
|
fs.rmSync(legacyHarnessDir, { recursive: true, force: true });
|
|
@@ -566,28 +432,19 @@ async function runUninstall({ hasYesFlag, args, isInteractive }) {
|
|
|
566
432
|
console.log("Uninstalling Harness OS from Global Home...");
|
|
567
433
|
console.log("-------------------------------------------------");
|
|
568
434
|
|
|
569
|
-
const
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
if (fs.existsSync(vscodeInstFile)) {
|
|
582
|
-
fs.unlinkSync(vscodeInstFile);
|
|
583
|
-
console.log(` ✅ Removed global Copilot instructions: ${vscodeInstFile}`);
|
|
584
|
-
}
|
|
585
|
-
const vscodeAgentFile = path.join(promptsDir, 'harness.agent.md');
|
|
586
|
-
if (fs.existsSync(vscodeAgentFile)) {
|
|
587
|
-
fs.unlinkSync(vscodeAgentFile);
|
|
588
|
-
console.log(` ✅ Removed global Codex agent: ${vscodeAgentFile}`);
|
|
435
|
+
for (const platform of platformModules) {
|
|
436
|
+
if (typeof platform.uninstall === 'function') {
|
|
437
|
+
platform.uninstall({
|
|
438
|
+
removeLocal: false,
|
|
439
|
+
removeGlobal: true,
|
|
440
|
+
workspaceRoot,
|
|
441
|
+
userHome,
|
|
442
|
+
getUserPromptsDir,
|
|
443
|
+
cleanEmptyDirs,
|
|
444
|
+
claudeHooks
|
|
445
|
+
});
|
|
446
|
+
}
|
|
589
447
|
}
|
|
590
|
-
cleanEmptyDirs(promptsDir, [userHome]);
|
|
591
448
|
|
|
592
449
|
// ~/.agents is a shared directory - other tools or the user's own files
|
|
593
450
|
// may live there. Never touch it directly; only clean up the
|
|
@@ -1,163 +1,163 @@
|
|
|
1
|
-
// Prompt-injection-only guidance for platforms with no hook/execution
|
|
2
|
-
// mechanism (Cursor, Copilot, Codex, Continue, Hermes). Single source of
|
|
3
|
-
// truth for the advisory block - it used to be duplicated verbatim inside
|
|
4
|
-
// installer.js's top level and again inside main().
|
|
5
|
-
const fs = require('fs');
|
|
6
|
-
const path = require('path');
|
|
7
|
-
|
|
8
|
-
const MARKER = "Harness OS Guidance (Advisory)";
|
|
9
|
-
|
|
10
|
-
const advisoryInstructions = [
|
|
11
|
-
`\n# ${MARKER}`,
|
|
12
|
-
`This file is advisory only - this platform has no hook/execution mechanism to`,
|
|
13
|
-
`enforce it mechanically (unlike Claude Code's hook-based circuit breaker). Treat`,
|
|
14
|
-
`these as strong defaults, not guarantees.`,
|
|
15
|
-
``,
|
|
16
|
-
`## 🚦 MANDATORY ENTRY TRIAGE & ROUTING (ALWAYS RUN FIRST)`,
|
|
17
|
-
`Every time you receive a new prompt, you MUST load the \`harness-everything\` skill and immediately do the following:`,
|
|
18
|
-
`1. Run the Tier Router script: \`node harness-everything/scripts/tier-router.js "<Brief summary of user's prompt>"\` (or simulate its routing logic if terminal is not initialized yet).`,
|
|
19
|
-
`2. Output a clear, stylized routing checkpoint block at the VERY BEGINNING of your response to the user:`,
|
|
20
|
-
` \`\`\`markdown`,
|
|
21
|
-
` ## 🚦 Harness OS Routing Checkpoint`,
|
|
22
|
-
` - **Active Tier**: Tier 1 (Trivial) | Tier 2 (Standard) | Tier 3 (Macro)`,
|
|
23
|
-
` - **Rationale**: <1-sentence rationale from the tier router output>`,
|
|
24
|
-
` - **Routed Skills, Guides & Actions**:`,
|
|
25
|
-
` - \`path/to/skill/or/guide.md\` (<Brief reason why this guide/skill is loaded/used>)`,
|
|
26
|
-
` \`\`\``,
|
|
27
|
-
``,
|
|
28
|
-
`## 🤖 COGNITIVE COMPLIANCE (NO SILENT DEGRADES FOR NEW FEATURES)`,
|
|
29
|
-
`- **Newly Added Features / Extensions**: Copilot is highly prone to treating new feature requests as Tier 1 direct edits. If a task introduces *any* new logic, a new API endpoint, or a new file/module, you **MUST NOT** treat it as Tier 1. It **MUST** be treated as a **Tier 2 (Standard Task)** or **Tier 3 (Macro Task)**.`,
|
|
30
|
-
`- **Tier 2 Activation**: Initialize the \`todo-driven-workflow\` checklist first. Summon Domain Experts based on tech stack. Load and execute the \`tdd\` (Test-Driven Development) skill (write tests first, implement, refactor).`,
|
|
31
|
-
`- **Tier 3 Activation**: Initialize the \`todo-driven-workflow\` checklist, load \`fable-mode\` and \`fable-discipline\`, run sub-agents via \`create-agent-launcher\`, and write global docs using \`repo-docs\`.`,
|
|
32
|
-
`- **Memory Summarization (Self-Evolve)**: Upon task completion, you **MUST** run the \`self-evolve\` skill (running \`node self-evolve/scripts/self-regression.js\` or writing memories) to record key insights, lessons learned, and error boundaries so your context builds across sessions.`,
|
|
33
|
-
`- **Environment Discovery**: Discover the environment (OS, shell, package manager) before running commands - don't assume.`,
|
|
34
|
-
`- **Rule of 3**: If the same error repeats 3 times in a row, STOP retrying. Explain what's failing and ask the human for direction instead of continuing to guess.`,
|
|
35
|
-
`- **Prefer Editing**: Prefer editing over rewriting; commit logically complete chunks rather than one giant diff.`,
|
|
36
|
-
``
|
|
37
|
-
].join('\n');
|
|
38
|
-
|
|
39
|
-
function injectAdvisoryText(targetFile, header, label) {
|
|
40
|
-
const dir = path.dirname(targetFile);
|
|
41
|
-
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
42
|
-
|
|
43
|
-
if (fs.existsSync(targetFile)) {
|
|
44
|
-
const content = fs.readFileSync(targetFile, 'utf8');
|
|
45
|
-
if (!content.includes(MARKER)) {
|
|
46
|
-
fs.appendFileSync(targetFile, advisoryInstructions, 'utf8');
|
|
47
|
-
console.log(` ✅ Augmented existing ${label} with Harness guidance (advisory-only)`);
|
|
48
|
-
}
|
|
49
|
-
} else {
|
|
50
|
-
fs.writeFileSync(targetFile, `${header}\n${advisoryInstructions}`, 'utf8');
|
|
51
|
-
console.log(` ✅ Created ${label} with Harness guidance (advisory-only)`);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function removeAdvisoryText(targetFile) {
|
|
56
|
-
if (!fs.existsSync(targetFile)) return;
|
|
57
|
-
try {
|
|
58
|
-
let content = fs.readFileSync(targetFile, 'utf8');
|
|
59
|
-
const markerIndex = content.indexOf(MARKER);
|
|
60
|
-
if (markerIndex !== -1) {
|
|
61
|
-
let cleanContent = content;
|
|
62
|
-
const hashMarkerIndex = content.lastIndexOf('#', markerIndex);
|
|
63
|
-
if (hashMarkerIndex !== -1) {
|
|
64
|
-
cleanContent = content.substring(0, hashMarkerIndex).trim() + '\n';
|
|
65
|
-
} else {
|
|
66
|
-
cleanContent = content.substring(0, markerIndex).trim() + '\n';
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const lines = cleanContent.trim().split('\n').map(l => l.trim()).filter(l => l !== '');
|
|
70
|
-
if (lines.length === 0 || (lines.length === 1 && (lines[0] === '# Cursor Project Rules' || lines[0] === '# AGENTS.md' || lines[0] === '# Copilot Instructions' || lines[0] === '# .hermes.md'))) {
|
|
71
|
-
fs.unlinkSync(targetFile);
|
|
72
|
-
console.log(` ✅ Removed empty advisory file: ${targetFile}`);
|
|
73
|
-
} else {
|
|
74
|
-
fs.writeFileSync(targetFile, cleanContent.trim() + '\n', 'utf8');
|
|
75
|
-
console.log(` ✅ Removed Harness guidance from: ${targetFile}`);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
} catch (e) {
|
|
79
|
-
console.warn(` ⚠️ Error removing advisory text from ${targetFile}: ${e.message}`);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Continue.dev reads project rules as individual Markdown files (with YAML
|
|
84
|
-
// frontmatter) from a `.continue/rules/` folder rather than one shared file,
|
|
85
|
-
// so - unlike the shared-file platforms above - Harness gets its own
|
|
86
|
-
// dedicated `harness.md` rule file instead of appending into an arbitrary
|
|
87
|
-
// pre-existing one.
|
|
88
|
-
function installContinueRule(targetFile, label) {
|
|
89
|
-
const dir = path.dirname(targetFile);
|
|
90
|
-
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
91
|
-
if (fs.existsSync(targetFile) && fs.readFileSync(targetFile, 'utf8').includes(MARKER)) {
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
const content = [
|
|
95
|
-
`---`,
|
|
96
|
-
`name: Harness OS Guidance`,
|
|
97
|
-
`alwaysApply: true`,
|
|
98
|
-
`description: "Harness OS routing, circuit-breaker awareness, and environment-discovery guidance (advisory only on Continue - no hook mechanism)"`,
|
|
99
|
-
`---`,
|
|
100
|
-
advisoryInstructions.replace(/^\n/, '')
|
|
101
|
-
].join('\n');
|
|
102
|
-
fs.writeFileSync(targetFile, content, 'utf8');
|
|
103
|
-
console.log(` ✅ Installed Continue rule file with Harness guidance (advisory-only): ${label}`);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function removeContinueRule(targetFile) {
|
|
107
|
-
if (!fs.existsSync(targetFile)) return;
|
|
108
|
-
try {
|
|
109
|
-
const content = fs.readFileSync(targetFile, 'utf8');
|
|
110
|
-
if (content.includes(MARKER)) {
|
|
111
|
-
fs.unlinkSync(targetFile);
|
|
112
|
-
console.log(` ✅ Removed Harness rule file: ${targetFile}`);
|
|
113
|
-
}
|
|
114
|
-
} catch (e) {
|
|
115
|
-
console.warn(` ⚠️ Error removing ${targetFile}: ${e.message}`);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function buildCopilotGlobalContent() {
|
|
120
|
-
return [
|
|
121
|
-
`---`,
|
|
122
|
-
`description: "Harness OS Guidance (Advisory)"`,
|
|
123
|
-
`applyTo: "**"`,
|
|
124
|
-
`---`,
|
|
125
|
-
`# Copilot Instructions`,
|
|
126
|
-
``,
|
|
127
|
-
advisoryInstructions.replace(/^\n/, '')
|
|
128
|
-
].join('\n');
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function buildCodexGlobalContent() {
|
|
132
|
-
return [
|
|
133
|
-
`---`,
|
|
134
|
-
`description: "Harness OS Guidance - Global custom agent for orchestrating multi-agent workflows"`,
|
|
135
|
-
`name: "Harness"`,
|
|
136
|
-
`user-invocable: true`,
|
|
137
|
-
`---`,
|
|
138
|
-
`# AGENTS.md`,
|
|
139
|
-
``,
|
|
140
|
-
`This file is advisory only - this platform has no hook/execution mechanism to`,
|
|
141
|
-
`enforce it mechanically (unlike Claude Code's hook-based circuit breaker). Treat`,
|
|
142
|
-
`these as strong defaults, not guarantees.`,
|
|
143
|
-
``,
|
|
144
|
-
`- Discover the environment (OS, shell, package manager) before running commands - don't assume.`,
|
|
145
|
-
`- Triage tasks: trivial fixes need no plan; standard features need tests; large refactors need`,
|
|
146
|
-
` an explicit plan reviewed with the human before implementation.`,
|
|
147
|
-
`- If the same error repeats 3 times in a row, STOP retrying. Explain what's failing and ask the`,
|
|
148
|
-
` human for direction instead of continuing to guess.`,
|
|
149
|
-
`- Prefer editing over rewriting; commit logically complete chunks rather than one giant diff.`,
|
|
150
|
-
``
|
|
151
|
-
].join('\n');
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
module.exports = {
|
|
155
|
-
MARKER,
|
|
156
|
-
advisoryInstructions,
|
|
157
|
-
injectAdvisoryText,
|
|
158
|
-
removeAdvisoryText,
|
|
159
|
-
installContinueRule,
|
|
160
|
-
removeContinueRule,
|
|
161
|
-
buildCopilotGlobalContent,
|
|
162
|
-
buildCodexGlobalContent,
|
|
163
|
-
};
|
|
1
|
+
// Prompt-injection-only guidance for platforms with no hook/execution
|
|
2
|
+
// mechanism (Cursor, Copilot, Codex, Continue, Hermes). Single source of
|
|
3
|
+
// truth for the advisory block - it used to be duplicated verbatim inside
|
|
4
|
+
// installer.js's top level and again inside main().
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
|
|
8
|
+
const MARKER = "Harness OS Guidance (Advisory)";
|
|
9
|
+
|
|
10
|
+
const advisoryInstructions = [
|
|
11
|
+
`\n# ${MARKER}`,
|
|
12
|
+
`This file is advisory only - this platform has no hook/execution mechanism to`,
|
|
13
|
+
`enforce it mechanically (unlike Claude Code's hook-based circuit breaker). Treat`,
|
|
14
|
+
`these as strong defaults, not guarantees.`,
|
|
15
|
+
``,
|
|
16
|
+
`## 🚦 MANDATORY ENTRY TRIAGE & ROUTING (ALWAYS RUN FIRST)`,
|
|
17
|
+
`Every time you receive a new prompt, you MUST load the \`harness-everything\` skill and immediately do the following:`,
|
|
18
|
+
`1. Run the Tier Router script: \`node harness-everything/scripts/tier-router.js "<Brief summary of user's prompt>"\` (or simulate its routing logic if terminal is not initialized yet).`,
|
|
19
|
+
`2. Output a clear, stylized routing checkpoint block at the VERY BEGINNING of your response to the user:`,
|
|
20
|
+
` \`\`\`markdown`,
|
|
21
|
+
` ## 🚦 Harness OS Routing Checkpoint`,
|
|
22
|
+
` - **Active Tier**: Tier 1 (Trivial) | Tier 2 (Standard) | Tier 3 (Macro)`,
|
|
23
|
+
` - **Rationale**: <1-sentence rationale from the tier router output>`,
|
|
24
|
+
` - **Routed Skills, Guides & Actions**:`,
|
|
25
|
+
` - \`path/to/skill/or/guide.md\` (<Brief reason why this guide/skill is loaded/used>)`,
|
|
26
|
+
` \`\`\``,
|
|
27
|
+
``,
|
|
28
|
+
`## 🤖 COGNITIVE COMPLIANCE (NO SILENT DEGRADES FOR NEW FEATURES)`,
|
|
29
|
+
`- **Newly Added Features / Extensions**: Copilot is highly prone to treating new feature requests as Tier 1 direct edits. If a task introduces *any* new logic, a new API endpoint, or a new file/module, you **MUST NOT** treat it as Tier 1. It **MUST** be treated as a **Tier 2 (Standard Task)** or **Tier 3 (Macro Task)**.`,
|
|
30
|
+
`- **Tier 2 Activation**: Initialize the \`todo-driven-workflow\` checklist first. Summon Domain Experts based on tech stack. Load and execute the \`tdd\` (Test-Driven Development) skill (write tests first, implement, refactor).`,
|
|
31
|
+
`- **Tier 3 Activation**: Initialize the \`todo-driven-workflow\` checklist, load \`fable-mode\` and \`fable-discipline\`, run sub-agents via \`create-agent-launcher\`, and write global docs using \`repo-docs\`.`,
|
|
32
|
+
`- **Memory Summarization (Self-Evolve)**: Upon task completion, you **MUST** run the \`self-evolve\` skill (running \`node self-evolve/scripts/self-regression.js\` or writing memories) to record key insights, lessons learned, and error boundaries so your context builds across sessions.`,
|
|
33
|
+
`- **Environment Discovery**: Discover the environment (OS, shell, package manager) before running commands - don't assume.`,
|
|
34
|
+
`- **Rule of 3**: If the same error repeats 3 times in a row, STOP retrying. Explain what's failing and ask the human for direction instead of continuing to guess.`,
|
|
35
|
+
`- **Prefer Editing**: Prefer editing over rewriting; commit logically complete chunks rather than one giant diff.`,
|
|
36
|
+
``
|
|
37
|
+
].join('\n');
|
|
38
|
+
|
|
39
|
+
function injectAdvisoryText(targetFile, header, label) {
|
|
40
|
+
const dir = path.dirname(targetFile);
|
|
41
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
42
|
+
|
|
43
|
+
if (fs.existsSync(targetFile)) {
|
|
44
|
+
const content = fs.readFileSync(targetFile, 'utf8');
|
|
45
|
+
if (!content.includes(MARKER)) {
|
|
46
|
+
fs.appendFileSync(targetFile, advisoryInstructions, 'utf8');
|
|
47
|
+
console.log(` ✅ Augmented existing ${label} with Harness guidance (advisory-only)`);
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
fs.writeFileSync(targetFile, `${header}\n${advisoryInstructions}`, 'utf8');
|
|
51
|
+
console.log(` ✅ Created ${label} with Harness guidance (advisory-only)`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function removeAdvisoryText(targetFile) {
|
|
56
|
+
if (!fs.existsSync(targetFile)) return;
|
|
57
|
+
try {
|
|
58
|
+
let content = fs.readFileSync(targetFile, 'utf8');
|
|
59
|
+
const markerIndex = content.indexOf(MARKER);
|
|
60
|
+
if (markerIndex !== -1) {
|
|
61
|
+
let cleanContent = content;
|
|
62
|
+
const hashMarkerIndex = content.lastIndexOf('#', markerIndex);
|
|
63
|
+
if (hashMarkerIndex !== -1) {
|
|
64
|
+
cleanContent = content.substring(0, hashMarkerIndex).trim() + '\n';
|
|
65
|
+
} else {
|
|
66
|
+
cleanContent = content.substring(0, markerIndex).trim() + '\n';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const lines = cleanContent.trim().split('\n').map(l => l.trim()).filter(l => l !== '');
|
|
70
|
+
if (lines.length === 0 || (lines.length === 1 && (lines[0] === '# Cursor Project Rules' || lines[0] === '# AGENTS.md' || lines[0] === '# Copilot Instructions' || lines[0] === '# .hermes.md'))) {
|
|
71
|
+
fs.unlinkSync(targetFile);
|
|
72
|
+
console.log(` ✅ Removed empty advisory file: ${targetFile}`);
|
|
73
|
+
} else {
|
|
74
|
+
fs.writeFileSync(targetFile, cleanContent.trim() + '\n', 'utf8');
|
|
75
|
+
console.log(` ✅ Removed Harness guidance from: ${targetFile}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
} catch (e) {
|
|
79
|
+
console.warn(` ⚠️ Error removing advisory text from ${targetFile}: ${e.message}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Continue.dev reads project rules as individual Markdown files (with YAML
|
|
84
|
+
// frontmatter) from a `.continue/rules/` folder rather than one shared file,
|
|
85
|
+
// so - unlike the shared-file platforms above - Harness gets its own
|
|
86
|
+
// dedicated `harness.md` rule file instead of appending into an arbitrary
|
|
87
|
+
// pre-existing one.
|
|
88
|
+
function installContinueRule(targetFile, label) {
|
|
89
|
+
const dir = path.dirname(targetFile);
|
|
90
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
91
|
+
if (fs.existsSync(targetFile) && fs.readFileSync(targetFile, 'utf8').includes(MARKER)) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const content = [
|
|
95
|
+
`---`,
|
|
96
|
+
`name: Harness OS Guidance`,
|
|
97
|
+
`alwaysApply: true`,
|
|
98
|
+
`description: "Harness OS routing, circuit-breaker awareness, and environment-discovery guidance (advisory only on Continue - no hook mechanism)"`,
|
|
99
|
+
`---`,
|
|
100
|
+
advisoryInstructions.replace(/^\n/, '')
|
|
101
|
+
].join('\n');
|
|
102
|
+
fs.writeFileSync(targetFile, content, 'utf8');
|
|
103
|
+
console.log(` ✅ Installed Continue rule file with Harness guidance (advisory-only): ${label}`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function removeContinueRule(targetFile) {
|
|
107
|
+
if (!fs.existsSync(targetFile)) return;
|
|
108
|
+
try {
|
|
109
|
+
const content = fs.readFileSync(targetFile, 'utf8');
|
|
110
|
+
if (content.includes(MARKER)) {
|
|
111
|
+
fs.unlinkSync(targetFile);
|
|
112
|
+
console.log(` ✅ Removed Harness rule file: ${targetFile}`);
|
|
113
|
+
}
|
|
114
|
+
} catch (e) {
|
|
115
|
+
console.warn(` ⚠️ Error removing ${targetFile}: ${e.message}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function buildCopilotGlobalContent() {
|
|
120
|
+
return [
|
|
121
|
+
`---`,
|
|
122
|
+
`description: "Harness OS Guidance (Advisory)"`,
|
|
123
|
+
`applyTo: "**"`,
|
|
124
|
+
`---`,
|
|
125
|
+
`# Copilot Instructions`,
|
|
126
|
+
``,
|
|
127
|
+
advisoryInstructions.replace(/^\n/, '')
|
|
128
|
+
].join('\n');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function buildCodexGlobalContent() {
|
|
132
|
+
return [
|
|
133
|
+
`---`,
|
|
134
|
+
`description: "Harness OS Guidance - Global custom agent for orchestrating multi-agent workflows"`,
|
|
135
|
+
`name: "Harness"`,
|
|
136
|
+
`user-invocable: true`,
|
|
137
|
+
`---`,
|
|
138
|
+
`# AGENTS.md`,
|
|
139
|
+
``,
|
|
140
|
+
`This file is advisory only - this platform has no hook/execution mechanism to`,
|
|
141
|
+
`enforce it mechanically (unlike Claude Code's hook-based circuit breaker). Treat`,
|
|
142
|
+
`these as strong defaults, not guarantees.`,
|
|
143
|
+
``,
|
|
144
|
+
`- Discover the environment (OS, shell, package manager) before running commands - don't assume.`,
|
|
145
|
+
`- Triage tasks: trivial fixes need no plan; standard features need tests; large refactors need`,
|
|
146
|
+
` an explicit plan reviewed with the human before implementation.`,
|
|
147
|
+
`- If the same error repeats 3 times in a row, STOP retrying. Explain what's failing and ask the`,
|
|
148
|
+
` human for direction instead of continuing to guess.`,
|
|
149
|
+
`- Prefer editing over rewriting; commit logically complete chunks rather than one giant diff.`,
|
|
150
|
+
``
|
|
151
|
+
].join('\n');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
module.exports = {
|
|
155
|
+
MARKER,
|
|
156
|
+
advisoryInstructions,
|
|
157
|
+
injectAdvisoryText,
|
|
158
|
+
removeAdvisoryText,
|
|
159
|
+
installContinueRule,
|
|
160
|
+
removeContinueRule,
|
|
161
|
+
buildCopilotGlobalContent,
|
|
162
|
+
buildCodexGlobalContent,
|
|
163
|
+
};
|