@dombaras/agent-harness 0.1.11 → 0.1.12

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 CHANGED
@@ -11,8 +11,9 @@ and QA gates — then deploys them into any project.
11
11
 
12
12
  ## Why
13
13
 
14
- - The agent harness is tooling, not application code. It should not be committed
15
- into every app repo.
14
+ - The agent harness is tooling, not application code. Its source lives in the
15
+ npm package you deploy it with `init`/`update` rather than hand-copying it
16
+ into every repo.
16
17
  - One canonical, versioned source of truth for personas/rules/QA tiers, deployed
17
18
  on demand and updatable via `npx @dombaras/agent-harness update`.
18
19
 
@@ -44,6 +45,7 @@ npx @dombaras/agent-harness init --target . --dry-run
44
45
  | `scripts/qa/*` | `test:dispatch` / `test:governance` / `test:qa-plan` gates + QA-script wiring check | harness (overwrite) |
45
46
  | `.agents/memory/*` | project data (domain-map, stack-versions, handoff, locations, model-routing, history, flow-map, qa-plan) | **project** (create-if-missing) |
46
47
  | `.harness.json` | deployed version + project profile + per-file checksums | harness |
48
+ | `.gitignore` | harness-managed section (`.harness-backup/`) merged in, project entries preserved | harness (merged) |
47
49
 
48
50
  ### `opencode.json` is merged, not clobbered
49
51
 
@@ -109,10 +111,9 @@ warns but does not block; the guarantee only applies to registered flows.
109
111
  `opencode/deepseek-v4-pro` (gateway), `pickle` → `opencode/big-pickle`, or any
110
112
  explicit `provider/model`. Restart opencode after switching (config reads once).
111
113
  - **`/board` command** — every deploy ships an opencode command
112
- (`.opencode/command/board.md`) that refreshes the canonical `BACKLOG.md` board:
113
- `git pull --ff-only` (safe, never forces), then renders Open (by priority),
114
- Frozen, the last few shipped rows, and the newest `.agents/memory/handoff.md`
115
- delta. Read-only — it never edits the board.
114
+ (`.opencode/command/board.md`) that reads the local `BACKLOG.md` and renders a
115
+ clean task list (Priority · Title · Short description). Read-only, no git the
116
+ local file is the source of truth.
116
117
 
117
118
  ## QA gates
118
119
 
@@ -149,11 +150,13 @@ npx @dombaras/agent-harness update --target /path/to/project
149
150
  - Overwrites harness-owned files, preserves `.agents/memory/*` and `BACKLOG.md`.
150
151
  - Auto-wires the harness gate scripts (`test:dispatch`, `test:governance`,
151
152
  `test:qa-plan`, `test:backlog`) into the target's `package.json` (merged, add-only).
