@udondan/avanti 0.12.1 → 0.13.0

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
@@ -1,4 +1,4 @@
1
- # avanti
1
+ # Avanti!
2
2
 
3
3
  A stateful package manager for arbitrary text files. Declare what you need and where to get it; avanti fetches, diffs, and writes with full version history, atomic rollbacks, and diff-before-apply safety.
4
4
 
@@ -79,15 +79,16 @@ npx @udondan/avanti --help
79
79
  avanti [options] [command]
80
80
 
81
81
  Options:
82
- -c, --config <path|url> path or remote spec for config file (default: auto-detected)
83
- -w, --working-dir <path> working directory for resolving paths (default: current directory)
82
+ -c, --config <path|url> path or remote spec for config file (default: auto-detected)
83
+ -w, --working-dir <path> working directory for resolving paths (default: current directory)
84
84
 
85
85
  Commands:
86
- diff [pullId] Show diff between remote sources and local files, or vs a past pull
87
- pull [--yes] Pull remote sources and write to local files
88
- log [file] Show pull history for the current project
89
- revert [pullId] [--yes] Atomically revert all project files to a past pull state
90
- reset [--yes] Restore all tracked files to their pre-avanti state
86
+ diff [pullId] Show diff between remote sources and local files, or vs a past pull
87
+ pull [--yes] [--accept-changes] Pull remote sources and write to local files
88
+ lock [--force] Pin SHA values for all remote sources in the config
89
+ log [file] Show pull history for the current project
90
+ revert [pullId] [--yes] Atomically revert all project files to a past pull state
91
+ reset [--yes] Restore all tracked files to their pre-avanti state
91
92
  ```
92
93
 
93
94
  ### `avanti diff`
@@ -98,8 +99,35 @@ Shows a colored git-diff-like output of what would change. Exits `0` if no chang
98
99
 
99
100
  Fetches all sources, shows the diff, and prompts for confirmation before writing. Use `--yes` to skip the prompt.
100
101
 
102
+ If any source has a `sha` field and the fetched content's SHA no longer matches, the pull is aborted with a mismatch error. Use `--accept-changes` to review the diff, confirm, and automatically update the SHA values in the config file.
103
+
101
104
  When avanti has previously synced a directory from a remote source and a file is no longer present in that source, the file is treated as stale: if avanti created it, it is deleted; if it existed before avanti first touched it, the original content is restored. Stale file changes appear in the diff before you confirm.
102
105
 
106
+ ### `avanti lock`
107
+
108
+ Fetches all remote sources and writes a SHA-256 fingerprint for each one into the config file. Comments and formatting are preserved.
109
+
110
+ ```sh
111
+ avanti lock # pin all unpinned remote sources
112
+ avanti lock --force # overwrite existing SHA values with fresh ones
113
+ ```
114
+
115
+ Once a source is pinned, `avanti pull` will verify the fetched content's SHA before applying any changes. If the upstream changed unexpectedly, avanti aborts with a clear error pointing to the affected source:
116
+
117
+ ```text
118
+ SHA mismatch for github:org/standards:company-rules.md
119
+ expected: abc123...
120
+ got: def456...
121
+
122
+ Run `avanti pull --accept-changes` to review the diff and update SHA values.
123
+ ```
124
+
125
+ `avanti diff` shows a `⚠ SHA mismatch` warning inline for any source that no longer matches its pinned SHA.
126
+
127
+ SHA is computed over the raw fetched content of each source, before any `replace` or `post` processing. Each file's path and content are fed into the hash in sorted order, separated by null bytes — so renames and additions affect the fingerprint even for single-file sources. Pull history records the observed SHA for every source, so `avanti log` shows a full audit trail of what changed and when.
128
+
129
+ Excluded from SHA pinning: local paths and `raw:` sources (their content is either authored locally or inline in the config, so changes are always visible).
130
+
103
131
  ## History
104
132
 
105
133
  Every successful `avanti pull` that writes at least one file is recorded in a local history store. This lets you inspect what changed, preview past states, revert the whole project, or fully undo all avanti changes.
@@ -287,27 +315,34 @@ src: ~/templates/file.txt
287
315
  src: /absolute/path/file.txt
288
316
  ```
289
317
 
290
- **Map** — for exec, gitlab, github, bitbucket, git, s3, vault, raw:
318
+ **Map** — for exec, gitlab, github, bitbucket, git, s3, vault, http, raw:
291
319
 
