phewsh 0.15.62 → 0.15.63

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.
@@ -554,6 +554,8 @@ async function main() {
554
554
  const parts = [cream('HEAD ' + v.shortHead)];
555
555
  parts.push(v.dirtyCount ? peach(`${v.dirtyCount} uncommitted`) : sage('clean'));
556
556
  if (v.driftCommits > 0) parts.push(ember(`⚠ ${v.driftCommits} commit${v.driftCommits !== 1 ? 's' : ''} since .intent updated`));
557
+ // Sharper than recency: the docs still name an older version than shipped.
558
+ if (v.versionDrift) parts.push(ember(`⚠ .intent says ${v.versionDrift.claimed}, shipped ${v.versionDrift.shipped} — /reconcile`));
557
559
  row('VERIFIED', parts.join(slate(' · ')) + slate(' — /truth · /brief'));
558
560
  }
559
561
  } catch { /* the verified row is a glance, never a blocker */ }
package/lib/truth.js CHANGED
@@ -273,16 +273,50 @@ async function fetchNpmLatest(packageName, { fetchImpl = global.fetch, timeoutMs
273
273
  // Fast, offline, fail-soft snapshot for the front-door cockpit — no npm fetch,
274
274
  // no file hashing. Answers "what verified truth is loaded?" at a glance so the
275
275
  // product thesis (one verified truth) is visible the moment phewsh opens.
276
+ // Cheap, offline version-claim drift: does the shipped package version sit ahead
277
+ // of the newest version the .intent narrative still claims? This is the SHARP
278
+ // staleness signal the front door was missing — the recency-based "commits since
279
+ // .intent changed" check goes quiet the moment you edit status.md, even if its
280
+ // headline claim is stale. We compare the project's package version (repo root,
281
+ // or a cli/ monorepo child like phewsh itself) to the max version mentioned in
282
+ // status.md/next.md, and only flag when code has shipped PAST the docs.
283
+ function quickVersionDrift(cwd = process.cwd()) {
284
+ try {
285
+ let shipped = null;
286
+ for (const rel of ['package.json', 'cli/package.json']) {
287
+ const p = path.join(cwd, rel);
288
+ if (!fs.existsSync(p)) continue;
289
+ try { shipped = JSON.parse(fs.readFileSync(p, 'utf-8')).version; } catch { /* unreadable */ }
290
+ if (shipped) break;
291
+ }
292
+ if (!shipped) return null;
293
+ let claimed = null;
294
+ for (const rel of ['.intent/status.md', '.intent/next.md']) {
295
+ const p = path.join(cwd, rel);
296
+ if (!fs.existsSync(p)) continue;
297
+ for (const m of fs.readFileSync(p, 'utf-8').matchAll(/\bv?(\d+\.\d+\.\d+)\b/g)) {
298
+ if (!claimed || compareVersions(m[1], claimed) > 0) claimed = m[1];
299
+ }
300
+ }
301
+ if (!claimed) return null;
302
+ return compareVersions(shipped, claimed) > 0 ? { shipped, claimed } : null;
303
+ } catch {
304
+ return null;
305
+ }
306
+ }
307
+
276
308
  function quickVerifiedState(cwd = process.cwd()) {
277
309
  try {
278
310
  const git = gitSnapshot(cwd);
279
- if (!git.available) return { available: false, isRepo: false };
311
+ const versionDrift = quickVersionDrift(cwd);
312
+ if (!git.available) return { available: false, isRepo: false, versionDrift };
280
313
  return {
281
314
  available: true,
282
315
  isRepo: true,
283
316
  shortHead: git.shortHead,
284
317
  dirtyCount: git.tracked.length + git.untracked.length,
285
318
  driftCommits: git.drift?.tracked ? git.drift.commitsSince : 0,
319
+ versionDrift,
286
320
  };
287
321
  } catch {
288
322
  return { available: false, isRepo: false };
@@ -397,5 +431,6 @@ module.exports = {
397
431
  parsePorcelain,
398
432
  projectionInfo,
399
433
  quickVerifiedState,
434
+ quickVersionDrift,
400
435
  statusDrift,
401
436
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "phewsh",
3
- "version": "0.15.62",
3
+ "version": "0.15.63",
4
4
  "description": "Turn intent into action. Structure your thinking, execute your next step.",
5
5
  "bin": {
6
6
  "phewsh": "bin/phewsh.js"