grounder 0.4.0 → 0.6.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 +150 -271
- package/dist/agents/claude.d.ts +4 -4
- package/dist/agents/claude.d.ts.map +1 -1
- package/dist/agents/claude.js +158 -178
- package/dist/agents/claude.js.map +1 -1
- package/dist/agents/cursor.d.ts +3 -3
- package/dist/agents/cursor.d.ts.map +1 -1
- package/dist/agents/cursor.js +97 -143
- package/dist/agents/cursor.js.map +1 -1
- package/dist/agents/home-skills.d.ts +46 -0
- package/dist/agents/home-skills.d.ts.map +1 -0
- package/dist/agents/home-skills.js +83 -0
- package/dist/agents/home-skills.js.map +1 -0
- package/dist/agents/hook-fragment.d.ts +52 -0
- package/dist/agents/hook-fragment.d.ts.map +1 -0
- package/dist/agents/hook-fragment.js +76 -0
- package/dist/agents/hook-fragment.js.map +1 -0
- package/dist/agents/hook-install.d.ts +62 -0
- package/dist/agents/hook-install.d.ts.map +1 -0
- package/dist/agents/hook-install.js +74 -0
- package/dist/agents/hook-install.js.map +1 -0
- package/dist/agents/hook-runtime.d.ts +80 -13
- package/dist/agents/hook-runtime.d.ts.map +1 -1
- package/dist/agents/hook-runtime.js +278 -74
- package/dist/agents/hook-runtime.js.map +1 -1
- package/dist/agents/index.d.ts +8 -14
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +13 -19
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/types.d.ts +56 -16
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/cli.js +15 -10
- package/dist/cli.js.map +1 -1
- package/dist/commands/apply.d.ts +69 -0
- package/dist/commands/apply.d.ts.map +1 -0
- package/dist/commands/apply.js +238 -0
- package/dist/commands/apply.js.map +1 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +197 -101
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/handoff/list.d.ts +23 -13
- package/dist/commands/handoff/list.d.ts.map +1 -1
- package/dist/commands/handoff/list.js +28 -16
- package/dist/commands/handoff/list.js.map +1 -1
- package/dist/commands/handoff/peek.d.ts +1 -1
- package/dist/commands/handoff/peek.d.ts.map +1 -1
- package/dist/commands/handoff/peek.js +28 -12
- package/dist/commands/handoff/peek.js.map +1 -1
- package/dist/commands/handoff.d.ts +2 -0
- package/dist/commands/handoff.d.ts.map +1 -1
- package/dist/commands/handoff.js +10 -1
- package/dist/commands/handoff.js.map +1 -1
- package/dist/commands/install-drift.d.ts +34 -0
- package/dist/commands/install-drift.d.ts.map +1 -0
- package/dist/commands/install-drift.js +72 -0
- package/dist/commands/install-drift.js.map +1 -0
- package/dist/commands/link.d.ts +12 -0
- package/dist/commands/link.d.ts.map +1 -0
- package/dist/commands/{repo/init.js → link.js} +35 -27
- package/dist/commands/link.js.map +1 -0
- package/dist/commands/migrate.d.ts +11 -3
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +66 -34
- package/dist/commands/migrate.js.map +1 -1
- package/dist/commands/note/list.d.ts +17 -9
- package/dist/commands/note/list.d.ts.map +1 -1
- package/dist/commands/note/list.js +19 -14
- package/dist/commands/note/list.js.map +1 -1
- package/dist/commands/note.d.ts +2 -0
- package/dist/commands/note.d.ts.map +1 -1
- package/dist/commands/note.js +10 -1
- package/dist/commands/note.js.map +1 -1
- package/dist/commands/output.d.ts +22 -2
- package/dist/commands/output.d.ts.map +1 -1
- package/dist/commands/output.js +18 -6
- package/dist/commands/output.js.map +1 -1
- package/dist/commands/overview.d.ts +33 -0
- package/dist/commands/overview.d.ts.map +1 -0
- package/dist/commands/overview.js +150 -0
- package/dist/commands/overview.js.map +1 -0
- package/dist/commands/plan/list.d.ts +20 -12
- package/dist/commands/plan/list.d.ts.map +1 -1
- package/dist/commands/plan/list.js +22 -17
- package/dist/commands/plan/list.js.map +1 -1
- package/dist/commands/plan.d.ts +2 -0
- package/dist/commands/plan.d.ts.map +1 -1
- package/dist/commands/plan.js +12 -2
- package/dist/commands/plan.js.map +1 -1
- package/dist/commands/render-artifact-table.d.ts +85 -0
- package/dist/commands/render-artifact-table.d.ts.map +1 -0
- package/dist/commands/render-artifact-table.js +232 -0
- package/dist/commands/render-artifact-table.js.map +1 -0
- package/dist/commands/require-linked.js +2 -2
- package/dist/commands/require-linked.js.map +1 -1
- package/dist/commands/search.d.ts +23 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +288 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/{vault/init.d.ts → setup.d.ts} +5 -4
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +210 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/status.d.ts +7 -0
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +273 -83
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/upgrade-banner.d.ts +2 -2
- package/dist/commands/upgrade-banner.js +2 -2
- package/dist/connector/home.d.ts +12 -0
- package/dist/connector/home.d.ts.map +1 -1
- package/dist/connector/home.js +26 -2
- package/dist/connector/home.js.map +1 -1
- package/dist/connector/ledger-migrations.d.ts +55 -0
- package/dist/connector/ledger-migrations.d.ts.map +1 -0
- package/dist/connector/ledger-migrations.js +94 -0
- package/dist/connector/ledger-migrations.js.map +1 -0
- package/dist/connector/state.d.ts +97 -60
- package/dist/connector/state.d.ts.map +1 -1
- package/dist/connector/state.js +165 -107
- package/dist/connector/state.js.map +1 -1
- package/dist/connector/vault.d.ts +2 -0
- package/dist/connector/vault.d.ts.map +1 -1
- package/dist/connector/vault.js +6 -1
- package/dist/connector/vault.js.map +1 -1
- package/dist/help.d.ts +3 -3
- package/dist/help.d.ts.map +1 -1
- package/dist/help.js +97 -56
- package/dist/help.js.map +1 -1
- package/dist/reconcile/apply.d.ts +31 -0
- package/dist/reconcile/apply.d.ts.map +1 -0
- package/dist/reconcile/apply.js +97 -0
- package/dist/reconcile/apply.js.map +1 -0
- package/dist/reconcile/core.d.ts +82 -0
- package/dist/reconcile/core.d.ts.map +1 -0
- package/dist/reconcile/core.js +163 -0
- package/dist/reconcile/core.js.map +1 -0
- package/dist/reconcile/disk.d.ts +13 -0
- package/dist/reconcile/disk.d.ts.map +1 -0
- package/dist/reconcile/disk.js +28 -0
- package/dist/reconcile/disk.js.map +1 -0
- package/dist/util/frontmatter.d.ts +9 -7
- package/dist/util/frontmatter.d.ts.map +1 -1
- package/dist/util/frontmatter.js +29 -4
- package/dist/util/frontmatter.js.map +1 -1
- package/dist/util/fs.d.ts +14 -0
- package/dist/util/fs.d.ts.map +1 -1
- package/dist/util/fs.js +27 -1
- package/dist/util/fs.js.map +1 -1
- package/dist/util/merge-json.d.ts +13 -2
- package/dist/util/merge-json.d.ts.map +1 -1
- package/dist/util/merge-json.js +24 -10
- package/dist/util/merge-json.js.map +1 -1
- package/dist/util/path.d.ts +23 -0
- package/dist/util/path.d.ts.map +1 -1
- package/dist/util/path.js +39 -0
- package/dist/util/path.js.map +1 -1
- package/dist/vault/list-handoffs.d.ts +14 -2
- package/dist/vault/list-handoffs.d.ts.map +1 -1
- package/dist/vault/list-handoffs.js +40 -23
- package/dist/vault/list-handoffs.js.map +1 -1
- package/dist/vault/list-markdown.d.ts +8 -0
- package/dist/vault/list-markdown.d.ts.map +1 -0
- package/dist/vault/list-markdown.js +35 -0
- package/dist/vault/list-markdown.js.map +1 -0
- package/dist/vault/list-notes.d.ts +15 -6
- package/dist/vault/list-notes.d.ts.map +1 -1
- package/dist/vault/list-notes.js +23 -27
- package/dist/vault/list-notes.js.map +1 -1
- package/dist/vault/list-plans.d.ts +12 -3
- package/dist/vault/list-plans.d.ts.map +1 -1
- package/dist/vault/list-plans.js +20 -24
- package/dist/vault/list-plans.js.map +1 -1
- package/dist/vault/search.d.ts +55 -0
- package/dist/vault/search.d.ts.map +1 -0
- package/dist/vault/search.js +432 -0
- package/dist/vault/search.js.map +1 -0
- package/dist/vault/write-handoff.d.ts +2 -0
- package/dist/vault/write-handoff.d.ts.map +1 -1
- package/dist/vault/write-handoff.js +5 -0
- package/dist/vault/write-handoff.js.map +1 -1
- package/dist/vault/write-note.d.ts +2 -0
- package/dist/vault/write-note.d.ts.map +1 -1
- package/dist/vault/write-note.js +9 -1
- package/dist/vault/write-note.js.map +1 -1
- package/dist/vault/write-plan.d.ts +4 -0
- package/dist/vault/write-plan.d.ts.map +1 -1
- package/dist/vault/write-plan.js +14 -1
- package/dist/vault/write-plan.js.map +1 -1
- package/package.json +11 -4
- package/templates/agents/claude/skills/grounder-handoff/SKILL.md +73 -0
- package/templates/agents/claude/{commands/grounder-note.md → skills/grounder-note/SKILL.md} +12 -2
- package/templates/agents/claude/skills/grounder-overview/SKILL.md +21 -0
- package/templates/agents/claude/{commands/grounder-plan.md → skills/grounder-plan/SKILL.md} +13 -5
- package/templates/agents/claude/skills/grounder-recall/SKILL.md +34 -0
- package/templates/agents/claude/skills/grounder-search/SKILL.md +152 -0
- package/templates/agents/cursor/skills/grounder-handoff/SKILL.md +73 -0
- package/templates/agents/cursor/{commands/grounder-note.md → skills/grounder-note/SKILL.md} +12 -2
- package/templates/agents/cursor/skills/grounder-overview/SKILL.md +21 -0
- package/templates/agents/cursor/{commands/grounder-plan.md → skills/grounder-plan/SKILL.md} +13 -5
- package/templates/agents/cursor/skills/grounder-recall/SKILL.md +34 -0
- package/templates/agents/cursor/skills/grounder-search/SKILL.md +152 -0
- package/templates/vault/plan.md +1 -1
- package/templates/vault/session-handoff.md +2 -1
- package/dist/agents/install-command.d.ts +0 -35
- package/dist/agents/install-command.d.ts.map +0 -1
- package/dist/agents/install-command.js +0 -65
- package/dist/agents/install-command.js.map +0 -1
- package/dist/commands/apply-agent-installs.d.ts +0 -34
- package/dist/commands/apply-agent-installs.d.ts.map +0 -1
- package/dist/commands/apply-agent-installs.js +0 -137
- package/dist/commands/apply-agent-installs.js.map +0 -1
- package/dist/commands/repo/init.d.ts +0 -11
- package/dist/commands/repo/init.d.ts.map +0 -1
- package/dist/commands/repo/init.js.map +0 -1
- package/dist/commands/vault/init.d.ts.map +0 -1
- package/dist/commands/vault/init.js +0 -90
- package/dist/commands/vault/init.js.map +0 -1
- package/templates/agents/claude/commands/grounder-task-handoff.md +0 -54
- package/templates/agents/claude/commands/grounder-task.md +0 -22
- package/templates/agents/cursor/commands/grounder-task-handoff.md +0 -54
- package/templates/agents/cursor/commands/grounder-task.md +0 -22
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { mkdir } from "node:fs/promises";
|
|
2
|
+
import { runtimeCliPath } from "../agents/hook-runtime.js";
|
|
3
|
+
import { resolveAgents } from "../agents/index.js";
|
|
4
|
+
import { homeConfigPath, InvalidHomeConfigError, readHomeConfig, withHomeDir, writeHomeConfig, } from "../connector/home.js";
|
|
5
|
+
import { ledgerVersionChanged, readGrounderState, statePath, } from "../connector/state.js";
|
|
6
|
+
import { isUnsupportedSchemaError } from "../connector/unsupported-schema.js";
|
|
7
|
+
import { helpExitCode } from "../help.js";
|
|
8
|
+
import { VERSION } from "../index.js";
|
|
9
|
+
import { flagBool, flagStrings, parseArgs } from "../util/parse-args.js";
|
|
10
|
+
import { resolveUserPath } from "../util/path.js";
|
|
11
|
+
import { confirm } from "../util/prompt.js";
|
|
12
|
+
import { projectsParent } from "../vault/layout.js";
|
|
13
|
+
import { applyAgentInstalls } from "./apply.js";
|
|
14
|
+
import { renderAgentErrors, renderModifiedNote, renderSummary, renderTable, rowsFromApplyResult, stateRow, } from "./render-artifact-table.js";
|
|
15
|
+
/**
|
|
16
|
+
* Read the existing home config for the "already exists with a different
|
|
17
|
+
* vault" conflict check. A corrupt/invalid file has no value worth
|
|
18
|
+
* conflict-checking — treat it as absent so `setup` can recreate it without
|
|
19
|
+
* requiring the user to manually delete it first.
|
|
20
|
+
*/
|
|
21
|
+
async function readExistingHomeForSetup() {
|
|
22
|
+
try {
|
|
23
|
+
return { home: await readHomeConfig(), invalidReason: null };
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
const reason = error instanceof InvalidHomeConfigError
|
|
27
|
+
? error.reason
|
|
28
|
+
: error instanceof Error
|
|
29
|
+
? error.message
|
|
30
|
+
: String(error);
|
|
31
|
+
return { home: null, invalidReason: reason };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export async function runSetup(argv) {
|
|
35
|
+
const helpCode = helpExitCode(argv, "setup");
|
|
36
|
+
if (helpCode !== null) {
|
|
37
|
+
return helpCode;
|
|
38
|
+
}
|
|
39
|
+
const { positional, flags, repeated } = parseArgs(argv);
|
|
40
|
+
const vaultPathArg = positional[0];
|
|
41
|
+
const yes = flagBool(flags, "yes", "y");
|
|
42
|
+
const force = flagBool(flags, "force", "f");
|
|
43
|
+
const hooks = flagBool(flags, "hooks");
|
|
44
|
+
const dryRun = flagBool(flags, "dry-run");
|
|
45
|
+
const agents = flagStrings(repeated, "agent");
|
|
46
|
+
if (!vaultPathArg) {
|
|
47
|
+
process.stderr.write("Usage: grounder setup <path>\n");
|
|
48
|
+
return 1;
|
|
49
|
+
}
|
|
50
|
+
return runSetupWithOptions({
|
|
51
|
+
vaultPath: vaultPathArg,
|
|
52
|
+
yes,
|
|
53
|
+
force,
|
|
54
|
+
hooks,
|
|
55
|
+
dryRun,
|
|
56
|
+
agents: agents.length > 0 ? agents : undefined,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
export async function runSetupWithOptions(options) {
|
|
60
|
+
return withHomeDir(options.homeDir, async () => {
|
|
61
|
+
const vaultRoot = resolveUserPath(options.vaultPath);
|
|
62
|
+
const yes = options.yes ?? false;
|
|
63
|
+
const force = options.force ?? false;
|
|
64
|
+
const hooks = options.hooks ?? false;
|
|
65
|
+
const dryRun = options.dryRun ?? false;
|
|
66
|
+
const homeDir = options.homeDir;
|
|
67
|
+
const { home: existingHome, invalidReason } = await readExistingHomeForSetup();
|
|
68
|
+
const projectsDir = projectsParent(vaultRoot);
|
|
69
|
+
const agents = await resolveAgents(options.agents);
|
|
70
|
+
if (existingHome && existingHome.vaultRoot !== vaultRoot && !force) {
|
|
71
|
+
process.stderr.write(`Home config already exists with vault ${existingHome.vaultRoot}. Use --force to overwrite.\n`);
|
|
72
|
+
return 1;
|
|
73
|
+
}
|
|
74
|
+
if (invalidReason) {
|
|
75
|
+
process.stdout.write(dryRun
|
|
76
|
+
? `Would replace invalid home config (${invalidReason}).\n`
|
|
77
|
+
: `Will replace invalid home config (${invalidReason}).\n`);
|
|
78
|
+
}
|
|
79
|
+
process.stdout.write(`Vault root: ${vaultRoot}\n`);
|
|
80
|
+
process.stdout.write("Connect to a markdown vault (once per machine).\n");
|
|
81
|
+
process.stdout.write(dryRun ? "Would write:\n" : "Will write:\n");
|
|
82
|
+
// One label column shared by every preview line — "runtime" (not "grounder
|
|
83
|
+
// runtime") so it's no wider than it needs to be and lines up with the
|
|
84
|
+
// agent ids instead of forcing its own, much wider, column.
|
|
85
|
+
const previewLabelWidth = Math.max("home".length, "vault".length, "runtime".length, ...agents.map((agent) => agent.id.length));
|
|
86
|
+
process.stdout.write(` ${"home".padEnd(previewLabelWidth)} ${homeConfigPath(homeDir)}\n`);
|
|
87
|
+
process.stdout.write(` ${"vault".padEnd(previewLabelWidth)} 10-Projects/ (if missing)\n`);
|
|
88
|
+
if (agents.length > 0) {
|
|
89
|
+
process.stdout.write(` ${"runtime".padEnd(previewLabelWidth)} ${runtimeCliPath(homeDir)}\n`);
|
|
90
|
+
}
|
|
91
|
+
for (const agent of agents) {
|
|
92
|
+
const label = agent.id.padEnd(previewLabelWidth);
|
|
93
|
+
for (const artifactPath of agent.expectedArtifacts(homeDir)) {
|
|
94
|
+
process.stdout.write(` ${label} ${artifactPath}\n`);
|
|
95
|
+
}
|
|
96
|
+
if (hooks && agent.expectedHookArtifacts) {
|
|
97
|
+
for (const hookPath of agent.expectedHookArtifacts(homeDir)) {
|
|
98
|
+
process.stdout.write(` ${label} hook ${hookPath}\n`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (agents.length === 0) {
|
|
103
|
+
process.stdout.write(" (no supported agents detected — skipping agent artifacts)\n");
|
|
104
|
+
}
|
|
105
|
+
process.stdout.write("\n");
|
|
106
|
+
if (dryRun) {
|
|
107
|
+
let priorState;
|
|
108
|
+
let applyResult;
|
|
109
|
+
try {
|
|
110
|
+
priorState = await readGrounderState(homeDir);
|
|
111
|
+
applyResult = await applyAgentInstalls({
|
|
112
|
+
agents,
|
|
113
|
+
force,
|
|
114
|
+
hooks,
|
|
115
|
+
// `setup` never retires legacy pre-skill command files, even with
|
|
116
|
+
// `--force` — see docs/upgrading.md and ApplyAgentInstallsOptions#retireLegacy.
|
|
117
|
+
retireLegacy: false,
|
|
118
|
+
dryRun: true,
|
|
119
|
+
homeDir,
|
|
120
|
+
grounderVersion: VERSION,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
if (isUnsupportedSchemaError(error)) {
|
|
125
|
+
process.stderr.write(`${error.message}\n`);
|
|
126
|
+
return 1;
|
|
127
|
+
}
|
|
128
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
129
|
+
process.stderr.write(`Dry run failed: agent install would not succeed:\n ${detail}\n`);
|
|
130
|
+
return 1;
|
|
131
|
+
}
|
|
132
|
+
if (agents.length === 0) {
|
|
133
|
+
return 0;
|
|
134
|
+
}
|
|
135
|
+
// A dry run never writes `~/.grounder/config.json` — if it doesn't
|
|
136
|
+
// already exist (first-time setup, or one whose config is invalid and
|
|
137
|
+
// would be replaced), `grounder migrate --force` would fail with "No
|
|
138
|
+
// home config found" until this exact command is re-run without
|
|
139
|
+
// `--dry-run`. Point the reader at that instead of a command that
|
|
140
|
+
// can't work yet.
|
|
141
|
+
const forceCommand = existingHome
|
|
142
|
+
? "grounder migrate"
|
|
143
|
+
: `grounder setup ${options.vaultPath}`;
|
|
144
|
+
const hadAgentError = reportAgentInstalls(applyResult, priorState, homeDir, true, forceCommand);
|
|
145
|
+
return hadAgentError ? 1 : 0;
|
|
146
|
+
}
|
|
147
|
+
if (!yes) {
|
|
148
|
+
const proceed = await confirm("Proceed?");
|
|
149
|
+
if (!proceed) {
|
|
150
|
+
process.stdout.write("Aborted.\n");
|
|
151
|
+
return 0;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
await writeHomeConfig({ vaultRoot });
|
|
155
|
+
await mkdir(projectsDir, { recursive: true });
|
|
156
|
+
process.stdout.write("✓ Wrote home config\n");
|
|
157
|
+
process.stdout.write(`✓ Vault scaffold: ${projectsDir}\n`);
|
|
158
|
+
let priorState;
|
|
159
|
+
let applyResult;
|
|
160
|
+
try {
|
|
161
|
+
priorState = await readGrounderState(homeDir);
|
|
162
|
+
applyResult = await applyAgentInstalls({
|
|
163
|
+
agents,
|
|
164
|
+
force,
|
|
165
|
+
hooks,
|
|
166
|
+
retireLegacy: false,
|
|
167
|
+
homeDir,
|
|
168
|
+
grounderVersion: VERSION,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
if (isUnsupportedSchemaError(error)) {
|
|
173
|
+
process.stderr.write(`${error.message}\n`);
|
|
174
|
+
return 1;
|
|
175
|
+
}
|
|
176
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
177
|
+
process.stderr.write(`\nHome config and vault scaffold were written, but agent skill files/hooks were not installed:\n ${detail}\n`);
|
|
178
|
+
return 1;
|
|
179
|
+
}
|
|
180
|
+
if (agents.length === 0) {
|
|
181
|
+
return 0;
|
|
182
|
+
}
|
|
183
|
+
// Real setup has already written a valid home config by this point
|
|
184
|
+
// (above), so `grounder migrate --force` always works as the remediation
|
|
185
|
+
// command here.
|
|
186
|
+
const hadAgentError = reportAgentInstalls(applyResult, priorState, homeDir, false, "grounder migrate");
|
|
187
|
+
return hadAgentError ? 1 : 0;
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Render the table/summary/conflict-note block shared by a dry-run preview
|
|
192
|
+
* and a real apply — same rows, same wording, only `renderSummary`'s tense
|
|
193
|
+
* differs, so a dry run tells the truth about what a real run would show.
|
|
194
|
+
* Returns whether any agent's hook step failed (see
|
|
195
|
+
* `AgentApplyResult#error`), so the caller can exit non-zero without
|
|
196
|
+
* duplicating that check.
|
|
197
|
+
*/
|
|
198
|
+
function reportAgentInstalls(applyResult, priorState, homeDir, dryRun, forceCommand) {
|
|
199
|
+
const rows = rowsFromApplyResult(applyResult);
|
|
200
|
+
const ledgerChanged = applyResult.agents.some((a) => a.ledgerChanged) || ledgerVersionChanged(priorState, VERSION);
|
|
201
|
+
rows.push(stateRow(ledgerChanged, priorState, statePath(homeDir)));
|
|
202
|
+
process.stdout.write("\n");
|
|
203
|
+
renderTable(rows);
|
|
204
|
+
process.stdout.write("\n");
|
|
205
|
+
renderSummary(rows, dryRun);
|
|
206
|
+
renderModifiedNote(rows, forceCommand);
|
|
207
|
+
renderAgentErrors(applyResult);
|
|
208
|
+
return applyResult.agents.some((a) => a.error !== undefined);
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
export interface StatusOptions {
|
|
2
2
|
cwd?: string;
|
|
3
3
|
homeDir?: string;
|
|
4
|
+
json?: boolean;
|
|
4
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* Bump whenever `writeJsonOutput`'s payload shape changes (fields added,
|
|
8
|
+
* removed, or renamed) — consumers (the VS Code extension's `status.ts`)
|
|
9
|
+
* compare this directly instead of inferring compatibility structurally.
|
|
10
|
+
*/
|
|
11
|
+
export declare const STATUS_JSON_SCHEMA_VERSION = 1;
|
|
5
12
|
export declare function runStatus(argv: string[]): Promise<number>;
|
|
6
13
|
export declare function runStatusWithOptions(options?: StatusOptions): Promise<number>;
|
|
7
14
|
//# sourceMappingURL=status.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAyBA,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAoWD;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAoC5C,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAqB/D;AAED,wBAAsB,oBAAoB,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAUvF"}
|
package/dist/commands/status.js
CHANGED
|
@@ -1,36 +1,30 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { ALL_AGENTS } from "../agents/index.js";
|
|
3
2
|
import { currentBranch, findGitRoot } from "../connector/git.js";
|
|
4
3
|
import { homeConfigPath, readHomeConfig, withHomeDir } from "../connector/home.js";
|
|
5
4
|
import { findLinkedRepoRoot, readRepoConfig, repoConfigPath, } from "../connector/repo.js";
|
|
6
|
-
import {
|
|
5
|
+
import { readGrounderState, statePath } from "../connector/state.js";
|
|
7
6
|
import { isUnsupportedSchemaError } from "../connector/unsupported-schema.js";
|
|
8
|
-
import { resolveLogsDir, resolveNotesDir, resolvePlansDir, resolveVaultRoot, } from "../connector/vault.js";
|
|
7
|
+
import { resolveLogsDir, resolveNotesDir, resolvePlansDir, resolveProjectVaultRoot, resolveVaultRoot, } from "../connector/vault.js";
|
|
9
8
|
import { helpExitCode } from "../help.js";
|
|
10
9
|
import { VERSION } from "../index.js";
|
|
10
|
+
import { flagBool, parseArgs } from "../util/parse-args.js";
|
|
11
|
+
import { installDriftDetected } from "./install-drift.js";
|
|
11
12
|
import { writeSection } from "./output.js";
|
|
12
13
|
import { packageVersionNotice } from "./package-version-notice.js";
|
|
13
14
|
const LABEL_WIDTH = 12;
|
|
14
|
-
const VAULT_INIT = "grounder
|
|
15
|
-
const REPO_INIT = "grounder
|
|
16
|
-
const REPO_INIT_FORCE = "grounder
|
|
15
|
+
const VAULT_INIT = "grounder setup <path>";
|
|
16
|
+
const REPO_INIT = "grounder link";
|
|
17
|
+
const REPO_INIT_FORCE = "grounder link --force";
|
|
17
18
|
const MIGRATE = "grounder migrate";
|
|
18
19
|
const MIGRATE_FORCE = "grounder migrate --force";
|
|
19
20
|
const UPGRADE_GROUNDER = "upgrade grounder";
|
|
21
|
+
const USAGE = "Usage: grounder status [--json]\n";
|
|
20
22
|
function statusLine(label, value) {
|
|
21
23
|
return ` ${label.padEnd(LABEL_WIDTH)}${value}\n`;
|
|
22
24
|
}
|
|
23
25
|
function errorDetail(error) {
|
|
24
26
|
return error instanceof Error ? error.message : String(error);
|
|
25
27
|
}
|
|
26
|
-
async function writeGitLine(gitRoot) {
|
|
27
|
-
if (!gitRoot) {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
const branch = await currentBranch(gitRoot);
|
|
31
|
-
const gitValue = branch !== undefined ? `${gitRoot} (branch: ${branch})` : gitRoot;
|
|
32
|
-
process.stdout.write(statusLine("Git:", gitValue));
|
|
33
|
-
}
|
|
34
28
|
async function tryReadHome() {
|
|
35
29
|
try {
|
|
36
30
|
return { home: await readHomeConfig(), invalid: null };
|
|
@@ -51,94 +45,290 @@ async function tryReadRepo(linkedRoot) {
|
|
|
51
45
|
};
|
|
52
46
|
}
|
|
53
47
|
}
|
|
54
|
-
async function
|
|
48
|
+
async function gatherStateInfo(homeDir) {
|
|
55
49
|
try {
|
|
56
50
|
const state = await readGrounderState(homeDir);
|
|
57
51
|
if (!state) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
process.stdout.write(statusLine("Package:", packageNotice.status));
|
|
65
|
-
}
|
|
66
|
-
if (isInstallSchemaStale(state, ALL_AGENTS)) {
|
|
67
|
-
process.stdout.write(statusLine("Schemas:", `ledger stale → ${MIGRATE}`));
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
process.stdout.write(statusLine("Schemas:", "current"));
|
|
52
|
+
return {
|
|
53
|
+
path: statePath(homeDir),
|
|
54
|
+
status: "missing",
|
|
55
|
+
packageNotice: null,
|
|
56
|
+
installCurrent: null,
|
|
57
|
+
};
|
|
71
58
|
}
|
|
59
|
+
const notice = packageVersionNotice(VERSION, state.grounderVersion);
|
|
60
|
+
const drift = await installDriftDetected(state, homeDir);
|
|
61
|
+
return {
|
|
62
|
+
path: statePath(homeDir),
|
|
63
|
+
status: "ok",
|
|
64
|
+
packageNotice: notice,
|
|
65
|
+
installCurrent: !drift,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
return {
|
|
70
|
+
path: statePath(homeDir),
|
|
71
|
+
status: isUnsupportedSchemaError(error) ? "unsupported" : "invalid",
|
|
72
|
+
packageNotice: null,
|
|
73
|
+
installCurrent: null,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function gatherMachine(homeInvalid, home, homeDir) {
|
|
78
|
+
const configPath = homeConfigPath(homeDir);
|
|
79
|
+
if (homeInvalid) {
|
|
80
|
+
return { configPath, configState: "invalid", vaultRoot: null, state: null };
|
|
81
|
+
}
|
|
82
|
+
if (!home) {
|
|
83
|
+
return { configPath, configState: "missing", vaultRoot: null, state: null };
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
configPath,
|
|
87
|
+
configState: "ok",
|
|
88
|
+
vaultRoot: resolveVaultRoot(home),
|
|
89
|
+
state: await gatherStateInfo(homeDir),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
async function gatherGit(gitRoot) {
|
|
93
|
+
if (!gitRoot) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
const branch = await currentBranch(gitRoot);
|
|
97
|
+
return { root: gitRoot, branch: branch ?? null };
|
|
98
|
+
}
|
|
99
|
+
async function gatherProject(params) {
|
|
100
|
+
const { cwd, gitRoot, linkedRoot, repo, repoInvalid, repoUnsupported, home } = params;
|
|
101
|
+
if (!linkedRoot) {
|
|
102
|
+
return {
|
|
103
|
+
linked: false,
|
|
104
|
+
folder: null,
|
|
105
|
+
isAncestorLink: false,
|
|
106
|
+
configPath: null,
|
|
107
|
+
configState: "missing",
|
|
108
|
+
projectId: null,
|
|
109
|
+
vaultRoot: null,
|
|
110
|
+
notesDir: null,
|
|
111
|
+
logsDir: null,
|
|
112
|
+
plansDir: null,
|
|
113
|
+
git: null,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
const git = await gatherGit(gitRoot);
|
|
117
|
+
const isAncestorLink = linkedRoot !== cwd;
|
|
118
|
+
const configPath = repoConfigPath(linkedRoot);
|
|
119
|
+
if (repoInvalid || !repo) {
|
|
120
|
+
const configState = repoUnsupported
|
|
121
|
+
? "unsupported"
|
|
122
|
+
: repoInvalid
|
|
123
|
+
? "invalid"
|
|
124
|
+
: "missing";
|
|
125
|
+
return {
|
|
126
|
+
linked: true,
|
|
127
|
+
folder: linkedRoot,
|
|
128
|
+
isAncestorLink,
|
|
129
|
+
configPath,
|
|
130
|
+
configState,
|
|
131
|
+
projectId: null,
|
|
132
|
+
vaultRoot: null,
|
|
133
|
+
notesDir: null,
|
|
134
|
+
logsDir: null,
|
|
135
|
+
plansDir: null,
|
|
136
|
+
git,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
linked: true,
|
|
141
|
+
folder: linkedRoot,
|
|
142
|
+
isAncestorLink,
|
|
143
|
+
configPath,
|
|
144
|
+
configState: "ok",
|
|
145
|
+
projectId: repo.projectId,
|
|
146
|
+
vaultRoot: home ? resolveProjectVaultRoot(home, repo) : null,
|
|
147
|
+
notesDir: home ? resolveNotesDir(home, repo) : null,
|
|
148
|
+
logsDir: home ? resolveLogsDir(home, repo) : null,
|
|
149
|
+
plansDir: home ? resolvePlansDir(home, repo) : null,
|
|
150
|
+
git,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
async function gatherStatus(options) {
|
|
154
|
+
const cwd = path.resolve(options.cwd ?? process.cwd());
|
|
155
|
+
const { home, invalid: homeInvalid } = await tryReadHome();
|
|
156
|
+
const gitRoot = await findGitRoot(cwd);
|
|
157
|
+
const linkedRoot = await findLinkedRepoRoot(cwd, gitRoot);
|
|
158
|
+
const { repo, invalid: repoInvalid, unsupported: repoUnsupported, } = linkedRoot
|
|
159
|
+
? await tryReadRepo(linkedRoot)
|
|
160
|
+
: { repo: null, invalid: null, unsupported: false };
|
|
161
|
+
const machine = await gatherMachine(homeInvalid, home, options.homeDir);
|
|
162
|
+
const project = await gatherProject({
|
|
163
|
+
cwd,
|
|
164
|
+
gitRoot,
|
|
165
|
+
linkedRoot,
|
|
166
|
+
repo,
|
|
167
|
+
repoInvalid,
|
|
168
|
+
repoUnsupported,
|
|
169
|
+
home,
|
|
170
|
+
});
|
|
171
|
+
return { cwd, machine, project };
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* `findLinkedRepoRoot` walks up to the nearest `.grounder.json`, so a
|
|
175
|
+
* subdirectory of a linked repo inherits that link. Surface it explicitly
|
|
176
|
+
* when `linkedRoot` isn't `cwd` itself, so callers (agents included) don't
|
|
177
|
+
* mistake an ancestor's link for this exact folder being linked.
|
|
178
|
+
*/
|
|
179
|
+
function writeAncestorNoteIfAny(cwd, folder) {
|
|
180
|
+
if (folder === cwd) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
process.stdout.write(statusLine("Note:", `linked ancestor — ${cwd} itself is unlinked; grounder link here would create a separate project`));
|
|
184
|
+
}
|
|
185
|
+
function writeGitLine(git) {
|
|
186
|
+
if (!git) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const value = git.branch !== null ? `${git.root} (branch: ${git.branch})` : git.root;
|
|
190
|
+
process.stdout.write(statusLine("Git:", value));
|
|
191
|
+
}
|
|
192
|
+
function writeStateLines(state) {
|
|
193
|
+
if (state.status === "missing") {
|
|
194
|
+
process.stdout.write(statusLine("State:", `missing → ${MIGRATE_FORCE}`));
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
if (state.status === "unsupported") {
|
|
198
|
+
process.stdout.write(statusLine("State:", `unsupported → ${UPGRADE_GROUNDER}`));
|
|
199
|
+
return;
|
|
72
200
|
}
|
|
73
|
-
|
|
201
|
+
if (state.status === "invalid") {
|
|
74
202
|
process.stdout.write(statusLine("State:", `invalid → ${MIGRATE_FORCE}`));
|
|
203
|
+
return;
|
|
75
204
|
}
|
|
205
|
+
process.stdout.write(statusLine("State:", state.path));
|
|
206
|
+
if (state.packageNotice) {
|
|
207
|
+
process.stdout.write(statusLine("Package:", state.packageNotice.status));
|
|
208
|
+
}
|
|
209
|
+
process.stdout.write(statusLine("Install:", state.installCurrent ? "current" : `outdated → ${MIGRATE}`));
|
|
210
|
+
}
|
|
211
|
+
function writeTextOutput(status) {
|
|
212
|
+
const { cwd, machine, project } = status;
|
|
213
|
+
writeSection("Machine");
|
|
214
|
+
if (machine.configState === "invalid") {
|
|
215
|
+
process.stdout.write(statusLine("Config:", `invalid → ${VAULT_INIT}`));
|
|
216
|
+
}
|
|
217
|
+
else if (machine.configState === "missing") {
|
|
218
|
+
process.stdout.write(statusLine("Config:", `missing → ${VAULT_INIT}`));
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
process.stdout.write(statusLine("Config:", machine.configPath));
|
|
222
|
+
process.stdout.write(statusLine("Vault:", machine.vaultRoot));
|
|
223
|
+
writeStateLines(machine.state);
|
|
224
|
+
}
|
|
225
|
+
process.stdout.write("\n");
|
|
226
|
+
writeSection("Project");
|
|
227
|
+
if (!project.linked) {
|
|
228
|
+
process.stdout.write(statusLine("Linked:", "no"));
|
|
229
|
+
if (machine.configState === "ok") {
|
|
230
|
+
process.stdout.write(statusLine("Config:", `missing → ${REPO_INIT}`));
|
|
231
|
+
}
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const folder = project.folder;
|
|
235
|
+
if (project.configState !== "ok") {
|
|
236
|
+
const fix = project.configState === "unsupported"
|
|
237
|
+
? UPGRADE_GROUNDER
|
|
238
|
+
: machine.configState === "ok"
|
|
239
|
+
? REPO_INIT_FORCE
|
|
240
|
+
: VAULT_INIT;
|
|
241
|
+
process.stdout.write(statusLine("Linked:", project.configState === "unsupported" ? `unsupported → ${fix}` : `incomplete → ${fix}`));
|
|
242
|
+
process.stdout.write(statusLine("Folder:", folder));
|
|
243
|
+
writeAncestorNoteIfAny(cwd, folder);
|
|
244
|
+
process.stdout.write(statusLine("Config:", project.configState === "unsupported"
|
|
245
|
+
? `unsupported → ${UPGRADE_GROUNDER}`
|
|
246
|
+
: project.configState === "invalid"
|
|
247
|
+
? `invalid → ${REPO_INIT_FORCE}`
|
|
248
|
+
: `missing → ${REPO_INIT}`));
|
|
249
|
+
writeGitLine(project.git);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
process.stdout.write(statusLine("Linked:", "yes"));
|
|
253
|
+
process.stdout.write(statusLine("Folder:", folder));
|
|
254
|
+
writeAncestorNoteIfAny(cwd, folder);
|
|
255
|
+
process.stdout.write(statusLine("Config:", project.configPath));
|
|
256
|
+
process.stdout.write(statusLine("Id:", project.projectId));
|
|
257
|
+
if (project.notesDir) {
|
|
258
|
+
process.stdout.write(statusLine("In Vault:", project.vaultRoot));
|
|
259
|
+
process.stdout.write(statusLine("Notes:", project.notesDir));
|
|
260
|
+
process.stdout.write(statusLine("Logs:", project.logsDir));
|
|
261
|
+
process.stdout.write(statusLine("Plans:", project.plansDir));
|
|
262
|
+
}
|
|
263
|
+
writeGitLine(project.git);
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Bump whenever `writeJsonOutput`'s payload shape changes (fields added,
|
|
267
|
+
* removed, or renamed) — consumers (the VS Code extension's `status.ts`)
|
|
268
|
+
* compare this directly instead of inferring compatibility structurally.
|
|
269
|
+
*/
|
|
270
|
+
export const STATUS_JSON_SCHEMA_VERSION = 1;
|
|
271
|
+
function writeJsonOutput(status) {
|
|
272
|
+
const { machine, project } = status;
|
|
273
|
+
const payload = {
|
|
274
|
+
schemaVersion: STATUS_JSON_SCHEMA_VERSION,
|
|
275
|
+
machine: {
|
|
276
|
+
configPath: machine.configPath,
|
|
277
|
+
configState: machine.configState,
|
|
278
|
+
vaultRoot: machine.vaultRoot,
|
|
279
|
+
state: machine.state
|
|
280
|
+
? {
|
|
281
|
+
path: machine.state.path,
|
|
282
|
+
status: machine.state.status,
|
|
283
|
+
packageVersionNotice: machine.state.packageNotice?.message ?? null,
|
|
284
|
+
installCurrent: machine.state.installCurrent,
|
|
285
|
+
}
|
|
286
|
+
: null,
|
|
287
|
+
},
|
|
288
|
+
project: {
|
|
289
|
+
linked: project.linked,
|
|
290
|
+
folder: project.folder,
|
|
291
|
+
isAncestorLink: project.isAncestorLink,
|
|
292
|
+
configPath: project.configPath,
|
|
293
|
+
configState: project.configState,
|
|
294
|
+
projectId: project.projectId,
|
|
295
|
+
vaultRoot: project.vaultRoot,
|
|
296
|
+
notesDir: project.notesDir,
|
|
297
|
+
logsDir: project.logsDir,
|
|
298
|
+
plansDir: project.plansDir,
|
|
299
|
+
git: project.git,
|
|
300
|
+
},
|
|
301
|
+
};
|
|
302
|
+
process.stdout.write(`${JSON.stringify(payload)}\n`);
|
|
76
303
|
}
|
|
77
304
|
export async function runStatus(argv) {
|
|
78
305
|
const helpCode = helpExitCode(argv, "status");
|
|
79
306
|
if (helpCode !== null) {
|
|
80
307
|
return helpCode;
|
|
81
308
|
}
|
|
82
|
-
|
|
309
|
+
const { positional, flags } = parseArgs(argv);
|
|
310
|
+
if (positional.length > 0) {
|
|
311
|
+
process.stderr.write(USAGE);
|
|
312
|
+
return 1;
|
|
313
|
+
}
|
|
314
|
+
const allowedFlags = new Set(["json"]);
|
|
315
|
+
for (const key of flags.keys()) {
|
|
316
|
+
if (!allowedFlags.has(key)) {
|
|
317
|
+
process.stderr.write(USAGE);
|
|
318
|
+
return 1;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return runStatusWithOptions({ json: flagBool(flags, "json") });
|
|
83
322
|
}
|
|
84
323
|
export async function runStatusWithOptions(options = {}) {
|
|
85
324
|
return withHomeDir(options.homeDir, async () => {
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const linkedRoot = await findLinkedRepoRoot(cwd, gitRoot);
|
|
90
|
-
const { repo, invalid: repoInvalid, unsupported: repoUnsupported, } = linkedRoot
|
|
91
|
-
? await tryReadRepo(linkedRoot)
|
|
92
|
-
: { repo: null, invalid: null, unsupported: false };
|
|
93
|
-
writeSection("Machine");
|
|
94
|
-
if (homeInvalid) {
|
|
95
|
-
process.stdout.write(statusLine("Config:", `invalid → ${VAULT_INIT}`));
|
|
96
|
-
}
|
|
97
|
-
else if (!home) {
|
|
98
|
-
process.stdout.write(statusLine("Config:", `missing → ${VAULT_INIT}`));
|
|
325
|
+
const status = await gatherStatus(options);
|
|
326
|
+
if (options.json) {
|
|
327
|
+
writeJsonOutput(status);
|
|
99
328
|
}
|
|
100
329
|
else {
|
|
101
|
-
|
|
102
|
-
process.stdout.write(statusLine("Vault:", resolveVaultRoot(home)));
|
|
103
|
-
await writeInstallStateLine(options.homeDir);
|
|
104
|
-
}
|
|
105
|
-
process.stdout.write("\n");
|
|
106
|
-
writeSection("Project");
|
|
107
|
-
if (!linkedRoot) {
|
|
108
|
-
process.stdout.write(statusLine("Linked:", "no"));
|
|
109
|
-
if (home) {
|
|
110
|
-
process.stdout.write(statusLine("Config:", `missing → ${REPO_INIT}`));
|
|
111
|
-
}
|
|
112
|
-
return 0;
|
|
113
|
-
}
|
|
114
|
-
if (repoInvalid || !repo) {
|
|
115
|
-
const fix = repoUnsupported ? UPGRADE_GROUNDER : home ? REPO_INIT_FORCE : VAULT_INIT;
|
|
116
|
-
process.stdout.write(statusLine("Linked:", repoUnsupported ? `unsupported → ${fix}` : `incomplete → ${fix}`));
|
|
117
|
-
process.stdout.write(statusLine("Folder:", linkedRoot));
|
|
118
|
-
process.stdout.write(statusLine("Config:", repoUnsupported
|
|
119
|
-
? `unsupported → ${UPGRADE_GROUNDER}`
|
|
120
|
-
: repoInvalid
|
|
121
|
-
? `invalid → ${REPO_INIT_FORCE}`
|
|
122
|
-
: `missing → ${REPO_INIT}`));
|
|
123
|
-
await writeGitLine(gitRoot);
|
|
124
|
-
return 0;
|
|
125
|
-
}
|
|
126
|
-
if (!home) {
|
|
127
|
-
process.stdout.write(statusLine("Linked:", `incomplete → ${VAULT_INIT}`));
|
|
128
|
-
process.stdout.write(statusLine("Folder:", linkedRoot));
|
|
129
|
-
process.stdout.write(statusLine("Config:", repoConfigPath(linkedRoot)));
|
|
130
|
-
process.stdout.write(statusLine("Id:", repo.projectId));
|
|
131
|
-
await writeGitLine(gitRoot);
|
|
132
|
-
return 0;
|
|
330
|
+
writeTextOutput(status);
|
|
133
331
|
}
|
|
134
|
-
process.stdout.write(statusLine("Linked:", "yes"));
|
|
135
|
-
process.stdout.write(statusLine("Folder:", linkedRoot));
|
|
136
|
-
process.stdout.write(statusLine("Config:", repoConfigPath(linkedRoot)));
|
|
137
|
-
process.stdout.write(statusLine("Id:", repo.projectId));
|
|
138
|
-
process.stdout.write(statusLine("Notes:", resolveNotesDir(home, repo)));
|
|
139
|
-
process.stdout.write(statusLine("Logs:", resolveLogsDir(home, repo)));
|
|
140
|
-
process.stdout.write(statusLine("Plans:", resolvePlansDir(home, repo)));
|
|
141
|
-
await writeGitLine(gitRoot);
|
|
142
332
|
return 0;
|
|
143
333
|
});
|
|
144
334
|
}
|