@augurworks/augur 0.15.10 → 0.15.11

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@augurworks/augur",
3
- "version": "0.15.10",
3
+ "version": "0.15.11",
4
4
  "files": [
5
5
  "scripts/",
6
6
  "build.js",
package/scripts/hook.mjs CHANGED
@@ -5,13 +5,15 @@
5
5
  // JSON on stdin (docs/drafts-that-land.md §7). Both answer with an exit code: 0 lets the
6
6
  // edit through, 2 refuses it and puts one sentence on stderr for the agent to read in its
7
7
  // next tool result. NOTHING ELSE EXITS NON-ZERO: an unreadable payload, a missing
8
- // registry, an exception — every accident exits 0 and says nothing, because the hook is
9
- // installed machine-wide and a bug here would take every editor down with it.
8
+ // registry, an exception — every accident exits 0 and says nothing, because the hook runs
9
+ // around every edit in the folder it is installed for and a bug here would take that
10
+ // editor down with it.
10
11
  //
11
12
  // pre refuse a write into a read-only copy, or into a shared checkout's prototype
12
13
  // post save the draft the edited file belongs to; refused saves fail with the reason
13
14
  //
14
- // `install|remove|status` manage the adapters `augur open` installs them once.
15
+ // `install|remove|status` manage the adapters for the folder they run in (the agent tool's
16
+ // project-local settings) — `augur open` installs them there the first time.
15
17
  import fs from "node:fs";
16
18
  import { ADAPTERS, denyDecision, saveDecision, installAdapters, removeAdapters } from "./lib/adapters.mjs";
17
19
  import { registryList, readState, unitClient, doSave } from "./lib/draft.mjs";
@@ -24,7 +26,7 @@ if (event === "install" || event === "remove" || event === "status") {
24
26
  const rows = event === "install" ? installAdapters() : event === "remove" ? removeAdapters() : installAdapters({ dryRun: true });
25
27
  for (const r of rows) {
26
28
  const verdict = event === "status" ? (r.result === "unchanged" ? "installed" : r.result === "absent" ? "absent" : "not installed") : r.result;
27
- console.log(`${r.name}: ${verdict}${r.path ? ` (${r.path})` : ""}`);
29
+ console.log(`${r.name}: ${verdict}${r.path ? ` (${r.path})` : ""}${r.movedFrom ? ` — an older machine-wide entry in ${r.movedFrom} was removed` : ""}`);
28
30
  }
29
31
  process.exit(0);
30
32
  }
@@ -84,7 +84,14 @@ export const ADAPTERS = Object.freeze([
84
84
  Object.freeze({
85
85
  id: "claude-code",
86
86
  name: "Claude Code",
87
- settingsPath: (home) => path.join(home, ".claude", "settings.json"),
87
+ // The hooks live in the PROJECT's local settings — the folder `augur open` runs in, which
88
+ // is where the draft folder is made — never in the account-wide file. Three cold agents
89
+ // in a row flagged a write to ~/.claude/settings.json and their person asked for it to be
90
+ // undone; a hook whose command carries this machine's absolute path belongs in the
91
+ // per-machine local file anyway. `legacyPath` is where older engines wrote it; an entry
92
+ // found there is removed on the next install so the two never fire together.
93
+ settingsPath: (cwd) => path.join(cwd, ".claude", "settings.local.json"),
94
+ legacyPath: (home) => path.join(home, ".claude", "settings.json"),
88
95
  detect: (home) => fs.existsSync(path.join(home, ".claude")),
89
96
  matcher: "Write|Edit|MultiEdit|NotebookEdit",
90
97
  payload: (j) => {
@@ -154,20 +161,28 @@ function writeJson(p, v) {
154
161
  fs.renameSync(p + ".tmp", p);
155
162
  }
156
163
 
157
- function applyToAdapters({ home = os.homedir(), dryRun = false } = {}, decide) {
164
+ function applyToAdapters({ home = os.homedir(), cwd = process.cwd(), dryRun = false } = {}, decide) {
158
165
  const out = [];
159
166
  for (const a of ADAPTERS) {
160
167
  if (!a.detect(home)) { out.push({ id: a.id, name: a.name, result: "absent" }); continue; }
161
- const p = a.settingsPath(home);
168
+ const p = a.settingsPath(cwd);
162
169
  const cur = readJson(p);
163
170
  const r = decide(a, cur);
164
171
  if (r.changed && !dryRun) writeJson(p, r.settings);
165
- out.push({ id: a.id, name: a.name, result: r.changed ? r.did : "unchanged", path: p });
172
+ // An entry an older engine left in the account-wide file: taken out, and said.
173
+ let movedFrom = null;
174
+ const lp = a.legacyPath ? a.legacyPath(home) : null;
175
+ const legacy = lp ? readJson(lp) : null;
176
+ if (legacy) {
177
+ const s = stripHooks(legacy);
178
+ if (s.changed) { movedFrom = lp; if (!dryRun) writeJson(lp, s.settings); }
179
+ }
180
+ out.push({ id: a.id, name: a.name, result: r.changed ? r.did : "unchanged", path: p, ...(movedFrom ? { movedFrom } : {}) });
166
181
  }
167
182
  return out;
168
183
  }
169
184
 
170
- /** Install the two hooks for every tool present on this machine. Idempotent; keeps every other hook. */
185
+ /** Install the two hooks, for the folder `cwd` (the agent tool's project-local settings), for every tool present on this machine. Idempotent; keeps every other hook. */
171
186
  export function installAdapters(opts = {}) {
172
187
  return applyToAdapters(opts, (a, cur) => {
173
188
  const onPath = typeof opts.onPath === "boolean" ? opts.onPath : augurOnPath();
package/scripts/open.mjs CHANGED
@@ -47,12 +47,14 @@ if (!r.ok) {
47
47
  die(`could not open: ${r.error || r.status}${r.reason ? ` (${r.reason})` : ""}${r.message ? ` — ${r.message}` : ""}`);
48
48
  }
49
49
  log(r.isNew ? `draft ${r.draftId} on ${unit} — a NEW prototype; ${dir} is empty, write its index.html there` : `draft ${r.draftId} on ${unit} — ${r.files} file(s) in ${dir}`);
50
- // The agent tool's hooks, installed for this machine the first time a draft is opened
51
- // here (idempotent; `AUGUR_NO_ADAPTERS=1` skips it — the suite and CI set it).
50
+ // The agent tool's hooks, installed for THIS folder (its project-local settings) the first
51
+ // time a draft is opened from here — never account-wide (idempotent; `AUGUR_NO_ADAPTERS=1`
52
+ // skips it — the suite and CI set it).
52
53
  if (!process.env.AUGUR_NO_ADAPTERS) {
53
54
  for (const a of installAdapters()) {
54
- if (a.result === "installed") log(`${a.name}: a save hook is now in ${a.path} — after each edit inside a draft folder it runs \`augur hook post\`, which saves that draft to ${origin}; before an edit it refuses writes into a shared checkout's prototypes. It does nothing outside draft folders and talks to nothing else; \`augur hook remove\` takes it out.`);
55
+ if (a.result === "installed") log(`${a.name}: a save hook is now in ${a.path} — for this folder only, nothing account-wide. After each edit inside a draft folder here it runs \`augur hook post\`, which saves that draft to ${origin}; before an edit it refuses writes into a shared checkout's prototypes. It does nothing else and talks to nothing else; \`augur hook remove\` run here takes it out.`);
55
56
  else if (a.result === "updated") log(`${a.name}: editor hooks updated (${a.path}).`);
57
+ if (a.movedFrom) log(`${a.name}: an older machine-wide entry in ${a.movedFrom} was removed; the hook lives with the folder now.`);
56
58
  }
57
59
  }
58
60
  if (r.others.length) {
package/src/_worker.js CHANGED
@@ -9307,9 +9307,10 @@ function doorText(f) {
9307
9307
  ? `You need no source tree here: \`augur open <opportunity>/<prototype>\` fetches that one\n`
9308
9308
  + `prototype into a folder of its own (see below). Do not clone the workspace first.\n\n`
9309
9309
  + `Until \`npm i -g @augurworks/augur\`, every verb runs as \`npx @augurworks/augur <verb>\`.\n`
9310
- + `The first \`open\` on a machine also installs a save hook in the editor tool's\n`
9311
- + `settings (it says which file): after each edit inside a draft folder it saves that\n`
9312
- + `draft; it does nothing elsewhere, and \`augur hook remove\` takes it out.\n\n`
9310
+ + `The first \`open\` in a folder also installs a save hook in the editor tool's settings\n`
9311
+ + `for that folder only (.claude/settings.local.json there; it says so), never account-wide:\n`
9312
+ + `after each edit inside a draft folder it saves that draft; it does nothing elsewhere,\n`
9313
+ + `and \`augur hook remove\` in that folder takes it out.\n\n`
9313
9314
  : `With no source tree yet, \`npx @augurworks/augur clone --space ${f.workspace}\` then fetches\n`
9314
9315
  + `one (it reads the origin from the pairing).\n\n`)
9315
9316
  : `Device pairing is switched off on this workspace. Ask an admin for an invite;\n`