292
320
  ```yaml
293
321
  src:
294
322
  exec: <shell command> # stdout becomes file content; target required
323
+ sha: abc123... # optional SHA-256 to verify stdout (see below)
295
324
 
296
325
  src:
297
326
  raw: | # inline content; target required
298
327
  your content here
299
328
 
329
+ src:
330
+ http: https://example.com/file.txt # explicit http/https URL with optional SHA
331
+ sha: abc123...
332
+
300
333
  src:
301
334
  gitlab:
302
335
  project: group/repo # GitLab project path
303
336
  file: path/to/file.txt # file or directory in repo
304
337
  ref: main # branch, tag, or $latest (optional)
338
+ sha: abc123... # optional SHA-256 fingerprint
305
339
 
306
340
  src:
307
341
  github:
308
342
  repo: owner/repo # GitHub owner/repo
309
343
  file: path/to/file.txt # file or directory in repo
310
344
  ref: main # branch, tag, or $latest (optional)
345
+ sha: abc123... # optional SHA-256 fingerprint
311
346
 
312
347
  src:
313
348
  bitbucket:
@@ -315,22 +350,32 @@ src:
315
350
  repo: my-repo # repository slug
316
351
  file: path/to/file.txt # file or directory in repo
317
352
  ref: main # branch, tag, or $latest (optional)
353
+ sha: abc123... # optional SHA-256 fingerprint
318
354
 
319
355
  src:
320
356
  git:
321
357
  repo: https://github.com/org/repo.git # any git remote (HTTPS or SSH)
322
358
  file: path/to/file.txt # file or directory in repo
323
359
  ref: main # branch, tag, or commit hash (optional)
360
+ sha: abc123... # optional SHA-256 fingerprint
324
361
 
325
362
  src:
326
363
  s3: s3://my-bucket/path/to/file.txt # S3 URI; end with / for a prefix sync
364
+ sha: abc123... # optional SHA-256 fingerprint
327
365
 
328
366
  src:
329
367
  vault:
330
368
  path: secret/myapp/config # Vault KV path (mount/subpath)
331
369
  field: db_password # specific field to extract (optional; omit for full JSON)
370
+ sha: abc123... # optional SHA-256 fingerprint
332
371
  ```
333
372
 
373
+ #### SHA pinning
374
+
375
+ The optional `sha` field pins a source to a specific content fingerprint. When present, avanti verifies the SHA-256 of the raw fetched content matches before writing anything. This makes your config act as a selective lockfile — only sources you care about get pinned, and changes are surfaced explicitly rather than applied silently.
376
+
377
+ Use `avanti lock` to compute and write SHA values automatically. Use `avanti pull --accept-changes` to review a mismatch and update the pinned SHA. Local paths and `raw:` sources do not support `sha` (changes to those are inherently visible).
378
+
334
379
  ### Directory Sources
335
380
 
336
381
  Any source type that references a path (local, GitLab, GitHub, Bitbucket, git, S3) can point to a directory instead of a single file. End the path with `/` to declare it a directory explicitly; without a trailing slash the tool probes the remote to decide.
package/dist/cli.js CHANGED
@@ -5,6 +5,7 @@ const commander_1 = require("commander");
5
5
  const diff_1 = require("./commands/diff");
6
6
  const pull_1 = require("./commands/pull");
7
7
  const log_1 = require("./commands/log");
8
+ const lock_1 = require("./commands/lock");
8
9
  const revert_1 = require("./commands/revert");
9
10
  const reset_1 = require("./commands/reset");
10
11
  const package_json_1 = require("../package.json");
@@ -17,6 +18,7 @@ program
17
18
  .option('-w, --working-dir <path>', 'working directory for resolving relative paths (default: current directory)');
18
19
  program.addCommand((0, diff_1.diffCommand)());
19
20
  program.addCommand((0, pull_1.pullCommand)());
21
+ program.addCommand((0, lock_1.lockCommand)());
20
22
  program.addCommand((0, log_1.logCommand)());
21
23
  program.addCommand((0, revert_1.revertCommand)());
