facult 2.12.0 → 2.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.
@@ -0,0 +1,223 @@
1
+ import { homedir } from "node:os";
2
+ import {
3
+ type CapabilityScopeMode,
4
+ parseCliContextArgs,
5
+ resolveCliContextRoot,
6
+ } from "./cli-context";
7
+ import { renderCode, renderKeyValue, renderPage } from "./cli-ui";
8
+ import { loadManagedState } from "./manage";
9
+ import {
10
+ facultAiDraftDir,
11
+ facultAiEvolutionReviewDir,
12
+ facultAiGraphPath,
13
+ facultAiIndexPath,
14
+ facultAiJournalPath,
15
+ facultAiProposalDir,
16
+ facultAiRuntimeScopeDir,
17
+ facultAiStateDir,
18
+ facultAiWritebackQueuePath,
19
+ facultAiWritebackReviewDir,
20
+ facultConfigPath,
21
+ facultGeneratedStateDir,
22
+ facultInstallStatePath,
23
+ facultLocalCacheRoot,
24
+ facultLocalStateRoot,
25
+ facultMachineStateDir,
26
+ facultRootDir,
27
+ facultRuntimeCacheDir,
28
+ machineStateProjectKey,
29
+ preferredGlobalAiRoot,
30
+ projectRootFromAiRoot,
31
+ } from "./paths";
32
+
33
+ export interface FacultPaths {
34
+ version: 1;
35
+ cwd: string;
36
+ homeDir: string;
37
+ scope: CapabilityScopeMode;
38
+ globalRoot: string;
39
+ contextRoot: string;
40
+ projectRoot: string | null;
41
+ projectKey: string | null;
42
+ canonical: {
43
+ globalRoot: string;
44
+ contextRoot: string;
45
+ configPath: string;
46
+ };
47
+ generated: {
48
+ stateDir: string;
49
+ aiStateDir: string;
50
+ indexPath: string;
51
+ graphPath: string;
52
+ };
53
+ runtime: {
54
+ localStateRoot: string;
55
+ localCacheRoot: string;
56
+ installStatePath: string;
57
+ runtimeCacheDir: string;
58
+ machineStateDir: string;
59
+ aiRuntimeScopeDir: string;
60
+ journalPath: string;
61
+ writebackQueuePath: string;
62
+ proposalDir: string;
63
+ draftDir: string;
64
+ };
65
+ review: {
66
+ writebackDir: string;
67
+ evolutionDir: string;
68
+ };
69
+ managedTools: string[];
70
+ }
71
+
72
+ export async function buildPaths(opts?: {
73
+ cwd?: string;
74
+ homeDir?: string;
75
+ rootArg?: string;
76
+ scope?: CapabilityScopeMode;
77
+ }): Promise<FacultPaths> {
78
+ const homeDir = opts?.homeDir ?? process.env.HOME?.trim() ?? homedir();
79
+ const cwd = opts?.cwd ?? process.cwd();
80
+ const scope = opts?.scope ?? "merged";
81
+ const globalRoot = facultRootDir(homeDir);
82
+ const contextRoot = resolveCliContextRoot({
83
+ homeDir,
84
+ cwd,
85
+ rootArg: opts?.rootArg,
86
+ scope,
87
+ });
88
+ const projectRoot = projectRootFromAiRoot(contextRoot, homeDir);
89
+ const managed = await loadManagedState(homeDir, contextRoot);
90
+
91
+ return {
92
+ version: 1,
93
+ cwd,
94
+ homeDir,
95
+ scope,
96
+ globalRoot,
97
+ contextRoot,
98
+ projectRoot,
99
+ projectKey: projectRoot
100
+ ? machineStateProjectKey(contextRoot, homeDir)
101
+ : null,
102
+ canonical: {
103
+ globalRoot: preferredGlobalAiRoot(homeDir),
104
+ contextRoot,
105
+ configPath: facultConfigPath(homeDir),
106
+ },
107
+ generated: {
108
+ stateDir: facultGeneratedStateDir({
109
+ home: homeDir,
110
+ rootDir: contextRoot,
111
+ }),
112
+ aiStateDir: facultAiStateDir(homeDir, contextRoot),
113
+ indexPath: facultAiIndexPath(homeDir, contextRoot),
114
+ graphPath: facultAiGraphPath(homeDir, contextRoot),
115
+ },
116
+ runtime: {
117
+ localStateRoot: facultLocalStateRoot(homeDir),
118
+ localCacheRoot: facultLocalCacheRoot(homeDir),
119
+ installStatePath: facultInstallStatePath(homeDir),
120
+ runtimeCacheDir: facultRuntimeCacheDir(homeDir),
121
+ machineStateDir: facultMachineStateDir(homeDir, contextRoot),
122
+ aiRuntimeScopeDir: facultAiRuntimeScopeDir(homeDir, contextRoot),
123
+ journalPath: facultAiJournalPath(homeDir, contextRoot),
124
+ writebackQueuePath: facultAiWritebackQueuePath(homeDir, contextRoot),
125
+ proposalDir: facultAiProposalDir(homeDir, contextRoot),
126
+ draftDir: facultAiDraftDir(homeDir, contextRoot),
127
+ },
128
+ review: {
129
+ writebackDir: facultAiWritebackReviewDir(homeDir, contextRoot),
130
+ evolutionDir: facultAiEvolutionReviewDir(homeDir, contextRoot),
131
+ },
132
+ managedTools: Object.keys(managed.tools).sort(),
133
+ };
134
+ }
135
+
136
+ function printHelp() {
137
+ console.log(
138
+ renderPage({
139
+ title: "fclt paths",
140
+ subtitle: "Show canonical, generated, runtime, and review paths.",
141
+ sections: [
142
+ {
143
+ title: "Usage",
144
+ lines: [
145
+ renderCode("fclt paths"),
146
+ renderCode("fclt paths --json"),
147
+ renderCode("fclt paths --project --json"),
148
+ ],
149
+ },
150
+ ],
151
+ })
152
+ );
153
+ }
154
+
155
+ function printPaths(paths: FacultPaths) {
156
+ console.log(
157
+ renderPage({
158
+ title: "fclt paths",
159
+ subtitle: paths.contextRoot,
160
+ sections: [
161
+ {
162
+ title: "Canonical",
163
+ lines: renderKeyValue([
164
+ ["global root", paths.globalRoot],
165
+ ["context root", paths.contextRoot],
166
+ ["project root", paths.projectRoot ?? "(none)"],
167
+ ["config", paths.canonical.configPath],
168
+ ]),
169
+ },
170
+ {
171
+ title: "Generated",
172
+ lines: renderKeyValue([
173
+ ["state", paths.generated.stateDir],
174
+ ["index", paths.generated.indexPath],
175
+ ["graph", paths.generated.graphPath],
176
+ ]),
177
+ },
178
+ {
179
+ title: "Runtime",
180
+ lines: renderKeyValue([
181
+ ["machine state", paths.runtime.machineStateDir],
182
+ ["writeback queue", paths.runtime.writebackQueuePath],
183
+ ["proposal dir", paths.runtime.proposalDir],
184
+ ["draft dir", paths.runtime.draftDir],
185
+ ]),
186
+ },
187
+ {
188
+ title: "Review",
189
+ lines: renderKeyValue([
190
+ ["writebacks", paths.review.writebackDir],
191
+ ["evolution", paths.review.evolutionDir],
192
+ ]),
193
+ },
194
+ ],
195
+ })
196
+ );
197
+ }
198
+
199
+ export async function pathsCommand(argv: string[]) {
200
+ if (argv.includes("--help") || argv.includes("-h") || argv[0] === "help") {
201
+ printHelp();
202
+ return;
203
+ }
204
+
205
+ const json = argv.includes("--json");
206
+ try {
207
+ const parsed = parseCliContextArgs(argv.filter((arg) => arg !== "--json"));
208
+ const paths = await buildPaths({
209
+ cwd: process.cwd(),
210
+ homeDir: process.env.HOME?.trim() || homedir(),
211
+ rootArg: parsed.rootArg,
212
+ scope: parsed.scope,
213
+ });
214
+ if (json) {
215
+ console.log(JSON.stringify(paths, null, 2));
216
+ return;
217
+ }
218
+ printPaths(paths);
219
+ } catch (err) {
220
+ console.error(err instanceof Error ? err.message : String(err));
221
+ process.exitCode = 1;
222
+ }
223
+ }