facult 1.1.0 → 1.2.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 +312 -26
- package/package.json +1 -1
- package/src/agents.ts +26 -1
- package/src/ai-state.ts +27 -2
- package/src/ai.ts +1763 -0
- package/src/audit/update-index.ts +1 -0
- package/src/autosync.ts +96 -27
- package/src/builtin.ts +61 -0
- package/src/cli-context.ts +198 -0
- package/src/enable-disable.ts +1 -0
- package/src/global-docs.ts +50 -6
- package/src/graph-query.ts +175 -0
- package/src/graph.ts +119 -0
- package/src/index-builder.ts +1099 -41
- package/src/index.ts +445 -23
- package/src/manage.ts +1870 -188
- package/src/paths.ts +137 -5
- package/src/query.ts +135 -4
- package/src/remote.ts +140 -9
- package/src/trust-list.ts +1 -0
- package/src/trust.ts +1 -0
package/README.md
CHANGED
|
@@ -15,14 +15,16 @@
|
|
|
15
15
|
</a>
|
|
16
16
|
</div>
|
|
17
17
|
|
|
18
|
-
`facult` is a CLI for managing
|
|
18
|
+
`facult` is a CLI for managing canonical AI capability across tools, users, and projects.
|
|
19
19
|
|
|
20
20
|
It helps you:
|
|
21
21
|
- discover what is installed on your machine
|
|
22
22
|
- consolidate everything into one canonical store
|
|
23
23
|
- review trust/security before installing remote content
|
|
24
24
|
- sync managed outputs into Codex, Cursor, and Claude
|
|
25
|
-
- manage a git-backed
|
|
25
|
+
- manage a git-backed AI store under `~/.ai` and repo-local `.ai/`
|
|
26
|
+
- model relationships between instructions, snippets, agents, skills, and rendered tool outputs
|
|
27
|
+
- preserve learning through writeback and evolve canonical assets over time
|
|
26
28
|
|
|
27
29
|
## What facult Is
|
|
28
30
|
|
|
@@ -32,7 +34,126 @@ Think of it as:
|
|
|
32
34
|
- inventory + auditing for agent assets
|
|
33
35
|
- package manager interface for skill/MCP catalogs
|
|
34
36
|
- sync layer that applies your chosen setup to each tool
|
|
35
|
-
- canonical source manager for global AI instructions, agents,
|
|
37
|
+
- canonical source manager for global and project AI instructions, snippets, agents, skills, tool configs, and rules
|
|
38
|
+
- a local capability graph for discovering what exists and what depends on what
|
|
39
|
+
- a writeback/evolution loop for turning repeated friction into durable improvements
|
|
40
|
+
|
|
41
|
+
## What facult Does
|
|
42
|
+
|
|
43
|
+
`facult` is not just a skill manager.
|
|
44
|
+
|
|
45
|
+
It provides five connected layers:
|
|
46
|
+
|
|
47
|
+
1. Canonical source
|
|
48
|
+
- global capability in `~/.ai`
|
|
49
|
+
- project capability in `<repo>/.ai`
|
|
50
|
+
- optional built-in Facult capability packs for bootstrap and defaults
|
|
51
|
+
2. Discovery
|
|
52
|
+
- inventory across skills, agents, snippets, instructions, MCP, and rendered surfaces
|
|
53
|
+
- merged views across builtin, global, and project provenance
|
|
54
|
+
- explicit dependency graph queries
|
|
55
|
+
3. Sync
|
|
56
|
+
- managed tool outputs for Codex, Claude, Cursor, and other file-backed surfaces
|
|
57
|
+
- rendered docs, agents, skills, MCP, config, and rules
|
|
58
|
+
4. Automation
|
|
59
|
+
- background autosync for local propagation
|
|
60
|
+
- optional git autosync for the canonical store
|
|
61
|
+
5. Evolution
|
|
62
|
+
- writeback capture
|
|
63
|
+
- proposal drafting and review
|
|
64
|
+
- controlled apply back into canonical assets
|
|
65
|
+
|
|
66
|
+
## Default Operating Model
|
|
67
|
+
|
|
68
|
+
`facult` ships with a built-in Facult operating-model pack. That pack includes default:
|
|
69
|
+
|
|
70
|
+
- instructions for evolution, integration, and project capability
|
|
71
|
+
- specialist agents such as `writeback-curator`, `evolution-planner`, and `scope-promoter`
|
|
72
|
+
- skills such as `capability-evolution` and `project-operating-layer-design`
|
|
73
|
+
|
|
74
|
+
When managed sync is enabled, these built-in assets are available by default even if you never copy them into `~/.ai`.
|
|
75
|
+
|
|
76
|
+
That means:
|
|
77
|
+
- builtin skills sync into managed tool skill directories by default
|
|
78
|
+
- builtin agents sync into tool agent directories when the tool supports agents
|
|
79
|
+
- if you do not author your own `AGENTS.global.md`, `facult` renders a builtin global baseline doc into tool-native global docs
|
|
80
|
+
|
|
81
|
+
This is intentionally virtual at the canonical level:
|
|
82
|
+
- builtin defaults remain part of the packaged tool
|
|
83
|
+
- your personal `~/.ai` stays clean unless you explicitly vendor or override something
|
|
84
|
+
- the live tool output on disk still contains the rendered defaults, so users and agents can read them directly
|
|
85
|
+
|
|
86
|
+
In practice, this means you do not need to drive writeback and evolution through the CLI alone. The default skills, agents, and global docs are meant to make that operating model available automatically.
|
|
87
|
+
|
|
88
|
+
If you want to disable the builtin default layer for a specific global or project canonical root:
|
|
89
|
+
|
|
90
|
+
```toml
|
|
91
|
+
version = 1
|
|
92
|
+
|
|
93
|
+
[builtin]
|
|
94
|
+
sync_defaults = false
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Put that in `config.toml` or `config.local.toml` under the active canonical root.
|
|
98
|
+
|
|
99
|
+
## Core Concepts
|
|
100
|
+
|
|
101
|
+
### Canonical vs rendered
|
|
102
|
+
|
|
103
|
+
`facult` separates source-of-truth from tool-native output.
|
|
104
|
+
|
|
105
|
+
- canonical source lives in `~/.ai` or `<repo>/.ai`
|
|
106
|
+
- rendered outputs live in tool homes like `~/.codex`, `<repo>/.codex`, `~/.claude`, or `~/.cursor`
|
|
107
|
+
- generated state lives in `~/.facult` or `<repo>/.facult`
|
|
108
|
+
|
|
109
|
+
This keeps authored capability portable and reviewable while still producing the exact files each tool expects.
|
|
110
|
+
|
|
111
|
+
### Global vs project capability
|
|
112
|
+
|
|
113
|
+
Use global `~/.ai` for reusable personal defaults:
|
|
114
|
+
- cross-project instructions
|
|
115
|
+
- reusable specialist agents
|
|
116
|
+
- shared skills
|
|
117
|
+
- default tool config and rules
|
|
118
|
+
|
|
119
|
+
Use project `.ai/` for repo-owned capability:
|
|
120
|
+
- project-specific instructions and snippets
|
|
121
|
+
- local architecture/testing doctrine
|
|
122
|
+
- project agents and skills that should travel with the codebase
|
|
123
|
+
- repo-local rendered outputs for teammates
|
|
124
|
+
|
|
125
|
+
Project capability is allowed to extend or shadow global capability in merged views, but it does not silently mutate the global source of truth.
|
|
126
|
+
|
|
127
|
+
### The capability graph
|
|
128
|
+
|
|
129
|
+
`facult` builds a generated graph of explicit relationships between canonical assets and rendered outputs.
|
|
130
|
+
|
|
131
|
+
That graph tracks things like:
|
|
132
|
+
- snippet markers
|
|
133
|
+
- `@ai/...` and `@project/...` refs
|
|
134
|
+
- `${refs.*}` symbolic refs
|
|
135
|
+
- rendered-target edges from canonical source to live tool files
|
|
136
|
+
|
|
137
|
+
This makes it possible to answer:
|
|
138
|
+
- what capability do I already have?
|
|
139
|
+
- what instructions or snippets does this agent depend on?
|
|
140
|
+
- what rendered files change if I update this canonical asset?
|
|
141
|
+
- what project asset is shadowing a global asset?
|
|
142
|
+
|
|
143
|
+
### Writeback and evolution
|
|
144
|
+
|
|
145
|
+
`facult` treats repeated failures, weak loops, missing context, and reusable patterns as signal worth preserving.
|
|
146
|
+
|
|
147
|
+
Writeback is the act of recording that signal in a structured way.
|
|
148
|
+
Evolution is the act of grouping that signal into reviewable proposals and applying it back into canonical assets.
|
|
149
|
+
|
|
150
|
+
This matters because otherwise the same problems repeat in chat without ever improving the actual operating layer. With `facult`, you can:
|
|
151
|
+
- record a weak verification pattern
|
|
152
|
+
- group repeated writebacks around an instruction or agent
|
|
153
|
+
- draft a proposal to tighten that canonical asset
|
|
154
|
+
- review and apply the change in a controlled way
|
|
155
|
+
|
|
156
|
+
The result is that your AI system can get better over time without hiding mutations in tool-specific state or losing the reasoning behind a change.
|
|
36
157
|
|
|
37
158
|
## Quick Start
|
|
38
159
|
|
|
@@ -96,21 +217,57 @@ facult index
|
|
|
96
217
|
|
|
97
218
|
Why `keep-current`: it is deterministic and non-interactive for duplicate sources.
|
|
98
219
|
|
|
99
|
-
Canonical source root: `~/.ai
|
|
220
|
+
Canonical source root: `~/.ai` for global work, or `<repo>/.ai` for project-local work. Generated state lives next to the active canonical root:
|
|
221
|
+
- global: `~/.facult`
|
|
222
|
+
- project: `<repo>/.facult`
|
|
223
|
+
|
|
224
|
+
### 3b. Bootstrap a repo-local `.ai`
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
cd /path/to/repo
|
|
228
|
+
bunx facult templates init project-ai
|
|
229
|
+
bunx facult index
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
This seeds `<repo>/.ai` from the built-in Facult operating-model pack and writes a merged project index/graph under `<repo>/.facult/ai/`.
|
|
100
233
|
|
|
101
234
|
### 4. Inspect what you have
|
|
102
235
|
|
|
103
236
|
```bash
|
|
104
237
|
facult list skills
|
|
238
|
+
facult list instructions
|
|
105
239
|
facult list mcp
|
|
106
240
|
facult show requesting-code-review
|
|
241
|
+
facult show instruction:WRITING
|
|
107
242
|
facult show mcp:github
|
|
243
|
+
facult find verification
|
|
244
|
+
facult graph show instruction:WRITING
|
|
245
|
+
facult graph deps AGENTS.global.md
|
|
246
|
+
facult graph dependents @ai/instructions/WRITING.md
|
|
247
|
+
facult ai writeback add --kind weak_verification --summary "Checks were too shallow" --asset instruction:VERIFICATION
|
|
248
|
+
facult ai evolve propose
|
|
249
|
+
facult ai evolve draft EV-00001
|
|
250
|
+
facult ai evolve accept EV-00001
|
|
251
|
+
facult ai evolve apply EV-00001
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Context controls:
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
facult list instructions --global
|
|
258
|
+
facult list instructions --project
|
|
259
|
+
facult find verification --scope merged --source project
|
|
260
|
+
facult sync codex --project
|
|
261
|
+
facult autosync status --global
|
|
262
|
+
facult list agents --root /path/to/repo/.ai
|
|
108
263
|
```
|
|
109
264
|
|
|
110
265
|
### 5. Enable managed mode for your tools
|
|
111
266
|
|
|
112
267
|
```bash
|
|
113
|
-
facult manage codex
|
|
268
|
+
facult manage codex --dry-run
|
|
269
|
+
facult manage codex --adopt-existing
|
|
270
|
+
facult sync codex --builtin-conflicts overwrite
|
|
114
271
|
facult manage cursor
|
|
115
272
|
facult manage claude
|
|
116
273
|
|
|
@@ -119,6 +276,9 @@ facult sync
|
|
|
119
276
|
```
|
|
120
277
|
|
|
121
278
|
At this point, your selected skills are actively synced to all managed tools.
|
|
279
|
+
If you run these commands from inside a repo that has `<repo>/.ai`, `facult` targets the project-local canonical store and repo-local tool outputs by default.
|
|
280
|
+
On first entry to managed mode, use `--dry-run` first if the live tool already has local content. `facult` will show what it would adopt into the active canonical store across skills, agents, docs, rules, config, and MCP, plus any conflicts. Then rerun with `--adopt-existing`; if names or files collide, add `--existing-conflicts keep-canonical` or `--existing-conflicts keep-existing`.
|
|
281
|
+
For builtin-backed rendered defaults, `facult` now tracks the last managed render hash. If a user edits the generated target locally, normal sync warns and preserves that local edit instead of silently overwriting it. To replace the local edit with the latest packaged builtin default, rerun sync with `--builtin-conflicts overwrite`.
|
|
122
282
|
|
|
123
283
|
### 6. Turn on background autosync
|
|
124
284
|
|
|
@@ -127,8 +287,8 @@ facult autosync install --git-remote origin --git-branch main --git-interval-min
|
|
|
127
287
|
facult autosync status
|
|
128
288
|
```
|
|
129
289
|
|
|
130
|
-
This installs a
|
|
131
|
-
- watches `~/.ai` for local changes and syncs managed tool outputs automatically
|
|
290
|
+
This installs a macOS LaunchAgent that:
|
|
291
|
+
- watches the active canonical root (`~/.ai` or `<repo>/.ai`) for local changes and syncs managed tool outputs automatically
|
|
132
292
|
- tracks dirty state for the canonical repo
|
|
133
293
|
- runs a slower git autosync loop that batches changes, auto-commits them, rebases on the configured remote branch, and pushes on success
|
|
134
294
|
|
|
@@ -175,9 +335,9 @@ facult sync
|
|
|
175
335
|
|
|
176
336
|
Note: `templates init mcp ...` is a scaffold, not a running server by itself.
|
|
177
337
|
|
|
178
|
-
## The
|
|
338
|
+
## The `.ai` Model
|
|
179
339
|
|
|
180
|
-
`facult`
|
|
340
|
+
`facult` treats both `~/.ai` and `<repo>/.ai` as canonical AI stores. The global store is for personal reusable capability; the project store is for repo-owned capability that should travel with the codebase.
|
|
181
341
|
|
|
182
342
|
Typical layout:
|
|
183
343
|
|
|
@@ -197,18 +357,42 @@ Typical layout:
|
|
|
197
357
|
codex/
|
|
198
358
|
config.toml
|
|
199
359
|
rules/
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
360
|
+
<repo>/
|
|
361
|
+
.ai/
|
|
362
|
+
config.toml
|
|
363
|
+
instructions/
|
|
364
|
+
snippets/
|
|
365
|
+
agents/
|
|
366
|
+
skills/
|
|
367
|
+
tools/
|
|
368
|
+
.facult/
|
|
369
|
+
ai/
|
|
370
|
+
index.json
|
|
371
|
+
graph.json
|
|
372
|
+
.codex/
|
|
373
|
+
.claude/
|
|
206
374
|
```
|
|
207
375
|
|
|
208
376
|
Important split:
|
|
209
|
-
-
|
|
210
|
-
-
|
|
211
|
-
- tool homes such as
|
|
377
|
+
- `.ai/` is canonical source
|
|
378
|
+
- `.facult/` is generated state, trust state, managed tool state, autosync state, and caches
|
|
379
|
+
- tool homes such as `.codex/` and `.claude/` are rendered outputs
|
|
380
|
+
- the generated capability graph lives at `.facult/ai/graph.json`
|
|
381
|
+
|
|
382
|
+
### Asset types
|
|
383
|
+
|
|
384
|
+
The canonical store can contain several distinct asset classes:
|
|
385
|
+
|
|
386
|
+
- `instructions/`: reusable doctrine and deeper conceptual guidance
|
|
387
|
+
- `snippets/`: small composable blocks that can be inserted into rendered markdown
|
|
388
|
+
- `agents/`: role-specific agent manifests
|
|
389
|
+
- `skills/`: workflow-specific capability folders
|
|
390
|
+
- `mcp/`: canonical MCP server definitions
|
|
391
|
+
- `tools/<tool>/config.toml`: canonical tool config
|
|
392
|
+
- `tools/<tool>/rules/*.rules`: canonical tool rules
|
|
393
|
+
- global docs such as `AGENTS.global.md` and `AGENTS.override.global.md`
|
|
394
|
+
|
|
395
|
+
Not every asset syncs directly to a tool. Some exist primarily to support rendered outputs or to be discovered and reused by other canonical assets.
|
|
212
396
|
|
|
213
397
|
### Canonical conventions
|
|
214
398
|
|
|
@@ -216,6 +400,8 @@ Important split:
|
|
|
216
400
|
- Use `snippets/` for composable partial blocks injected into markdown templates
|
|
217
401
|
- Use `tools/codex/rules/*.rules` for actual Codex approval-policy rules
|
|
218
402
|
- Use logical refs such as `@ai/instructions/WRITING.md` in tracked source
|
|
403
|
+
- Use `@builtin/facult-operating-model/...` for packaged Facult defaults
|
|
404
|
+
- Use `@project/...` when a tracked ref must resolve inside a repo-local `.ai`
|
|
219
405
|
- Use config-backed refs in prompts where you want stable named references such as `${refs.writing_rule}`
|
|
220
406
|
|
|
221
407
|
### Config and env layering
|
|
@@ -239,6 +425,8 @@ Built-ins currently include:
|
|
|
239
425
|
Recommended split:
|
|
240
426
|
- `config.toml`: tracked, portable, non-secret refs/defaults
|
|
241
427
|
- `config.local.toml`: ignored, machine-local paths and secrets
|
|
428
|
+
- `[builtin].sync_defaults = false`: disable builtin default sync/materialization for this root
|
|
429
|
+
- `facult sync --builtin-conflicts overwrite`: allow packaged builtin defaults to overwrite locally modified generated targets
|
|
242
430
|
|
|
243
431
|
### Snippets
|
|
244
432
|
|
|
@@ -263,6 +451,92 @@ facult snippets sync [--dry-run] [file...]
|
|
|
263
451
|
|
|
264
452
|
Snippets are already used during global Codex `AGENTS.md` rendering.
|
|
265
453
|
|
|
454
|
+
### Graph inspection
|
|
455
|
+
|
|
456
|
+
The generated graph in `.facult/ai/graph.json` is queryable directly:
|
|
457
|
+
|
|
458
|
+
```bash
|
|
459
|
+
facult graph show instruction:WRITING
|
|
460
|
+
facult graph deps AGENTS.global.md
|
|
461
|
+
facult graph dependents @project/instructions/TESTING.md
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
This is the explicit dependency layer for:
|
|
465
|
+
- snippet markers like `<!-- fclty:... -->`
|
|
466
|
+
- config-backed refs like `${refs.*}`
|
|
467
|
+
- canonical refs like `@ai/...`
|
|
468
|
+
- project refs like `@project/...`
|
|
469
|
+
- rendered outputs such as managed agents, docs, MCP configs, tool configs, and tool rules
|
|
470
|
+
|
|
471
|
+
### Writeback and evolution
|
|
472
|
+
|
|
473
|
+
`facult` also has a local writeback/evolution substrate built on top of the graph:
|
|
474
|
+
|
|
475
|
+
```bash
|
|
476
|
+
facult ai writeback add \
|
|
477
|
+
--kind weak_verification \
|
|
478
|
+
--summary "Verification guidance did not distinguish shallow checks from meaningful proof." \
|
|
479
|
+
--asset instruction:VERIFICATION \
|
|
480
|
+
--tag verification \
|
|
481
|
+
--tag false-positive
|
|
482
|
+
|
|
483
|
+
facult ai writeback list
|
|
484
|
+
facult ai writeback show WB-00001
|
|
485
|
+
facult ai writeback group --by asset
|
|
486
|
+
facult ai writeback summarize --by kind
|
|
487
|
+
facult ai evolve propose
|
|
488
|
+
facult ai evolve list
|
|
489
|
+
facult ai evolve show EV-00001
|
|
490
|
+
facult ai evolve draft EV-00001
|
|
491
|
+
facult ai evolve review EV-00001
|
|
492
|
+
facult ai evolve accept EV-00001
|
|
493
|
+
facult ai evolve reject EV-00001 --reason "Needs a tighter draft"
|
|
494
|
+
facult ai evolve supersede EV-00001 --by EV-00002
|
|
495
|
+
facult ai evolve apply EV-00001
|
|
496
|
+
facult ai evolve promote EV-00003 --to global --project
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
Runtime state stays generated and local:
|
|
500
|
+
- global writeback state: `~/.facult/ai/global/...`
|
|
501
|
+
- project writeback state: `~/.facult/ai/projects/<slug>/...`
|
|
502
|
+
|
|
503
|
+
That split is intentional:
|
|
504
|
+
- canonical source remains in `~/.ai` or `<repo>/.ai`
|
|
505
|
+
- writeback queues, journals, and proposal records stay outside the canonical git-backed tree by default
|
|
506
|
+
|
|
507
|
+
Use writeback when:
|
|
508
|
+
- a task exposed a weak or misleading verification loop
|
|
509
|
+
- an instruction or agent was missing key context
|
|
510
|
+
- a pattern proved reusable enough to become doctrine
|
|
511
|
+
- a project-local pattern deserves promotion toward global capability
|
|
512
|
+
|
|
513
|
+
Do not think of writeback as “taking notes.” Think of it as preserving signal that should change the system, not just the current conversation.
|
|
514
|
+
|
|
515
|
+
For many users, the normal entrypoint is not the CLI directly. The builtin operating-model layer is designed so synced agents, skills, and global docs can push the system toward writeback and evolution by default, while the `facult ai ...` commands remain the explicit operator surface when you want direct control.
|
|
516
|
+
|
|
517
|
+
Current apply semantics are intentionally policy-bound:
|
|
518
|
+
- targets are resolved through the generated graph when possible and fall back to canonical ref resolution for missing assets
|
|
519
|
+
- apply is limited to markdown canonical assets
|
|
520
|
+
- proposals must be drafted before they can be applied; higher-risk proposals still require explicit acceptance
|
|
521
|
+
- supported proposal kinds currently include `create_instruction`, `update_instruction`, `create_agent`, `update_agent`, `update_asset`, `create_asset`, `extract_snippet`, `add_skill`, and `promote_asset`
|
|
522
|
+
- low-risk project-scoped additive proposals such as `create_instruction` can be applied directly after drafting, while global and higher-risk proposals still require review/acceptance
|
|
523
|
+
|
|
524
|
+
Current review/draft semantics:
|
|
525
|
+
- `writeback group` and `writeback summarize` expose recurring patterns across `asset`, `kind`, and `domain` without mutating canonical assets
|
|
526
|
+
- drafted proposals emit both a human-readable markdown draft and a patch artifact under generated state
|
|
527
|
+
- rerunning `evolve draft <id> --append ...` revises the draft and records draft history
|
|
528
|
+
- `evolve promote --to global` creates a new high-risk global proposal from a project-scoped proposal; that promoted proposal can then be drafted, reviewed, and applied into `~/.ai`
|
|
529
|
+
|
|
530
|
+
### Scope and source selection
|
|
531
|
+
|
|
532
|
+
Most inventory and sync commands support explicit canonical-root selection:
|
|
533
|
+
|
|
534
|
+
- `--global` to force `~/.ai`
|
|
535
|
+
- `--project` to force the nearest repo-local `.ai`
|
|
536
|
+
- `--root /path/to/.ai` to point at a specific canonical root
|
|
537
|
+
- `--scope merged|global|project` for discovery views
|
|
538
|
+
- `--source builtin|global|project` to filter provenance in list/find/show/graph flows
|
|
539
|
+
|
|
266
540
|
## Security and Trust
|
|
267
541
|
|
|
268
542
|
`facult` has two trust layers:
|
|
@@ -308,9 +582,11 @@ Recommended security flow:
|
|
|
308
582
|
- Inventory and discovery
|
|
309
583
|
```bash
|
|
310
584
|
facult scan [--from <path>] [--json] [--show-duplicates]
|
|
311
|
-
facult list [skills|mcp|agents|snippets] [--enabled-for <tool>] [--untrusted] [--flagged] [--pending]
|
|
585
|
+
facult list [skills|mcp|agents|snippets|instructions] [--enabled-for <tool>] [--untrusted] [--flagged] [--pending]
|
|
312
586
|
facult show <name>
|
|
587
|
+
facult show instruction:<name>
|
|
313
588
|
facult show mcp:<name> [--show-secrets]
|
|
589
|
+
facult find <query> [--json]
|
|
314
590
|
```
|
|
315
591
|
|
|
316
592
|
- Canonical store and migration
|
|
@@ -322,13 +598,13 @@ facult migrate [--from <path>] [--dry-run] [--move] [--write-config]
|
|
|
322
598
|
|
|
323
599
|
- Managed mode and rollout
|
|
324
600
|
```bash
|
|
325
|
-
facult manage <tool>
|
|
601
|
+
facult manage <tool> [--dry-run] [--adopt-existing] [--existing-conflicts keep-canonical|keep-existing]
|
|
326
602
|
facult unmanage <tool>
|
|
327
603
|
facult managed
|
|
328
604
|
facult enable <name> [--for <tool1,tool2,...>]
|
|
329
605
|
facult enable mcp:<name> [--for <tool1,tool2,...>]
|
|
330
606
|
facult disable <name> [--for <tool1,tool2,...>]
|
|
331
|
-
facult sync [tool] [--dry-run]
|
|
607
|
+
facult sync [tool] [--dry-run] [--builtin-conflicts overwrite]
|
|
332
608
|
facult autosync install [tool] [--git-remote <name>] [--git-branch <name>] [--git-interval-minutes <n>] [--git-disable]
|
|
333
609
|
facult autosync status [tool]
|
|
334
610
|
facult autosync restart [tool]
|
|
@@ -351,6 +627,7 @@ facult sources clear <source>
|
|
|
351
627
|
- Templates and snippets
|
|
352
628
|
```bash
|
|
353
629
|
facult templates list
|
|
630
|
+
facult templates init project-ai
|
|
354
631
|
facult templates init skill <name>
|
|
355
632
|
facult templates init mcp <name>
|
|
356
633
|
facult templates init snippet <marker>
|
|
@@ -374,9 +651,10 @@ facult <command> --help
|
|
|
374
651
|
|
|
375
652
|
`facult` resolves the canonical root in this order:
|
|
376
653
|
1. `FACULT_ROOT_DIR`
|
|
377
|
-
2.
|
|
378
|
-
3. `~/.
|
|
379
|
-
4.
|
|
654
|
+
2. nearest project `.ai` from the current working directory for CLI-facing commands
|
|
655
|
+
3. `~/.facult/config.json` (`rootDir`)
|
|
656
|
+
4. `~/.ai`
|
|
657
|
+
5. `~/agents/.facult` (or a detected legacy store under `~/agents/`)
|
|
380
658
|
|
|
381
659
|
### Runtime env vars
|
|
382
660
|
|
|
@@ -452,7 +730,7 @@ Default install path is `~/.facult/bin/facult`. You can pass a custom target dir
|
|
|
452
730
|
|
|
453
731
|
Current v1 behavior:
|
|
454
732
|
- macOS LaunchAgent-backed
|
|
455
|
-
- immediate local managed-tool sync on
|
|
733
|
+
- immediate local managed-tool sync on the configured canonical root
|
|
456
734
|
- periodic git autosync for the canonical repo
|
|
457
735
|
- automatic autosync commits with source-tagged commit messages such as:
|
|
458
736
|
- `chore(facult-autosync): sync canonical ai changes from <host> [service:all]`
|
|
@@ -464,6 +742,14 @@ facult autosync install
|
|
|
464
742
|
facult autosync status
|
|
465
743
|
```
|
|
466
744
|
|
|
745
|
+
Project-local usage:
|
|
746
|
+
|
|
747
|
+
```bash
|
|
748
|
+
cd /path/to/repo
|
|
749
|
+
facult autosync install codex
|
|
750
|
+
facult autosync status codex
|
|
751
|
+
```
|
|
752
|
+
|
|
467
753
|
Tool-scoped service:
|
|
468
754
|
|
|
469
755
|
```bash
|
|
@@ -554,7 +840,7 @@ Not as a first-party `facult mcp serve` runtime.
|
|
|
554
840
|
Yes. The core model now includes:
|
|
555
841
|
- canonical personal AI source in `~/.ai`
|
|
556
842
|
- rendered managed outputs in tool homes such as `~/.codex`
|
|
557
|
-
- global instruction docs such as `AGENTS.global.md`
|
|
843
|
+
- global instruction docs such as `AGENTS.global.md`, rendered by default into `~/.codex/AGENTS.md`, `~/.claude/CLAUDE.md`, and `~/.cursor/AGENTS.md`
|
|
558
844
|
- tool-native configs such as `~/.codex/config.toml`
|
|
559
845
|
- tool-native rule files such as `~/.codex/rules/*.rules`
|
|
560
846
|
|
package/package.json
CHANGED
package/src/agents.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
+
import { facultBuiltinPackRoot } from "./builtin";
|
|
2
3
|
|
|
3
4
|
const AI_REF_RE = /(?<![\w@])@ai\/([^\s"'`<>]+)/g;
|
|
5
|
+
const BUILTIN_REF_RE = /(?<![\w@])@builtin\/([^\s"'`<>]+)/g;
|
|
6
|
+
const PROJECT_REF_RE = /(?<![\w@])@project\/([^\s"'`<>]+)/g;
|
|
4
7
|
const INTERPOLATION_RE = /\$\{([^}]+)\}/g;
|
|
5
8
|
const TRAILING_PUNCTUATION_RE = /[.,;:!?)}\]]+$/;
|
|
6
9
|
const MAX_RENDER_PASSES = 10;
|
|
@@ -40,6 +43,24 @@ export function renderAiRefs(input: string, canonicalRoot: string): string {
|
|
|
40
43
|
});
|
|
41
44
|
}
|
|
42
45
|
|
|
46
|
+
export function renderBuiltinRefs(input: string): string {
|
|
47
|
+
const builtinRoot = facultBuiltinPackRoot();
|
|
48
|
+
return input.replace(BUILTIN_REF_RE, (_match, refPath: string) => {
|
|
49
|
+
const { path, suffix } = trimTrailingPunctuation(refPath);
|
|
50
|
+
const relative = path.startsWith("facult-operating-model/")
|
|
51
|
+
? path.slice("facult-operating-model/".length)
|
|
52
|
+
: path;
|
|
53
|
+
return `${join(builtinRoot, relative)}${suffix}`;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function renderProjectRefs(input: string, projectRoot: string): string {
|
|
58
|
+
return input.replace(PROJECT_REF_RE, (_match, refPath: string) => {
|
|
59
|
+
const { path, suffix } = trimTrailingPunctuation(refPath);
|
|
60
|
+
return `${join(projectRoot, ".ai", path)}${suffix}`;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
43
64
|
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
44
65
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
45
66
|
}
|
|
@@ -169,7 +190,11 @@ export async function renderCanonicalText(
|
|
|
169
190
|
seen.add(rendered);
|
|
170
191
|
|
|
171
192
|
const interpolated = interpolateString(rendered, context);
|
|
172
|
-
const
|
|
193
|
+
const withAiRefs = renderAiRefs(interpolated, options.rootDir);
|
|
194
|
+
const withBuiltinRefs = renderBuiltinRefs(withAiRefs);
|
|
195
|
+
const withRefs = options.projectRoot
|
|
196
|
+
? renderProjectRefs(withBuiltinRefs, options.projectRoot)
|
|
197
|
+
: withBuiltinRefs;
|
|
173
198
|
if (withRefs === rendered) {
|
|
174
199
|
return withRefs;
|
|
175
200
|
}
|
package/src/ai-state.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { copyFile, mkdir, stat } from "node:fs/promises";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import { buildIndex } from "./index-builder";
|
|
4
|
-
import { facultAiIndexPath } from "./paths";
|
|
4
|
+
import { facultAiGraphPath, facultAiIndexPath } from "./paths";
|
|
5
5
|
|
|
6
6
|
async function fileExists(path: string): Promise<boolean> {
|
|
7
7
|
try {
|
|
@@ -24,7 +24,7 @@ export async function ensureAiIndexPath(args: {
|
|
|
24
24
|
repaired: boolean;
|
|
25
25
|
source: "generated" | "legacy" | "rebuilt" | "missing";
|
|
26
26
|
}> {
|
|
27
|
-
const generatedPath = facultAiIndexPath(args.homeDir);
|
|
27
|
+
const generatedPath = facultAiIndexPath(args.homeDir, args.rootDir);
|
|
28
28
|
if (await fileExists(generatedPath)) {
|
|
29
29
|
return { path: generatedPath, repaired: false, source: "generated" };
|
|
30
30
|
}
|
|
@@ -53,3 +53,28 @@ export async function ensureAiIndexPath(args: {
|
|
|
53
53
|
|
|
54
54
|
return { path: generatedPath, repaired: false, source: "missing" };
|
|
55
55
|
}
|
|
56
|
+
|
|
57
|
+
export async function ensureAiGraphPath(args: {
|
|
58
|
+
homeDir: string;
|
|
59
|
+
rootDir: string;
|
|
60
|
+
repair?: boolean;
|
|
61
|
+
}): Promise<{
|
|
62
|
+
path: string;
|
|
63
|
+
rebuilt: boolean;
|
|
64
|
+
}> {
|
|
65
|
+
const generatedPath = facultAiGraphPath(args.homeDir, args.rootDir);
|
|
66
|
+
if (await fileExists(generatedPath)) {
|
|
67
|
+
return { path: generatedPath, rebuilt: false };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (args.repair !== false) {
|
|
71
|
+
const { graphPath } = await buildIndex({
|
|
72
|
+
rootDir: args.rootDir,
|
|
73
|
+
homeDir: args.homeDir,
|
|
74
|
+
force: false,
|
|
75
|
+
});
|
|
76
|
+
return { path: graphPath, rebuilt: true };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return { path: generatedPath, rebuilt: false };
|
|
80
|
+
}
|