mirror-mind 0.33.1 → 0.33.2
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/docs/releases/index.md +1 -0
- package/docs/releases/v0.33.2.md +124 -0
- package/package.json +1 -1
- package/plugins/mirror-mind/.claude-plugin/plugin.json +1 -1
- package/ts/src/frontDoor/runtimeRoute.ts +44 -27
- package/ts/src/runtime/channel.ts +18 -0
- package/ts/src/runtime/git.ts +46 -7
- package/ts/src/runtime/installKind.ts +15 -0
- package/ts/src/runtime/status.ts +24 -29
package/docs/releases/index.md
CHANGED
|
@@ -12,6 +12,7 @@ Future release notes should use the structure defined in [Release Notes](../proc
|
|
|
12
12
|
|
|
13
13
|
## Releases
|
|
14
14
|
|
|
15
|
+
- [v0.33.2 — Git Runs Where Mirror Lives](v0.33.2.md) — patch release of one Change Request, CR138: on a clone install, `runtime status`, `version`, and `diagnose` describe the install from any directory, and `diagnose` grades Mirror's own tree. Git now runs only in the install's own checkout, so a checkout someone else made can no longer run a `core.fsmonitor` command through these commands; `version --start PATH` is the one explicit exception. Package installs were never exposed. No migration.
|
|
15
16
|
- [v0.33.1 — The Install Answers For Itself](v0.33.1.md) — patch release of six RS010 Change Requests: the welcome card, the status line, and both `release-notes` readers answer for the install that is running, never for the cwd or the repository around the install. A package asks its own tree and the npm registry, a clone its own checkout and remote; `pending` says `unknown` when it cannot tell, and a `--ref` value can no longer run a command through git. No migration.
|
|
16
17
|
- [v0.33.0 — One Plugin, Three Runtimes](v0.33.0.md) — minor release closing CV21.DS2: the one plugin works as it is on Claude Code, Codex, and Grok. Its MCP server starts on all three, the explicit Mirror form is recognized in every runtime's spelling, and each session is logged under its runtime with every reply beside its prompt. Also: a faster Pi session start, and notice that Gemini CLI is retired in favor of Antigravity.
|
|
17
18
|
- [v0.32.1 — The Release That Shipped](v0.32.1.md) — patch release that is the published CV22 release: `v0.32.0` was tagged and its publication refused by the retired-surface tripwire over one sentence in Getting Started, now rephrased. No code, behavior, or schema differs from `v0.32.0`; read that note for the release itself.
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
digest: >
|
|
3
|
+
v0.33.2 is a maintenance release of one Change Request, CR138, which closes
|
|
4
|
+
the family v0.33.1 began. For a clone install, `runtime status`, `version`,
|
|
5
|
+
and `diagnose` described the repository the person was standing in, not the
|
|
6
|
+
install: a healthy clone read `attention needed` outside its checkout, and
|
|
7
|
+
`diagnose` reported another project's uncommitted files as Mirror drift.
|
|
8
|
+
Because git reads a repository's own config, running these commands inside a
|
|
9
|
+
checkout someone else made could also run a command that checkout chose. Git
|
|
10
|
+
now runs only in the install's own checkout, and `version --start PATH` is
|
|
11
|
+
the one explicit exception. Package installs, the default, were never
|
|
12
|
+
exposed. Upgrade with `mirror runtime update`; there is no migration.
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# v0.33.2 — Git Runs Where Mirror Lives
|
|
16
|
+
|
|
17
|
+
**Date:** 2026-10-15
|
|
18
|
+
|
|
19
|
+
## Highlights
|
|
20
|
+
|
|
21
|
+
- **On a clone install, `runtime status`, `version`, and `diagnose` describe the install
|
|
22
|
+
from any directory** (CR138). A healthy clone is `ready` everywhere. The channel row is
|
|
23
|
+
what `runtime channel` reports, and the clone role is the checkout's own.
|
|
24
|
+
- **`diagnose` grades Mirror's own tree.** Run inside another project, it reported that
|
|
25
|
+
project's uncommitted files as Mirror drift and advised committing, stashing, or
|
|
26
|
+
discarding them. It no longer looks there.
|
|
27
|
+
- **A checkout you did not make can no longer run a command through these commands.**
|
|
28
|
+
Git reads a repository's `.git/config`, where `core.fsmonitor` names a command git runs
|
|
29
|
+
on `status`. Run inside such a checkout, `runtime status`, `version`, and `diagnose` ran
|
|
30
|
+
it. They now run git only in the install's own checkout. `version --start PATH` is the
|
|
31
|
+
one documented way to inspect another repository.
|
|
32
|
+
- **Package installs were never exposed.** A package inspects no repository; its
|
|
33
|
+
clone-role row now reads `none (package install)`.
|
|
34
|
+
- **An install that cannot be identified inspects no repository**, and says why;
|
|
35
|
+
`update --check` answers `unknown` with the reason.
|
|
36
|
+
|
|
37
|
+
## Where We Started
|
|
38
|
+
|
|
39
|
+
`v0.33.1` made the welcome card, the status line, and both release-notes readers answer
|
|
40
|
+
for the install instead of the cwd. CR138, captured during that work, named the same
|
|
41
|
+
defect in `runtime status` and `runtime version` for a clone: both named the install on
|
|
42
|
+
their first line, then reported the repository, git state, and channel of whatever
|
|
43
|
+
directory they were run in. REFERENCE.md's recommended update flow begins with `runtime
|
|
44
|
+
status`, so a clone user who ran it from a project was told `attention needed` about a
|
|
45
|
+
healthy install.
|
|
46
|
+
|
|
47
|
+
Selection found more than the capture said. The clone-role row read the cwd too.
|
|
48
|
+
`runtime diagnose` built the same report, so from inside another project it listed that
|
|
49
|
+
project's uncommitted files as Mirror's and recommended discarding work in a repository
|
|
50
|
+
that was not Mirror's. The plan's review then measured the third face. Git runs a
|
|
51
|
+
repository's own `core.fsmonitor` command on `status`, so these commands, run inside a
|
|
52
|
+
checkout someone else made, ran what that checkout chose. No skill runs these commands,
|
|
53
|
+
so it took a person running them there. The exposure was clone installs, and installs
|
|
54
|
+
that cannot be identified; a package never inspected a repository.
|
|
55
|
+
|
|
56
|
+
## What Changed
|
|
57
|
+
|
|
58
|
+
**One rule says where the repository rows come from.** `inspectionRootFor(install,
|
|
59
|
+
start)`: `--start` when given, else a clone's own checkout, else nowhere. The report
|
|
60
|
+
builder and `runtime version` both use it. The builder no longer defaults to the cwd, and
|
|
61
|
+
`status`, `diagnose`, and the update gate pass none.
|
|
62
|
+
|
|
63
|
+
**The rows are the install's.** The channel row is the answer `runtime channel` gives,
|
|
64
|
+
and the clone role is the checkout's marker. `diagnose`'s worktree findings come from the
|
|
65
|
+
install's tree, so a dirty Mirror checkout is still reported and another project's work
|
|
66
|
+
never is.
|
|
67
|
+
|
|
68
|
+
**`--start` is the one explicit exception.** `runtime version --start PATH` keeps its
|
|
69
|
+
documented meaning, to inspect the repository at PATH, and is now named as the one way
|
|
70
|
+
these commands run git in a repository the install does not own.
|
|
71
|
+
|
|
72
|
+
**An install that cannot be identified asks nothing.** Its git rows say `install kind
|
|
73
|
+
unknown: <reason>`, and its verdict is `attention needed`, which is true: `runtime
|
|
74
|
+
update` refuses such an install. `update --check` answers `unknown` with the same reason
|
|
75
|
+
instead of asking the cwd's git.
|
|
76
|
+
|
|
77
|
+
The tests run every command from a directory in no repository and from a hostile project:
|
|
78
|
+
uncommitted work, its own channel and role markers, and a `core.fsmonitor` that creates a
|
|
79
|
+
marker file. The answers are byte-identical, and the marker never appears, except through
|
|
80
|
+
`--start`, which asks for it. No golden changed.
|
|
81
|
+
|
|
82
|
+
### What you will notice
|
|
83
|
+
|
|
84
|
+
- On a clone, `runtime status` gives the same answer from any directory as from the
|
|
85
|
+
checkout, and `runtime version`'s `Update channel:` matches `runtime channel`.
|
|
86
|
+
- On a package, `Clone role: none (package install)`.
|
|
87
|
+
- `runtime diagnose` may still report `front_door_errors`. Every command that exits 1 to
|
|
88
|
+
report a verdict, `diagnose` included, is logged as an error and counted. That is
|
|
89
|
+
CR139, captured and not in this release.
|
|
90
|
+
|
|
91
|
+
## Upgrading
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
mirror runtime update # or: npm install -g mirror-mind
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
There is no database migration, and no runtime wiring changes. The update itself is run
|
|
98
|
+
by the version you have now; the fix applies from the first command after it.
|
|
99
|
+
|
|
100
|
+
## Conscious Exclusions
|
|
101
|
+
|
|
102
|
+
- **Counting verdicts as front-door errors** (CR139). `runtime status`'s `attention
|
|
103
|
+
needed`, `diagnose`'s findings, and `release-notes pending`'s `unknown` exit 1, and the
|
|
104
|
+
front door logs every non-zero exit as an error that `diagnose` counts. This release
|
|
105
|
+
removes the false verdicts that fed it, not the loop.
|
|
106
|
+
- **The `release` environment's ref check** (CR136).
|
|
107
|
+
- **Retiring `version --start`.** It was kept, as the explicit override it always was.
|
|
108
|
+
|
|
109
|
+
## What We Learned
|
|
110
|
+
|
|
111
|
+
In CR133 to CR135, "never the cwd" was a correctness rule: the person's project is not
|
|
112
|
+
Mirror, so it cannot answer Mirror's questions. CR138 showed it is also a trust boundary.
|
|
113
|
+
The cwd's repository configures the very git that inspects it, so a wrong answer and an
|
|
114
|
+
executed command had the same cause and the same fix, which is where a command decides to
|
|
115
|
+
look.
|
|
116
|
+
|
|
117
|
+
A test can pin a defect as faithfully as it pins a feature. One CLI test asserted, with a
|
|
118
|
+
comment saying so: "Git inspection still describes the cwd." It was right about the
|
|
119
|
+
oracle and wrong about the product, and it now pins the fix.
|
|
120
|
+
|
|
121
|
+
## Next Horizon
|
|
122
|
+
|
|
123
|
+
CR139, the verdict loop, is the visible next step in RS010. CR136 would harden the
|
|
124
|
+
publish route.
|
package/package.json
CHANGED
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
renderRuntimeBackupCreated,
|
|
22
22
|
verifyBackupArchive,
|
|
23
23
|
} from "#runtime/backup.ts";
|
|
24
|
-
import { channelFor, renderChannel, setChannel } from "#runtime/channel.ts";
|
|
24
|
+
import { channelFor, channelForReport, renderChannel, setChannel } from "#runtime/channel.ts";
|
|
25
25
|
import {
|
|
26
26
|
diagnoseRuntime,
|
|
27
27
|
hookFailureFindings,
|
|
@@ -33,16 +33,16 @@ import {
|
|
|
33
33
|
} from "#runtime/diagnose.ts";
|
|
34
34
|
import {
|
|
35
35
|
checkUpdateAvailability,
|
|
36
|
-
|
|
36
|
+
cloneRoleFor,
|
|
37
37
|
inspectGitFor,
|
|
38
38
|
inspectGitWorktree,
|
|
39
|
-
inspectUpdateChannel,
|
|
40
39
|
packageVersion,
|
|
41
40
|
renderRuntimeUpdateAvailability,
|
|
42
41
|
renderRuntimeVersion,
|
|
42
|
+
unavailableUpdateCheck,
|
|
43
43
|
upstreamFor,
|
|
44
44
|
} from "#runtime/git.ts";
|
|
45
|
-
import { detectInstallKind, type InstallKind } from "#runtime/installKind.ts";
|
|
45
|
+
import { detectInstallKind, type InstallKind, inspectionRootFor } from "#runtime/installKind.ts";
|
|
46
46
|
import { MIGRATE_DECLINED_EXIT, renderMigrate, runMigrate } from "#runtime/migrate.ts";
|
|
47
47
|
import {
|
|
48
48
|
buildPendingReleaseNotes,
|
|
@@ -156,6 +156,11 @@ function resolveWelcomeHome(explicit: string | null, env: NodeJS.ProcessEnv): st
|
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
export interface RuntimeRouteIo {
|
|
159
|
+
/**
|
|
160
|
+
* Where the command was run. No `runtime` read route consults it: since
|
|
161
|
+
* CR134 and CR138 they answer for the install, wherever they run. Tests pass
|
|
162
|
+
* it to show that it does not matter.
|
|
163
|
+
*/
|
|
159
164
|
cwd?: string;
|
|
160
165
|
env?: NodeJS.ProcessEnv;
|
|
161
166
|
stdout?: (text: string) => void;
|
|
@@ -244,7 +249,6 @@ export async function runRuntimeReadRoute(
|
|
|
244
249
|
io: InstallRouteIo = {},
|
|
245
250
|
): Promise<number> {
|
|
246
251
|
const env = io.env ?? process.env;
|
|
247
|
-
const cwd = io.cwd ?? process.cwd();
|
|
248
252
|
const args = argv.slice(1);
|
|
249
253
|
const subcommand = args[0] ?? "";
|
|
250
254
|
// The version is the running tree's, never the cwd's: for a skill the cwd
|
|
@@ -254,19 +258,24 @@ export async function runRuntimeReadRoute(
|
|
|
254
258
|
|
|
255
259
|
if (subcommand === "version") {
|
|
256
260
|
const startArg = optionValue(args, "--start");
|
|
257
|
-
const
|
|
258
|
-
|
|
261
|
+
const install = io.install ?? detectThisInstall();
|
|
262
|
+
// The install's own repository, or the one `--start` names: the one
|
|
263
|
+
// explicit way these commands run git outside the install (CR138).
|
|
264
|
+
const root = inspectionRootFor(install, startArg ? expandHome(startArg) : null);
|
|
259
265
|
writeOut(
|
|
260
266
|
io,
|
|
261
267
|
renderRuntimeVersion({
|
|
262
268
|
version,
|
|
263
269
|
install,
|
|
264
|
-
git: inspectGitFor(install,
|
|
265
|
-
cloneRole:
|
|
266
|
-
updateChannel:
|
|
267
|
-
install
|
|
268
|
-
|
|
269
|
-
|
|
270
|
+
git: inspectGitFor(install, root),
|
|
271
|
+
cloneRole: cloneRoleFor(install, root),
|
|
272
|
+
updateChannel: channelForReport(
|
|
273
|
+
install,
|
|
274
|
+
root,
|
|
275
|
+
env,
|
|
276
|
+
io.osHome ?? homedir(),
|
|
277
|
+
optionValue(args, "--channel"),
|
|
278
|
+
),
|
|
270
279
|
}),
|
|
271
280
|
);
|
|
272
281
|
return 0;
|
|
@@ -274,24 +283,24 @@ export async function runRuntimeReadRoute(
|
|
|
274
283
|
|
|
275
284
|
if (subcommand === "status") {
|
|
276
285
|
const report = buildRuntimeStatus({
|
|
277
|
-
start: cwd,
|
|
278
286
|
mirrorHome: optionValue(args, "--mirror-home"),
|
|
279
287
|
channel: optionValue(args, "--channel"),
|
|
280
288
|
env,
|
|
281
289
|
version,
|
|
282
|
-
install: detectThisInstall(),
|
|
290
|
+
install: io.install ?? detectThisInstall(),
|
|
283
291
|
});
|
|
284
292
|
writeOut(io, renderRuntimeStatus(report, env));
|
|
285
293
|
return statusVerdict(report) === "ready" ? 0 : 1;
|
|
286
294
|
}
|
|
287
295
|
|
|
288
296
|
if (subcommand === "diagnose") {
|
|
297
|
+
// The install's own tree, so its worktree findings are Mirror's and never
|
|
298
|
+
// the cwd project's (CR138).
|
|
289
299
|
const report = buildRuntimeStatus({
|
|
290
|
-
start: cwd,
|
|
291
300
|
mirrorHome: optionValue(args, "--mirror-home"),
|
|
292
301
|
env,
|
|
293
302
|
version,
|
|
294
|
-
install: detectThisInstall(),
|
|
303
|
+
install: io.install ?? detectThisInstall(),
|
|
295
304
|
});
|
|
296
305
|
const findings = [
|
|
297
306
|
...diagnoseRuntime(report, inspectGitWorktree(report.git.repository)),
|
|
@@ -340,7 +349,7 @@ export async function runRuntimeReadRoute(
|
|
|
340
349
|
|
|
341
350
|
if (subcommand === "backup") return runRuntimeBackup(args.slice(1), io, env);
|
|
342
351
|
if (subcommand === "migrate") return runRuntimeMigrate(args.slice(1), io, env);
|
|
343
|
-
if (subcommand === "update") return runRuntimeUpdate(args.slice(1), io, env
|
|
352
|
+
if (subcommand === "update") return runRuntimeUpdate(args.slice(1), io, env);
|
|
344
353
|
if (subcommand === "channel") return runRuntimeChannel(args.slice(1), io, env);
|
|
345
354
|
|
|
346
355
|
// Routing answers every name it does not recognize before dispatch (the
|
|
@@ -486,9 +495,8 @@ function runRuntimeChannel(
|
|
|
486
495
|
*/
|
|
487
496
|
function runRuntimeUpdate(
|
|
488
497
|
args: readonly string[],
|
|
489
|
-
io:
|
|
498
|
+
io: InstallRouteIo,
|
|
490
499
|
env: NodeJS.ProcessEnv,
|
|
491
|
-
cwd: string,
|
|
492
500
|
): number {
|
|
493
501
|
const version = packageVersion(runningTreeRoot()) ?? "unknown";
|
|
494
502
|
const channelOverride = optionValue(args, "--channel");
|
|
@@ -499,11 +507,16 @@ function runRuntimeUpdate(
|
|
|
499
507
|
// npm runs in the tree the front door runs from -- for a package, the
|
|
500
508
|
// install's own root -- and never in the cwd, whose `.npmrc` could name
|
|
501
509
|
// another registry or prefix (CR135). The strategy's own calls do the same.
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
const
|
|
510
|
+
//
|
|
511
|
+
// Git runs in the clone's own checkout and nowhere else: the gate's report
|
|
512
|
+
// and `--check` name no cwd (CR138), whose `.git/config` could name a
|
|
513
|
+
// command for git to run.
|
|
514
|
+
const install =
|
|
515
|
+
io.install ??
|
|
516
|
+
detectInstallKind({
|
|
517
|
+
frontDoorPath: frontDoorSelfPath(),
|
|
518
|
+
npmRootGlobal: npmRootGlobal(runningTreeRoot()),
|
|
519
|
+
});
|
|
507
520
|
const channel = channelFor(install, env, homedir(), channelOverride);
|
|
508
521
|
|
|
509
522
|
if (args.includes("--check")) {
|
|
@@ -517,7 +530,12 @@ function runRuntimeUpdate(
|
|
|
517
530
|
? 0
|
|
518
531
|
: 1;
|
|
519
532
|
}
|
|
520
|
-
|
|
533
|
+
// An install that cannot be identified has no checkout to ask, and the
|
|
534
|
+
// cwd is not one (CR138, decision 2). `runtime update` refuses it too.
|
|
535
|
+
const availability =
|
|
536
|
+
install.kind === "clone"
|
|
537
|
+
? checkUpdateAvailability(install.repository, channelOverride, version)
|
|
538
|
+
: unavailableUpdateCheck(version, channel, `install kind unknown: ${install.reason}`);
|
|
521
539
|
writeOut(io, renderRuntimeUpdateAvailability(availability));
|
|
522
540
|
return availability.status === "up_to_date" || availability.status === "update_available"
|
|
523
541
|
? 0
|
|
@@ -541,7 +559,6 @@ function runRuntimeUpdate(
|
|
|
541
559
|
|
|
542
560
|
const gate = (): { ready: boolean; allowed: boolean; detail: string } => {
|
|
543
561
|
const report = buildRuntimeStatus({
|
|
544
|
-
start,
|
|
545
562
|
mirrorHome,
|
|
546
563
|
channel: channelOverride,
|
|
547
564
|
env,
|
|
@@ -82,6 +82,24 @@ export function channelFor(
|
|
|
82
82
|
return { value: DEFAULT_CHANNEL, source: null, note: "install kind unknown" };
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
/**
|
|
86
|
+
* The channel row of `status` and `version` (CR138). A package's is its
|
|
87
|
+
* config file's. A clone's is the marker in the repository the rows come from
|
|
88
|
+
* (`inspectionRootFor`): its own checkout, or `version --start PATH`, the
|
|
89
|
+
* flag's documented meaning. With no root, the install's own answer, which for
|
|
90
|
+
* a clone without `--start` is the same marker, read the same way.
|
|
91
|
+
*/
|
|
92
|
+
export function channelForReport(
|
|
93
|
+
install: InstallKind,
|
|
94
|
+
root: string | null,
|
|
95
|
+
env: ConfigEnv = process.env,
|
|
96
|
+
home: string = homedir(),
|
|
97
|
+
override: string | null = null,
|
|
98
|
+
): MarkerValue {
|
|
99
|
+
if (install.kind === "package" || root === null) return channelFor(install, env, home, override);
|
|
100
|
+
return inspectUpdateChannel(root, override);
|
|
101
|
+
}
|
|
102
|
+
|
|
85
103
|
export type ChannelWrite =
|
|
86
104
|
| { ok: true; path: string; value: string; previous: string }
|
|
87
105
|
| { ok: false; reason: string; exitCode: 1 | 2 };
|
package/ts/src/runtime/git.ts
CHANGED
|
@@ -436,12 +436,52 @@ export const NO_REPOSITORY: GitStatus = {
|
|
|
436
436
|
};
|
|
437
437
|
|
|
438
438
|
/**
|
|
439
|
-
* The git facts of
|
|
440
|
-
*
|
|
441
|
-
*
|
|
439
|
+
* The git facts of the install's `root` (`inspectionRootFor`): a package's
|
|
440
|
+
* are `NO_REPOSITORY` (CV22.DS10.US3 plateau 4), since grading the cwd of a
|
|
441
|
+
* package install as a tree read "not a git repository" as a git error. With
|
|
442
|
+
* no root -- an install that cannot be identified, and no `--start` -- no
|
|
443
|
+
* repository is inspected at all, and the rows say why (CR138, decision 2).
|
|
442
444
|
*/
|
|
443
|
-
export function inspectGitFor(install: InstallKind,
|
|
444
|
-
|
|
445
|
+
export function inspectGitFor(install: InstallKind, root: string | null): GitStatus {
|
|
446
|
+
if (install.kind === "package") return NO_REPOSITORY;
|
|
447
|
+
if (root === null) {
|
|
448
|
+
const reason =
|
|
449
|
+
install.kind === "unknown" ? `install kind unknown: ${install.reason}` : "no repository";
|
|
450
|
+
return { ...NO_REPOSITORY, error: reason };
|
|
451
|
+
}
|
|
452
|
+
return inspectGit(root);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* The clone role the install's checkout declares (CR138). A package has none
|
|
457
|
+
* to declare. With no root, nothing is read, and the oracle's answer for no
|
|
458
|
+
* repository stands: the default, with the note that says why.
|
|
459
|
+
*/
|
|
460
|
+
export function cloneRoleFor(install: InstallKind, root: string | null): MarkerValue {
|
|
461
|
+
if (install.kind === "package") return { value: "none", source: null, note: "package install" };
|
|
462
|
+
if (root === null) return { value: DEFAULT_CLONE_ROLE, source: null, note: "no repository" };
|
|
463
|
+
return inspectCloneRole(root);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/** The clone-role rows of `status` and `version`, one renderer for both (CR138). */
|
|
467
|
+
export function renderCloneRoleLines(install: InstallKind, role: MarkerValue): string[] {
|
|
468
|
+
if (install.kind === "package") return ["Clone role: none (package install)"];
|
|
469
|
+
const lines = [`Clone role: ${role.value}`];
|
|
470
|
+
if (role.note) lines.push(`Clone role note: ${role.note}`);
|
|
471
|
+
return lines;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* `update --check` for an install whose repository is not asked: the same
|
|
476
|
+
* shape as the check's own `unknown`, with the reason (CR138). An install that
|
|
477
|
+
* cannot be identified has no checkout to ask, and the cwd is not one.
|
|
478
|
+
*/
|
|
479
|
+
export function unavailableUpdateCheck(
|
|
480
|
+
version: string,
|
|
481
|
+
updateChannel: MarkerValue,
|
|
482
|
+
note: string,
|
|
483
|
+
): UpdateAvailability {
|
|
484
|
+
return availability(version, updateChannel, { note });
|
|
445
485
|
}
|
|
446
486
|
|
|
447
487
|
/**
|
|
@@ -470,8 +510,7 @@ export function renderRuntimeVersion(report: RuntimeVersionReport): string {
|
|
|
470
510
|
lines.push(`Version: ${report.version}`);
|
|
471
511
|
lines.push(...renderInstallLines(report.install));
|
|
472
512
|
lines.push(...renderRepositoryLines(report.install, report.git, false));
|
|
473
|
-
lines.push(
|
|
474
|
-
if (report.cloneRole.note) lines.push(`Clone role note: ${report.cloneRole.note}`);
|
|
513
|
+
lines.push(...renderCloneRoleLines(report.install, report.cloneRole));
|
|
475
514
|
lines.push(`Update channel: ${report.updateChannel.value}`);
|
|
476
515
|
if (report.updateChannel.note) lines.push(`Update channel note: ${report.updateChannel.note}`);
|
|
477
516
|
return `${lines.join("\n")}\n`;
|
|
@@ -201,6 +201,21 @@ export function detectInstallKind(probe: InstallKindProbe): InstallKind {
|
|
|
201
201
|
};
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
+
/**
|
|
205
|
+
* Where the repository rows of `status`, `version`, and `diagnose` come from
|
|
206
|
+
* (CR138): `start` when one is given -- `version --start PATH`, or a test --
|
|
207
|
+
* else a clone's own checkout, else nowhere. Never the cwd. For a skill the
|
|
208
|
+
* cwd is the person's project, and git run there reads that project's config,
|
|
209
|
+
* where `core.fsmonitor` names a command git runs on `status`.
|
|
210
|
+
*/
|
|
211
|
+
export function inspectionRootFor(
|
|
212
|
+
install: InstallKind,
|
|
213
|
+
start: string | null | undefined,
|
|
214
|
+
): string | null {
|
|
215
|
+
if (start !== null && start !== undefined) return resolve(start);
|
|
216
|
+
return install.kind === "clone" ? install.repository : null;
|
|
217
|
+
}
|
|
218
|
+
|
|
204
219
|
/** One line for a render or a log entry. */
|
|
205
220
|
export function describeInstallKind(install: InstallKind): string {
|
|
206
221
|
if (install.kind === "clone") return `clone (${install.repository})`;
|
package/ts/src/runtime/status.ts
CHANGED
|
@@ -26,16 +26,21 @@ import { inspectMigrationFiles } from "#extensions/migrations.ts";
|
|
|
26
26
|
import { type DbPathEnv, dbNameForEnv, resolveMirrorHome } from "#frontDoor/dbPath.ts";
|
|
27
27
|
import { DEFAULT_EMBEDDING_MODEL, DEFAULT_EXTRACTION_MODEL } from "#providers/config.ts";
|
|
28
28
|
import { sortByCodePoint } from "#util/pythonText.ts";
|
|
29
|
-
import {
|
|
29
|
+
import { channelForReport } from "./channel.ts";
|
|
30
30
|
import type { MarkerValue } from "./git.ts";
|
|
31
31
|
import {
|
|
32
|
+
cloneRoleFor,
|
|
32
33
|
type GitStatus,
|
|
33
|
-
inspectCloneRole,
|
|
34
34
|
inspectGitFor,
|
|
35
|
-
|
|
35
|
+
renderCloneRoleLines,
|
|
36
36
|
renderRepositoryLines,
|
|
37
37
|
} from "./git.ts";
|
|
38
|
-
import {
|
|
38
|
+
import {
|
|
39
|
+
detectInstallKind,
|
|
40
|
+
type InstallKind,
|
|
41
|
+
inspectionRootFor,
|
|
42
|
+
renderInstallLines,
|
|
43
|
+
} from "./installKind.ts";
|
|
39
44
|
|
|
40
45
|
export interface CoreMigrationHealth {
|
|
41
46
|
ready: boolean;
|
|
@@ -339,6 +344,11 @@ export function detectNodeVersion(): string | null {
|
|
|
339
344
|
}
|
|
340
345
|
|
|
341
346
|
export interface BuildStatusOptions {
|
|
347
|
+
/**
|
|
348
|
+
* An explicit repository to inspect. Absent, the install's own: a clone's
|
|
349
|
+
* checkout, and for anything else none (CR138). It used to default to the
|
|
350
|
+
* cwd, which for a skill is the person's project.
|
|
351
|
+
*/
|
|
342
352
|
start?: string;
|
|
343
353
|
mirrorHome?: string | null;
|
|
344
354
|
channel?: string | null;
|
|
@@ -354,21 +364,6 @@ export interface BuildStatusOptions {
|
|
|
354
364
|
install?: InstallKind;
|
|
355
365
|
}
|
|
356
366
|
|
|
357
|
-
/**
|
|
358
|
-
* The channel the report shows. A clone is inspected at `start`, as the
|
|
359
|
-
* oracle did and `version --start PATH` still means; a package has no tree at
|
|
360
|
-
* `start` and keeps its channel in the user's config file (US3 D9).
|
|
361
|
-
*/
|
|
362
|
-
function channelForStatus(
|
|
363
|
-
install: InstallKind,
|
|
364
|
-
startPath: string,
|
|
365
|
-
override: string | null,
|
|
366
|
-
env: NodeJS.ProcessEnv,
|
|
367
|
-
): MarkerValue {
|
|
368
|
-
if (install.kind === "package") return channelFor(install, env, undefined, override);
|
|
369
|
-
return inspectUpdateChannel(startPath, override);
|
|
370
|
-
}
|
|
371
|
-
|
|
372
367
|
/**
|
|
373
368
|
* Python's `resolve_mirror_home` raises `ValueError`, and
|
|
374
369
|
* `build_runtime_status` prints `str(exc)` as `Mirror home note:`. The front
|
|
@@ -394,16 +389,17 @@ function mirrorHomeForStatus(env: DbPathEnv): { home: string | null; error: stri
|
|
|
394
389
|
|
|
395
390
|
/** Port of `build_runtime_status`. */
|
|
396
391
|
export function buildRuntimeStatus(options: BuildStatusOptions = {}): RuntimeStatusReport {
|
|
397
|
-
const startPath = resolve(options.start ?? process.cwd());
|
|
398
392
|
const env = options.env ?? process.env;
|
|
399
393
|
const install =
|
|
400
394
|
options.install ??
|
|
401
395
|
detectInstallKind({ frontDoorPath: new URL("../frontDoor/cli.ts", import.meta.url).pathname });
|
|
402
|
-
// The
|
|
403
|
-
// cwd
|
|
404
|
-
//
|
|
405
|
-
//
|
|
406
|
-
|
|
396
|
+
// The repository rows are the install's own, or the one `start` names; never
|
|
397
|
+
// the cwd's (CR138). The git facts are a clone's: a package has no
|
|
398
|
+
// repository, and grading the cwd as one read "not a git repository" as a git
|
|
399
|
+
// error, said `attention needed`, and so refused every package update at the
|
|
400
|
+
// gate (CV22.DS10.US3 plateau 4, found by the package lane of the update smoke).
|
|
401
|
+
const root = inspectionRootFor(install, options.start);
|
|
402
|
+
const git = inspectGitFor(install, root);
|
|
407
403
|
|
|
408
404
|
let mirrorHome: string | null;
|
|
409
405
|
let mirrorHomeError: string | null;
|
|
@@ -430,9 +426,9 @@ export function buildRuntimeStatus(options: BuildStatusOptions = {}): RuntimeSta
|
|
|
430
426
|
core_migrations: inspectCoreMigrations(dbPath, dbExists),
|
|
431
427
|
extensions: listInstalledExtensions(mirrorHome),
|
|
432
428
|
extension_health: inspectExtensionHealth(mirrorHome, dbPath, dbExists),
|
|
433
|
-
clone_role:
|
|
429
|
+
clone_role: cloneRoleFor(install, root),
|
|
434
430
|
memory_env: memoryEnv,
|
|
435
|
-
update_channel:
|
|
431
|
+
update_channel: channelForReport(install, root, env, undefined, options.channel ?? null),
|
|
436
432
|
node_version: options.nodeVersion === undefined ? detectNodeVersion() : options.nodeVersion,
|
|
437
433
|
};
|
|
438
434
|
}
|
|
@@ -533,8 +529,7 @@ export function renderRuntimeStatus(
|
|
|
533
529
|
lines.push("Installed extensions: 0");
|
|
534
530
|
}
|
|
535
531
|
lines.push(...renderExtensionHealth(report.extension_health));
|
|
536
|
-
lines.push(
|
|
537
|
-
if (report.clone_role.note) lines.push(`Clone role note: ${report.clone_role.note}`);
|
|
532
|
+
lines.push(...renderCloneRoleLines(report.install, report.clone_role));
|
|
538
533
|
lines.push(`Update channel: ${report.update_channel.value}`);
|
|
539
534
|
if (report.update_channel.note) lines.push(`Update channel note: ${report.update_channel.note}`);
|
|
540
535
|
lines.push(`Node: ${report.node_version || "not found (TS front door requires Node >= 24)"}`);
|