@dombaras/agent-harness 0.1.6 → 0.1.7

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
@@ -123,6 +123,10 @@ npx @dombaras/agent-harness update --target /path/to/project
123
123
  modified harness files. Your unrelated uncommitted work is never staged.
124
124
  - `--no-commit` to skip commit+push, `--no-push` to commit but not push.
125
125
  - `init` never commits.
126
+ - Harness-owned paths are **force-added**, so a project that gitignores deployment
127
+ artifacts (an inherited `.agents/` `.opencode/` `AGENTS.md` pattern) still gets the
128
+ harness commit instead of a raw `git add` failure that silently skips it — force-added
129
+ files are called out in the summary.
126
130
  - **`[Nothing-to-Update]` confirmation**: if the target is already at this CLI's version and no
127
131
  harness-owned file changed, `update` says so explicitly, writes nothing, and makes no commit —
128
132
  a no-op is never mistaken for a sync and never churns `.harness.json`.
@@ -210,9 +210,12 @@ function isGitRepo(target) {
210
210
  // project's next session never sees "unexplained" modified harness files. Scoped
211
211
  // to this run's changed harness files (never `git add -A`) so unrelated uncommitted
212
212
  // work is NEVER swept in. Memory/backup files are excluded (project data / rollback).
213
- // Returns { committed:boolean, staged:string[], skipped:string[], pushed:boolean|null }.
213
+ // Harness-owned paths are force-added (`-f`): target projects often gitignore
214
+ // .agents/ .opencode/ AGENTS.md (inherited from the harness's own .gitignore), and
215
+ // a plain `git add` would fail on the first ignored path and commit NOTHING.
216
+ // Returns { committed:boolean, staged:string[], skipped:string[], pushed:boolean|null, forceAdded:string[] }.
214
217
  function commitHarnessChanges(target, changedRels, opts) {
215
- const out = { committed: false, staged: [], skipped: [], pushed: null };
218
+ const out = { committed: false, staged: [], skipped: [], pushed: null, forceAdded: [] };
216
219
  if (!opts.commit) return out;
217
220
  if (!isGitRepo(target)) {
218
221
  out.skipped.push("not a git repo");
@@ -222,9 +225,13 @@ function commitHarnessChanges(target, changedRels, opts) {
222
225
  out.skipped.push("no harness files changed");
223
226
  return out;
224
227
  }
225
- const addR = runGit(target, ["add", "--", ...changedRels]);
228
+ const ignored = runGit(target, ["check-ignore", ...changedRels]);
229
+ if (ignored.ok && ignored.out) {
230
+ out.forceAdded = ignored.out.split(/\r?\n/).filter(Boolean).map(relKey);
231
+ }
232
+ const addR = runGit(target, ["add", "-f", "--", ...changedRels]);
226
233
  if (!addR.ok) {
227
- out.skipped.push("git add failed: " + addR.err);
234
+ out.skipped.push("git add failed: " + firstGitErrorLine(addR.err));
228
235
  return out;
229
236
  }
230
237
  const diffCached = runGit(target, ["diff", "--cached", "--name-only"]);
@@ -238,7 +245,7 @@ function commitHarnessChanges(target, changedRels, opts) {
238
245
  const message = `chore(harness): @dombaras/agent-harness ${prior}${PKG.version}`;
239
246
  const commitR = runGit(target, ["commit", "-m", message]);
240
247
  if (!commitR.ok) {
241
- out.skipped.push("commit failed: " + commitR.err);
248
+ out.skipped.push("commit failed: " + firstGitErrorLine(commitR.err));
242
249
  return out;
243
250
  }
244
251
  out.committed = true;
@@ -247,7 +254,7 @@ function commitHarnessChanges(target, changedRels, opts) {
247
254
  if (hasRemote) {
248
255
  const pushR = runGit(target, ["push", "origin", "HEAD"]);
249
256
  out.pushed = pushR.ok;
250
- if (!pushR.ok) out.skipped.push("push failed: " + pushR.err);
257
+ if (!pushR.ok) out.skipped.push("push failed: " + firstGitErrorLine(pushR.err));
251
258
  } else {
252
259
  out.skipped.push("no git remote to push");
253
260
  }
@@ -255,6 +262,16 @@ function commitHarnessChanges(target, changedRels, opts) {
255
262
  return out;
256
263
  }
257
264
 
265
+ /* Pull the first real error line out of git's stderr, dropping the LF/CRLF
266
+ * warnings and `hint:` noise that bury the actual message. */
267
+ function firstGitErrorLine(err) {
268
+ const line = String(err || "")
269
+ .split(/\r?\n/)
270
+ .map((l) => l.trim())
271
+ .find((l) => l && !/^warning:/i.test(l) && !/^hint:/i.test(l));
272
+ return line || "git command failed";
273
+ }
274
+
258
275
  // ---------------------------------------------------------------- deploy
259
276
 
260
277
  function backup(target, rel, content) {
@@ -537,6 +554,12 @@ function printCommitResult(result) {
537
554
  console.log("");
538
555
  if (c.committed) {
539
556
  console.log(" committed harness files: " + c.staged.join(", "));
557
+ if (c.forceAdded.length) {
558
+ console.log(
559
+ " force-added (gitignored in this project, but harness-owned): " +
560
+ c.forceAdded.join(", ")
561
+ );
562
+ }
540
563
  console.log(
541
564
  c.pushed === true
542
565
  ? " pushed to origin."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dombaras/agent-harness",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
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"