22
24
  program.addCommand((0, reset_1.resetCommand)());
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,0CAA8C;AAC9C,0CAA8C;AAC9C,wCAA4C;AAC5C,8CAAkD;AAClD,4CAAgD;AAChD,kDAA0C;AAE1C,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CACV,kEAAkE,CACnE;KACA,OAAO,CAAC,sBAAO,CAAC;KAChB,MAAM,CAAC,qBAAqB,EAAE,qBAAqB,CAAC;KACpD,MAAM,CACL,0BAA0B,EAC1B,6EAA6E,CAC9E,CAAC;AAEJ,OAAO,CAAC,UAAU,CAAC,IAAA,kBAAW,GAAE,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,IAAA,kBAAW,GAAE,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,IAAA,gBAAU,GAAE,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,IAAA,sBAAa,GAAE,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,IAAA,oBAAY,GAAE,CAAC,CAAC;AAEnC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,0CAA8C;AAC9C,0CAA8C;AAC9C,wCAA4C;AAC5C,0CAA8C;AAC9C,8CAAkD;AAClD,4CAAgD;AAChD,kDAA0C;AAE1C,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CACV,kEAAkE,CACnE;KACA,OAAO,CAAC,sBAAO,CAAC;KAChB,MAAM,CAAC,qBAAqB,EAAE,qBAAqB,CAAC;KACpD,MAAM,CACL,0BAA0B,EAC1B,6EAA6E,CAC9E,CAAC;AAEJ,OAAO,CAAC,UAAU,CAAC,IAAA,kBAAW,GAAE,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,IAAA,kBAAW,GAAE,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,IAAA,kBAAW,GAAE,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,IAAA,gBAAU,GAAE,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,IAAA,sBAAa,GAAE,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,IAAA,oBAAY,GAAE,CAAC,CAAC;AAEnC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAepC,wBAAgB,WAAW,IAAI,OAAO,CAyErC"}
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAepC,wBAAgB,WAAW,IAAI,OAAO,CAkFrC"}
@@ -60,6 +60,13 @@ function diffCommand() {
60
60
  for (const entry of config.files) {
61
61
  try {
62
62
  const result = await (0, sources_1.fetchSource)(entry, workingDir, vars);
63
+ for (const rec of result.sourceRecords) {
64
+ if (!rec.matched) {
65
+ console.error(`⚠ SHA mismatch for ${rec.sourceLabel}\n` +
66
+ ` expected: ${rec.expectedSha}\n` +
67
+ ` got: ${rec.observedSha}`);
68
+ }
69
+ }
63
70
  for (const [relPath, rawContent] of result.files) {
64
71
  let content = rawContent;
65
72
  if (entry.replace?.length)
@@ -1 +1 @@
1
- {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function lockCommand(): Command;
3
+ //# sourceMappingURL=lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../src/commands/lock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,WAAW,IAAI,OAAO,CAkFrC"}
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.lockCommand = void 0;
27
+ const commander_1 = require("commander");
28
+ const path = __importStar(require("path"));
29
+ const config_1 = require("../config");
30
+ const sources_1 = require("../sources");
31
+ const config_writeback_1 = require("../config-writeback");
32
+ function lockCommand() {
33
+ return new commander_1.Command('lock')
34
+ .description('Compute and pin SHA values for all remote sources in the config')
35
+ .option('--force', 'overwrite existing SHA values')
36
+ .action(async (options, cmd) => {
37
+ const opts = options;
38
+ const configPath = (0, config_1.resolveConfigPath)(cmd.parent?.opts().config);
39
+ const rawWorkingDir = cmd.parent?.opts().workingDir;
40
+ const workingDir = rawWorkingDir
41
+ ? path.resolve(rawWorkingDir)
42
+ : process.cwd();
43
+ if ((0, config_1.isRemoteConfigSpec)(configPath)) {
44
+ console.error('avanti lock requires a local config file.');
45
+ process.exit(2);
46
+ }
47
+ let config;
48
+ try {
49
+ config = await (0, config_1.loadConfig)(configPath);
50
+ }
51
+ catch (err) {
52
+ console.error(err.message);
53
+ process.exit(2);
54
+ }
55
+ const vars = config.variables ?? {};
56
+ const toPin = new Map(); // label → sha
57
+ let hasError = false;
58
+ let remoteSourceCount = 0;
59
+ for (const entry of config.files) {
60
+ try {
61
+ const result = await (0, sources_1.fetchSource)(entry, workingDir, vars);
62
+ remoteSourceCount += result.sourceRecords.length;
63
+ for (const rec of result.sourceRecords) {
64
+ if (!opts.force && rec.expectedSha !== undefined)
65
+ continue;
66
+ toPin.set(rec.sourceLabel, rec.observedSha);
67
+ }
68
+ }
69
+ catch (err) {
70
+ console.error(`Error processing ${JSON.stringify(entry.src)}: ${err.message}`);
71
+ hasError = true;
72
+ }
73
+ }
74
+ if (toPin.size === 0) {
75
+ if (hasError)
76
+ process.exit(2);
77
+ if (remoteSourceCount === 0) {
78
+ console.log('No SHA-pinnable remote sources found in config.');
79
+ }
80
+ else {
81
+ console.log('All remote sources already have SHA values pinned. Use --force to overwrite.');
82
+ }
83
+ process.exit(0);
84
+ }
85
+ if (hasError) {
86
+ console.error('Aborting: one or more sources failed to fetch. No changes written.');
87
+ process.exit(2);
88
+ }
89
+ const pinned = (0, config_writeback_1.writeUpdatedShas)(configPath, toPin);
90
+ if (pinned) {
91
+ for (const [label, sha] of toPin) {
92
+ console.log(` pinned ${label} ${sha.slice(0, 16)}`);
93
+ }
94
+ console.log(`\nPinned ${toPin.size} source(s).`);
95
+ }
96
+ else {
97
+ console.log('All SHA values are already up to date.');
98
+ }
99
+ process.exit(0);
100
+ });
101
+ }
102
+ exports.lockCommand = lockCommand;
103
+ //# sourceMappingURL=lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.js","sourceRoot":"","sources":["../../src/commands/lock.ts"],"names":[],"mappings":"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"}
@@ -62,6 +62,18 @@ function showPullHistory(history) {
62
62
  for (const ref of pull.files) {
63
63
  const label = ref.wasNew ? '(new file)' : '(modified)';
64
64
  console.log(` ${ref.absolutePath} → v${ref.version} ${label}`);
65
+ if (ref.sources && ref.sources.length > 0) {
66
+ for (const s of ref.sources) {
67
+ const shaShort = s.observedSha.slice(0, 16);
68
+ if (s.accepted && s.expectedSha) {
69
+ const prevShort = s.expectedSha.slice(0, 16);
70
+ console.log(` ${s.label} sha:${shaShort} ⚠ accepted (was: ${prevShort})`);
71
+ }
72
+ else {
73
+ console.log(` ${s.label} sha:${shaShort}`);
74
+ }
75
+ }
76
+ }
65
77
  }
66
78
  console.log('');
67
79
  }
@@ -76,6 +88,8 @@ function showFileHistory(history, filePath, workingDir) {
76
88
  return;
77
89
  }
78
90
  console.log(`${absolutePath}\n`);
91
+ const pulls = history.listPulls();
92
+ const pullsById = new Map(pulls.map((p) => [p.pullId, p]));
79
93
  const versions = [...fileHistory.versions].reverse();
80
94
  for (const v of versions) {
81
95
  const vLabel = `v${v.version}`;
@@ -89,6 +103,22 @@ function showFileHistory(history, filePath, workingDir) {
89
103
  if (v.isOriginal)
90
104
  suffix = ' (original, before avanti)';
91
105
  console.log(` ${vLabel.padEnd(4)} ${ts} ${pullRef}${suffix}`);
106
+ if (v.pullId) {
107
+ const pullEntry = pullsById.get(v.pullId);
108
+ const fileRef = pullEntry?.files.find((f) => f.absolutePath === absolutePath && f.version === v.version);
109
+ if (fileRef?.sources && fileRef.sources.length > 0) {
110
+ for (const s of fileRef.sources) {
111
+ const shaShort = s.observedSha.slice(0, 16);
112
+ if (s.accepted && s.expectedSha) {
113
+ const prevShort = s.expectedSha.slice(0, 16);
114
+ console.log(` ${s.label} sha:${shaShort} ⚠ accepted (was: ${prevShort})`);
115
+ }
116
+ else {
117
+ console.log(` ${s.label} sha:${shaShort}`);
118
+ }
119
+ }
120
+ }
121
+ }
92
122
  }
93
123
  }
94
124
  function formatTimestamp(iso) {
@@ -1 +1 @@
1
- {"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/commands/log.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/commands/log.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA8DpC,wBAAgB,WAAW,IAAI,OAAO,CAoKrC"}
1
+ {"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmGpC,wBAAgB,WAAW,IAAI,OAAO,CAoSrC"}
@@ -34,14 +34,28 @@ const diff_1 = require("../diff");
34
34
  const writer_1 = require("../writer");
35
35
  const history_1 = require("../history");
36
36
  const prompt_1 = require("../prompt");
37
+ const config_writeback_1 = require("../config-writeback");
37
38
  async function runFetchLoop(config, workingDir) {
38
39
  const vars = config.variables ?? {};
39
40
  const writeTargets = [];
40
41
  const allDiffs = [];
42
+ const shaErrors = [];
43
+ const seenShaErrorLabels = new Set();
44
+ const sourceRecordsByTarget = new Map();
41
45
  let hasError = false;
42
46
  for (const entry of config.files) {
43
47
  try {
44
48
  const result = await (0, sources_1.fetchSource)(entry, workingDir, vars);
49
+ for (const rec of result.sourceRecords) {
50
+ if (!rec.matched && !seenShaErrorLabels.has(rec.sourceLabel)) {
51
+ seenShaErrorLabels.add(rec.sourceLabel);
52
+ shaErrors.push({
53
+ sourceLabel: rec.sourceLabel,
54
+ expectedSha: rec.expectedSha,
55
+ observedSha: rec.observedSha,
56
+ });
57
+ }
58
+ }
45
59
  for (const [relPath, rawContent] of result.files) {
46
60
  let content = rawContent;
47
61
  if (entry.replace?.length)
@@ -51,6 +65,9 @@ async function runFetchLoop(config, workingDir) {
51
65
  const targetPath = (0, diff_1.resolveTargetPath)(entry, relPath, workingDir, vars);
52
66
  allDiffs.push((0, diff_1.computeDiff)(targetPath, content));
53
67
  writeTargets.push({ targetPath, content, mode: entry.mode });
68
+ if (result.sourceRecords.length > 0) {
69
+ sourceRecordsByTarget.set(targetPath, result.sourceRecords);
70
+ }
54
71
  }
55
72
  }
56
73
  catch (err) {
@@ -58,13 +75,22 @@ async function runFetchLoop(config, workingDir) {
58
75
  hasError = true;
59
76
  }
60
77
  }
61
- return { writeTargets, allDiffs, hasError };
78
+ return { writeTargets, allDiffs, hasError, shaErrors, sourceRecordsByTarget };
79
+ }
80
+ function printShaErrors(errors) {
81
+ for (const e of errors) {
82
+ console.error(`SHA mismatch for ${e.sourceLabel}\n` +
83
+ ` expected: ${e.expectedSha}\n` +
84
+ ` got: ${e.observedSha}`);
85
+ }
62
86
  }
63
87
  function pullCommand() {
64
88
  return new commander_1.Command('pull')
65
89
  .description('Pull remote sources and write to local files')
66
90
  .option('-y, --yes', 'skip confirmation prompt')
91
+ .option('--accept-changes', 'accept SHA mismatches, update SHA values in config, and apply changes')
67
92
  .action(async (options, cmd) => {
93
+ const opts = options;
68
94
  const configPath = (0, config_1.resolveConfigPath)(cmd.parent?.opts().config);
69
95
  const rawWorkingDir = cmd.parent?.opts().workingDir;
70
96
  const workingDir = rawWorkingDir
@@ -82,11 +108,17 @@ function pullCommand() {
82
108
  const historyAvailable = history.ensureStorageDir();
83
109
  const pullId = historyAvailable ? history.openPullSession() : null;
84
110
  const firstPass = await runFetchLoop(config, workingDir);
85
- let { writeTargets, allDiffs } = firstPass;
111
+ let { writeTargets, allDiffs, sourceRecordsByTarget } = firstPass;
86
112
  if (firstPass.hasError) {
87
113
  console.error('Aborting due to errors.');
88
114
  process.exit(2);
89
115
  }
116
+ // SHA validation — abort unless --accept-changes
117
+ if (firstPass.shaErrors.length > 0 && !opts.acceptChanges) {
118
+ printShaErrors(firstPass.shaErrors);
119
+ console.error('\nRun `avanti pull --accept-changes` to review the diff and update SHA values.');
120
+ process.exit(2);
121
+ }
90
122
  // Detect self-config update: only applies to local config files
91
123
  if (!(0, config_1.isRemoteConfigSpec)(configPath)) {
92
124
  const configIdx = writeTargets.findIndex((t) => t.targetPath === configPath);
@@ -100,16 +132,28 @@ function pullCommand() {
100
132
  console.error('Aborting due to errors in re-evaluated config.');
101
133
  process.exit(2);
102
134
  }
103
- // Ensure the config file write is present in the final targets.
104
- // The new config may or may not reference itself; either way we
105
- // must write the updated config that was fetched in the first pass.
135
+ if (second.shaErrors.length > 0 && !opts.acceptChanges) {
136
+ printShaErrors(second.shaErrors);
137
+ console.error('\nRun `avanti pull --accept-changes` to review the diff and update SHA values.');
138
+ process.exit(2);
139
+ }
106
140
  const configInSecond = second.writeTargets.findIndex((t) => t.targetPath === configPath);
107
141
  if (configInSecond === -1) {
108
142
  second.writeTargets.push(writeTargets[configIdx]);
109
143
  second.allDiffs.push(allDiffs[configIdx]);
144
+ const firstPassRecords = sourceRecordsByTarget.get(configPath);
145
+ if (firstPassRecords) {
146
+ second.sourceRecordsByTarget.set(configPath, firstPassRecords);
147
+ }
110
148
  }
111
149
  writeTargets = second.writeTargets;
112
150
  allDiffs = second.allDiffs;
151
+ sourceRecordsByTarget = second.sourceRecordsByTarget;
152
+ const existingLabels = new Set(firstPass.shaErrors.map((e) => e.sourceLabel));
153
+ for (const e of second.shaErrors) {
154
+ if (!existingLabels.has(e.sourceLabel))
155
+ firstPass.shaErrors.push(e);
156
+ }
113
157
  }
114
158
  catch (err) {
115
159
  console.warn(`Warning: updated config is invalid, skipping re-evaluation: ${err.message}`);
@@ -148,26 +192,81 @@ function pullCommand() {
148
192
  const hasChanges = allDiffs.some((d) => d.hasChanges) ||
149
193
  staleDiffs.some((d) => d.hasChanges);
150
194
  (0, diff_1.printDiffs)([...allDiffs, ...staleDiffs]);
151
- if (!hasChanges) {
195
+ // Show SHA mismatch summary when using --accept-changes
196
+ if (opts.acceptChanges && firstPass.shaErrors.length > 0) {
197
+ console.error('');
198
+ printShaErrors(firstPass.shaErrors);
199
+ }
200
+ if (!hasChanges && firstPass.shaErrors.length === 0) {
152
201
  console.log('Nothing to do.');
153
202
  process.exit(0);
154
203
  }
155
- const yes = options.yes ?? false;
204
+ const yes = opts.yes ?? false;
156
205
  if (!yes) {
157
- const ok = await (0, prompt_1.confirm)('Apply changes? [y/N] ');
206
+ const promptMsg = opts.acceptChanges && firstPass.shaErrors.length > 0
207
+ ? 'Accept new SHA values and apply changes? [y/N] '
208
+ : 'Apply changes? [y/N] ';
209
+ const ok = await (0, prompt_1.confirm)(promptMsg);
158
210
  if (!ok) {
159
211
  console.log('Aborted.');
160
212
  process.exit(0);
161
213
  }
162
214
  }
215
+ // Warn when --accept-changes is used with a remote config: SHA values
216
+ // cannot be written back, so the mismatch will recur on the next pull.
217
+ if (opts.acceptChanges &&
218
+ firstPass.shaErrors.length > 0 &&
219
+ (0, config_1.isRemoteConfigSpec)(configPath)) {
220
+ console.warn('Warning: config is remote; SHA values cannot be written back. ' +
221
+ 'Mismatches accepted for this session only.');
222
+ }
223
+ // Pre-apply SHA updates to the config write target in-memory so that both
224
+ // history and the on-disk file reflect the final pinned state in one pass.
225
+ const shaUpdates = opts.acceptChanges &&
226
+ firstPass.shaErrors.length > 0 &&
227
+ !(0, config_1.isRemoteConfigSpec)(configPath)
228
+ ? new Map(firstPass.shaErrors.map((e) => [e.sourceLabel, e.observedSha]))
229
+ : null;
230
+ let configShaPreApplied = false;
231
+ if (shaUpdates !== null) {
232
+ const configTargetIdx = writeTargets.findIndex((t) => t.targetPath === configPath);
233
+ if (configTargetIdx !== -1) {
234
+ const patched = (0, config_writeback_1.applyUpdatedShas)(writeTargets[configTargetIdx].content, shaUpdates);
235
+ if (patched !== null) {
236
+ writeTargets[configTargetIdx] = {
237
+ ...writeTargets[configTargetIdx],
238
+ content: patched,
239
+ };
240
+ // Recompute diff so staging and atomicWrite both see SHA-patched content,
241
+ // even when the original content diff was empty.
242
+ allDiffs[configTargetIdx] = (0, diff_1.computeDiff)(writeTargets[configTargetIdx].targetPath, patched);
243
+ configShaPreApplied = true;
244
+ }
245
+ }
246
+ }
163
247
  // Stage history versions before atomicWrite so v0 is captured before overwrite
164
248
  const stagedFileRefs = [];
165
249
  if (pullId) {
250
+ const acceptedShaLabels = new Set(firstPass.shaErrors.map((e) => e.sourceLabel));
166
251
  for (let i = 0; i < writeTargets.length; i++) {
167
- if (!allDiffs[i].hasChanges)
252
+ const targetPath = writeTargets[i].targetPath;
253
+ const records = sourceRecordsByTarget.get(targetPath);
254
+ const hasAcceptedSha = opts.acceptChanges &&
255
+ records?.some((r) => !r.matched && acceptedShaLabels.has(r.sourceLabel));
256
+ if (!allDiffs[i].hasChanges && !hasAcceptedSha)
168
257
  continue;
169
258
  try {
170
- const { fileRef } = history.stageFileVersion(pullId, writeTargets[i].targetPath, writeTargets[i].content, allDiffs[i].isNew);
259
+ const sourceShaRecords = records !== undefined
260
+ ? records.map((r) => ({
261
+ label: r.sourceLabel,
262
+ observedSha: r.observedSha,
263
+ expectedSha: r.expectedSha,
264
+ accepted: !r.matched &&
265
+ (opts.acceptChanges ?? false) &&
266
+ acceptedShaLabels.has(r.sourceLabel),
267
+ }))
268
+ : undefined;
269
+ const { fileRef } = history.stageFileVersion(pullId, targetPath, writeTargets[i].content, allDiffs[i].isNew, sourceShaRecords);
171
270
  stagedFileRefs.push(fileRef);
172
271
  }
173
272
  catch {
@@ -176,17 +275,29 @@ function pullCommand() {
176
275
  }
177
276
  }
178
277
  try {
179
- (0, writer_1.atomicWrite)([...writeTargets, ...staleToRestore], staleToDelete);
180
- const written = writeTargets.filter((_, i) => allDiffs[i].hasChanges).length +
181
- staleToRestore.length +
182
- staleToDelete.length;
278
+ const changedTargets = writeTargets.filter((_, i) => allDiffs[i].hasChanges);
279
+ (0, writer_1.atomicWrite)([...changedTargets, ...staleToRestore], staleToDelete);
280
+ const written = changedTargets.length + staleToRestore.length + staleToDelete.length;
183
281
  console.log(`Wrote ${written} file(s).`);
184
282
  }
185
283
  catch (err) {
186
284
  console.error(`Write failed: ${err.message}`);
187
285
  process.exit(2);
188
286
  }
189
- // Only record to pulls.jsonl if at least one file was actually written
287
+ // SHA writeback: write updated sha values into config file after all writes complete.
288
+ // Skipped when config was a write target and already patched in-memory above.
289
+ if (shaUpdates !== null && !configShaPreApplied) {
290
+ try {
291
+ const pinned = (0, config_writeback_1.writeUpdatedShas)(configPath, shaUpdates);
292
+ if (pinned)
293
+ console.log(`Updated ${shaUpdates.size} SHA pin(s) in config.`);
294
+ }
295
+ catch (err) {
296
+ console.warn(`Warning: could not update SHA values in config: ${err.message}`);
297
+ }
298
+ }
299
+ // Only record to pulls.jsonl if at least one file was staged (written or
300
+ // SHA-accepted via --accept-changes with no content diff)
190
301
  if (pullId && stagedFileRefs.length > 0) {
191
302
  try {
192
303
  history.closePullSession(pullId, (0, config_1.normalizeConfigKey)(configPath), stagedFileRefs);