152
- - **Auto-commits** only the harness files it changed (`chore(harness): @dombaras/agent-harness
153
+ - **Auto-commits** the harness files it changed (`chore(harness): @dombaras/agent-harness
153
154
  <old> -> <new>`) and **pushes** to origin, so the next session never sees unexplained
154
155
  modified harness files. Your unrelated uncommitted work is never staged.
155
156
  - `--no-commit` to skip commit+push, `--no-push` to commit but not push.
156
- - `init` never commits.
157
+ - `init` auto-commits + pushes by default too: it commits everything it scaffolds
158
+ (including `.agents/memory/*`, `.agents/features/*`, and `BACKLOG.md`) so a fresh
159
+ project starts fully tracked and no harness file is left untracked.
157
160
  - Harness-owned paths are **force-added**, so a project that gitignores deployment
158
161
  artifacts (an inherited `.agents/` `.opencode/` `AGENTS.md` pattern) still gets the
159
162
  harness commit instead of a raw `git add` failure that silently skips it — force-added
@@ -171,6 +174,10 @@ npx @dombaras/agent-harness update --target /path/to/project
171
174
  last deploy (tracked by checksum in `.harness.json`), it is backed up to
172
175
  `.harness-backup/<timestamp>/` before overwrite.
173
176
  - `opencode.json` is merged (project keys preserved).
177
+ - **Managed `.gitignore`**: the harness merges a marked section (`.harness-backup/`, its
178
+ local rollback artifacts) into the project's `.gitignore`, preserving every project entry.
179
+ New harness files are tracked (committed), not ignored — so they don't need a gitignore
180
+ change. If the harness ever adds a new local-only artifact, `update` re-merges the entry.
174
181
  - `--dry-run` previews the plan without writing.
175
182
 
176
183
  ### Backlog migration (`migrate-backlog`)
@@ -217,6 +217,25 @@ function mergePackageJson(target) {
217
217
  return { text: JSON.stringify(merged, null, 2) + "\n", hadPkg };
218
218
  }
219
219
 
220
+ // Harness-managed .gitignore entries. These are LOCAL-ONLY artifacts (never
221
+ // committed): everything else the harness deploys is tracked by git. Entries
222
+ // live in a marked section so `update` can re-merge them (and pick up new
223
+ // entries) without touching the project's own ignores.
224
+ const GITIGNORE_MARKER = "# agent-harness (managed below)";
225
+ const HARNESS_IGNORE_ENTRIES = [".harness-backup/"];
226
+
227
+ function mergeGitignore(target) {
228
+ const p = path.join(target, ".gitignore");
229
+ const existing = fs.existsSync(p) ? fs.readFileSync(p, "utf8") : "";
230
+ const lines = existing.split(/\r?\n/);
231
+ const idx = lines.findIndex((l) => l === GITIGNORE_MARKER);
232
+ const kept = idx === -1 ? lines : lines.slice(0, idx);
233
+ while (kept.length && kept[kept.length - 1].trim() === "") kept.pop();
234
+ const managed = [GITIGNORE_MARKER, ...HARNESS_IGNORE_ENTRIES, ""];
235
+ const out = kept.length ? [...kept, "", ...managed] : [...managed];
236
+ return out.join("\n");
237
+ }
238
+
220
239
  // ---------------------------------------------------------------- git helpers
221
240
 
222
241
  function runGit(target, args) {
@@ -348,6 +367,23 @@ async function deploy(target, opts) {
348
367
  }
349
368
  }
350
369
 
370
+ // Merge harness-managed gitignore entries (add-only, marked section).
371
+ {
372
+ const text = mergeGitignore(target);
373
+ const key = ".gitignore";
374
+ const targetAbs = path.join(target, ".gitignore");
375
+ const had = fs.existsSync(targetAbs);
376
+ const current = had ? fs.readFileSync(targetAbs, "utf8") : null;
377
+ if (!had) actions.push({ rel: key, kind: "create" });
378
+ else if (current !== text) actions.push({ rel: key, kind: "merge" });
379
+ else actions.push({ rel: key, kind: "unchanged" });
380
+ manifest[key] = sha256(text);
381
+ if (!dryRun) {
382
+ fs.mkdirSync(path.dirname(targetAbs), { recursive: true });
383
+ fs.writeFileSync(targetAbs, text, "utf8");
384
+ }
385
+ }
386
+
351
387
  for (const { abs, rel } of listFiles(TEMPLATES_DIR)) {
352
388
  const key = relKey(rel);
353
389
  const targetAbs = path.join(target, rel);
@@ -425,15 +461,15 @@ async function deploy(target, opts) {
425
461
  fs.writeFileSync(path.join(target, CONFIG_FILE), JSON.stringify(config, null, 2) + "\n", "utf8");
426
462
  }
427
463
 
428
- // Auto-commit only this run's changed harness-owned files (update only).
464
+ // Auto-commit the files this run created/changed so nothing the harness
465
+ // deploys is left untracked. Runs for both `init` and `update`. Excludes only
466
+ // rollback artifacts; freshly-scaffolded project-data files (memory/features/
467
+ // BACKLOG) are committed so they start tracked, while pre-existing project
468
+ // data is never touched (a "preserve" never enters `changedRelsAll`).
429
469
  let commitResult = null;
430
- if (isUpdate && !dryRun && !nothingToUpdate) {
431
- const changedRels = changedRelsAll.filter(
432
- (r) =>
433
- !r.startsWith(".agents/memory/") &&
434
- !r.startsWith(".agents/features/") &&
435
- !r.startsWith(".harness-backup/")
436
- );
470
+ const shouldCommit = !dryRun && (!isUpdate || !nothingToUpdate);
471
+ if (shouldCommit) {
472
+ const changedRels = changedRelsAll.filter((r) => !r.startsWith(".harness-backup/"));
437
473
  changedRels.push(CONFIG_FILE); // .harness.json reflects the new deployed version
438
474
  commitResult = commitHarnessChanges(target, changedRels, {
439
475
  commit,
@@ -527,13 +563,14 @@ function printUsage() {
527
563
  console.log(
528
564
  `agent-harness v${PKG.version}\n\n` +
529
565
  `Usage:\n` +
530
- ` agent-harness init [--target <dir>] [--name <project>] [--domain <desc>] [--yes] [--dry-run]\n` +
566
+ ` agent-harness init [--target <dir>] [--name <project>] [--domain <desc>] [--yes] [--dry-run] [--no-commit] [--no-push]\n` +
531
567
  ` agent-harness update [--target <dir>] [--dry-run] [--no-commit] [--no-push]\n` +
532
568
  ` agent-harness migrate-backlog [--target <dir>]\n` +
533
569
  `\n` +
534
- ` update auto-commits only the harness files it changes (chore(harness): ...) and\n` +
535
- ` pushes to origin by default. Use --no-commit to skip commit+push, or --no-push\n` +
536
- ` to commit but not push. Your unrelated uncommitted work is never staged.\n` +
570
+ ` init and update auto-commit only the harness files they create/change\n` +
571
+ ` (chore(harness): ...) and push to origin by default. Use --no-commit to\n` +
572
+ ` skip commit+push, or --no-push to commit but not push. Your unrelated\n` +
573
+ ` uncommitted work is never staged.\n` +
537
574
  `\n` +
538
575
  ` migrate-backlog consolidates any live \`.agents/features/INDEX.md\` F-rows and\n` +
539
576
  ` \`.agents/memory/todo.md\` into the canonical BACKLOG.md, then rewrites those\n` +
@@ -785,10 +822,11 @@ async function init(target, flags) {
785
822
  yes: !!flags["--yes"],
786
823
  dryRun: !!flags["--dry-run"],
787
824
  isUpdate: false,
788
- commit: false,
789
- push: false,
825
+ commit: !flags["--no-commit"],
826
+ push: !flags["--no-commit"] && !flags["--no-push"],
790
827
  });
791
828
  printSummary(result, false);
829
+ printCommitResult(result);
792
830
  if (!result.dryRun) printNextSteps();
793
831
  }
794
832
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dombaras/agent-harness",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "Reusable multi-agent harness for AI-assisted development: personas, skills, operating rules, model routing, and QA gates. Deploy into any project with `npx @dombaras/agent-harness init`.",
5
5
  "bin": {
6
6
  "agent-harness": "bin/agent-harness.js"
@@ -1,23 +1,21 @@
1
1
  ---
2
- description: Refresh the task board pull the latest, then show BACKLOG.md open/frozen/shipped plus the newest handoff delta.
2
+ description: Show the local BACKLOG.md as a clean task list (title, short description, priority). Read-only no git.
3
3
  ---
4
4
 
5
- Refresh the canonical task board. Run these steps read-only, then report terse.
5
+ Read `BACKLOG.md` at the repo root and display a clean, human-readable task list.
6
+ The local file is the source of truth — do NOT run git, do NOT pull, do NOT edit
7
+ anything.
6
8
 
7
- 1. Sync the workspace (never rewrite history, never force):
8
- - `git fetch --all --prune`
9
- - `git pull --ff-only`
10
- - If the pull fails (uncommitted local changes / conflict), do NOT force — report the failure and show the board from the current on-disk state, flagged "possibly stale".
9
+ Render the `Open` rows (and the `Active / next` picks if present) as a table with
10
+ exactly these columns:
11
11
 
12
- 2. Read `BACKLOG.md` (repo root) and `.agents/memory/handoff.md`.
12
+ | Priority | Title | Short description |
13
+ |----------|-------|-------------------|
14
+ | P1 | F-001 | block something |
13
15
 
14
- 3. Render a compact board:
15
- - `Active / next` picks (if any).
16
- - `Open` grouped by priority P1 → P4, each row as `ID — task (evidence)`.
17
- - `Frozen` rows with their reopen condition (one line each).
18
- - `Archive` — only the last ~5 shipped rows (date/commit).
19
- - Latest handoff delta (planned → shipped → deferred) from `.agents/memory/handoff.md`, plus any new `git log` commits from other sessions since the last refresh.
16
+ - **Priority** = the `P` cell.
17
+ - **Title** = the row's ID.
18
+ - **Short description** = the `Task` cell.
19
+ - Omit the `Evidence` column. Do not render the Frozen / Archive sections.
20
20
 
21
- Rules:
22
- - Read-only: never edit `BACKLOG.md`, `.agents/memory/*`, or any code here.
23
- - This is a status snapshot, not a report. If a field is unknown write `?` — never invent.
21
+ One row per open task. Never invent — show a `?` cell exactly as `?`.