@dombaras/agent-harness 0.1.5 → 0.1.6
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 +9 -0
- package/bin/agent-harness.js +52 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -123,6 +123,15 @@ 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
|
+
- **`[Nothing-to-Update]` confirmation**: if the target is already at this CLI's version and no
|
|
127
|
+
harness-owned file changed, `update` says so explicitly, writes nothing, and makes no commit —
|
|
128
|
+
a no-op is never mistaken for a sync and never churns `.harness.json`.
|
|
129
|
+
- **Downgrade guard**: `update` refuses to run on a target whose deployed harness is NEWER than
|
|
130
|
+
this CLI (e.g. deployed from a local checkout that was never published) and tells you to publish
|
|
131
|
+
that version first.
|
|
132
|
+
- **Published-version check**: if this CLI's version is not the latest `dist-tags.latest` on npm,
|
|
133
|
+
`update` warns you — catches the "bumped the version and updated a project from a local
|
|
134
|
+
checkout, but never published" gap before it silently forks the projects.
|
|
126
135
|
- **Non-destructive**: if a harness-owned file was modified locally since the
|
|
127
136
|
last deploy (tracked by checksum in `.harness.json`), it is backed up to
|
|
128
137
|
`.harness-backup/<timestamp>/` before overwrite.
|
package/bin/agent-harness.js
CHANGED
|
@@ -274,6 +274,17 @@ async function deploy(target, opts) {
|
|
|
274
274
|
}
|
|
275
275
|
const VARIABLES = { PROJECT_NAME: projectName, PROJECT_DOMAIN: projectDomain };
|
|
276
276
|
|
|
277
|
+
// Refuse to downgrade: the target's deployed harness is newer than this CLI.
|
|
278
|
+
// This is how the "I updated from a local checkout that I never published"
|
|
279
|
+
// mistake surfaces instead of silently writing older templates over a newer
|
|
280
|
+
// deployment (and auto-committing that regression).
|
|
281
|
+
if (isUpdate && existing.version && compareVersions(existing.version, PKG.version) > 0) {
|
|
282
|
+
throw new Error(
|
|
283
|
+
`"${projectName}" has harness v${existing.version} — NEWER than this CLI (v${PKG.version}). ` +
|
|
284
|
+
`Not downgrading. Publish v${existing.version} (or this CLI) so \`update\` can re-sync from the registry.`
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
|
|
277
288
|
const previousFiles = existing.files || {};
|
|
278
289
|
const actions = [];
|
|
279
290
|
const manifest = {};
|
|
@@ -349,6 +360,16 @@ async function deploy(target, opts) {
|
|
|
349
360
|
}
|
|
350
361
|
}
|
|
351
362
|
|
|
363
|
+
// Nothing-to-update detection: an update that made no effective change to any
|
|
364
|
+
// harness-owned file and was already running this exact version is a no-op —
|
|
365
|
+
// report it clearly instead of printing a zero-delta "Updated", and leave the
|
|
366
|
+
// target byte-for-byte untouched (no .harness.json timestamp churn, no commit).
|
|
367
|
+
const changedRelsAll = actions
|
|
368
|
+
.filter((a) => ["create", "overwrite", "overwrite (backup)", "merge"].includes(a.kind))
|
|
369
|
+
.map((a) => a.rel);
|
|
370
|
+
const nothingToUpdate =
|
|
371
|
+
!!isUpdate && changedRelsAll.length === 0 && compareVersions(existing.version || "0", PKG.version) === 0;
|
|
372
|
+
|
|
352
373
|
const config = {
|
|
353
374
|
version: PKG.version,
|
|
354
375
|
projectName,
|
|
@@ -357,22 +378,13 @@ async function deploy(target, opts) {
|
|
|
357
378
|
updatedAt: new Date().toISOString(),
|
|
358
379
|
files: manifest,
|
|
359
380
|
};
|
|
360
|
-
if (!dryRun) {
|
|
381
|
+
if (!dryRun && !nothingToUpdate) {
|
|
361
382
|
fs.writeFileSync(path.join(target, CONFIG_FILE), JSON.stringify(config, null, 2) + "\n", "utf8");
|
|
362
383
|
}
|
|
363
384
|
|
|
364
|
-
// Nothing-to-update detection: an update that made no effective change to any
|
|
365
|
-
// harness-owned file and was already running this exact version is a no-op —
|
|
366
|
-
// still report it clearly instead of printing a zero-delta "Updated".
|
|
367
|
-
const changedRelsAll = actions
|
|
368
|
-
.filter((a) => ["create", "overwrite", "overwrite (backup)", "merge"].includes(a.kind))
|
|
369
|
-
.map((a) => a.rel);
|
|
370
|
-
const nothingToUpdate =
|
|
371
|
-
!!isUpdate && changedRelsAll.length === 0 && compareVersions(existing.version || "0", PKG.version) === 0;
|
|
372
|
-
|
|
373
385
|
// Auto-commit only this run's changed harness-owned files (update only).
|
|
374
386
|
let commitResult = null;
|
|
375
|
-
if (isUpdate && !dryRun) {
|
|
387
|
+
if (isUpdate && !dryRun && !nothingToUpdate) {
|
|
376
388
|
const changedRels = changedRelsAll.filter(
|
|
377
389
|
(r) => !r.startsWith(".agents/memory/") && !r.startsWith(".harness-backup/")
|
|
378
390
|
);
|
|
@@ -404,10 +416,22 @@ function summarize(actions) {
|
|
|
404
416
|
|
|
405
417
|
function printSummary(result, isUpdate) {
|
|
406
418
|
const { projectName, actions, dryRun } = result;
|
|
419
|
+
|
|
420
|
+
if (isUpdate && result.nothingToUpdate) {
|
|
421
|
+
console.log(
|
|
422
|
+
`\n[Nothing-to-Update] agent-harness v${PKG.version}: "${projectName}" is already at ` +
|
|
423
|
+
`v${result.priorVersion || PKG.version} and no harness-owned file changed.`
|
|
424
|
+
);
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
|
|
407
428
|
const verb = isUpdate
|
|
408
429
|
? (dryRun ? "Would update" : "Updated")
|
|
409
430
|
: (dryRun ? "Would initialize" : "Initialized");
|
|
410
431
|
console.log(`\nagent-harness v${PKG.version} ${verb.toLowerCase()} "${projectName}"` + (dryRun ? " (dry run)" : ""));
|
|
432
|
+
if (isUpdate && result.priorVersion && result.priorVersion !== PKG.version) {
|
|
433
|
+
console.log(` harness: v${result.priorVersion} -> v${PKG.version}`);
|
|
434
|
+
}
|
|
411
435
|
for (const a of actions) console.log(` [${a.kind}] ${a.rel}`);
|
|
412
436
|
const counts = summarize(actions);
|
|
413
437
|
console.log(
|
|
@@ -417,6 +441,22 @@ function printSummary(result, isUpdate) {
|
|
|
417
441
|
);
|
|
418
442
|
}
|
|
419
443
|
|
|
444
|
+
/* Best-effort warning: when this CLI's version is not the latest published on
|
|
445
|
+
* the registry, flag it. This catches the "bumped + ran update from a local
|
|
446
|
+
* checkout, but never published" silent gap. */
|
|
447
|
+
function printUnpublishedWarning() {
|
|
448
|
+
const published = publishedLatestVersion();
|
|
449
|
+
if (published == null || published === "" || published === PKG.version) return;
|
|
450
|
+
const cmp = compareVersions(PKG.version, published);
|
|
451
|
+
if (cmp <= 0) return;
|
|
452
|
+
console.log(
|
|
453
|
+
`\n WARNING: this CLI is v${PKG.version}, but the latest version published on ` +
|
|
454
|
+
`npm is v${published}. If you ran this from a local checkout, the changes were ` +
|
|
455
|
+
`NOT published — Publish first, then \`update\` other projects, or they will ` +
|
|
456
|
+
`branch off an older harness.`
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
|
|
420
460
|
function printNextSteps() {
|
|
421
461
|
console.log(" Next steps:");
|
|
422
462
|
console.log(" 1. Fill in `.agents/memory/domain-map.md`, `.agents/memory/stack-versions.md`,");
|
|
@@ -487,6 +527,7 @@ async function update(target, flags) {
|
|
|
487
527
|
push: !flags["--no-commit"] && !flags["--no-push"],
|
|
488
528
|
});
|
|
489
529
|
printSummary(result, true);
|
|
530
|
+
printUnpublishedWarning();
|
|
490
531
|
printCommitResult(result);
|
|
491
532
|
}
|
|
492
533
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dombaras/agent-harness",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
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"
|