facult 2.9.0 → 2.10.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 +13 -6
- package/package.json +1 -1
- package/src/manage.ts +40 -20
package/README.md
CHANGED
|
@@ -127,7 +127,7 @@ fclt index
|
|
|
127
127
|
|
|
128
128
|
Why `keep-current`: it is deterministic and non-interactive for duplicate sources.
|
|
129
129
|
|
|
130
|
-
### 4.
|
|
130
|
+
### 4. Optional: manage a tool and sync
|
|
131
131
|
|
|
132
132
|
```bash
|
|
133
133
|
fclt manage codex --dry-run
|
|
@@ -140,7 +140,11 @@ fclt enable requesting-code-review receiving-code-review brainstorming systemati
|
|
|
140
140
|
fclt sync
|
|
141
141
|
```
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
Managed rendering is an advanced mode. Prefer `fclt inventory`, `fclt list`, `fclt consolidate`, and explicit writeback/evolution when you mainly want visibility and normalization across Codex, Claude, and other tool homes. Use `manage` only when you want fclt to write rendered files back into a tool.
|
|
144
|
+
|
|
145
|
+
Use `--dry-run` first if the live tool already has local content. If the tool already contains skills, agents, rules, docs, config, or MCP definitions, rerun `manage` with `--adopt-existing` and add `--existing-conflicts keep-canonical|keep-existing` if names collide.
|
|
146
|
+
|
|
147
|
+
Ordinary `fclt sync` does not import live tool edits into canonical state. If you intentionally edited skills, agents, docs, rules, config, or MCP entries in Codex/Claude and want fclt to pick them up, run `fclt sync --adopt-live`.
|
|
144
148
|
|
|
145
149
|
Codex path policy:
|
|
146
150
|
- skills render to `.agents/skills`
|
|
@@ -200,6 +204,8 @@ Useful AI behavior is composable. You need small reusable parts, a clean way to
|
|
|
200
204
|
- discovery and graph views for dependencies, provenance, and rendered targets
|
|
201
205
|
- writeback and evolution flows for improving canonical assets over time
|
|
202
206
|
|
|
207
|
+
The renderer is optional. The low-friction default is to let tools keep their native files, use `fclt inventory`/`scan`/`list` to see the full global set, and use `fclt consolidate` or `fclt sync --adopt-live` only when you explicitly want to promote live tool edits into canonical `~/.ai`.
|
|
208
|
+
|
|
203
209
|
## Built-in Defaults
|
|
204
210
|
|
|
205
211
|
`fclt` includes a built-in layer for writeback and evolution. By default, that layer provides:
|
|
@@ -231,9 +237,10 @@ Put that in `config.toml` or `config.local.toml` under the active canonical root
|
|
|
231
237
|
|
|
232
238
|
`fclt` is CLI-first. The practical setup is:
|
|
233
239
|
1. Install `fclt` globally so any agent runtime can execute it.
|
|
234
|
-
2.
|
|
235
|
-
3.
|
|
236
|
-
4.
|
|
240
|
+
2. Use `fclt inventory`, `fclt list`, and `fclt consolidate` to inspect and normalize existing tool-native state.
|
|
241
|
+
3. If you want fclt-owned rendered outputs, manage each agent tool with `fclt manage <tool>` and `fclt sync`.
|
|
242
|
+
4. Let the built-in operating-model layer render global writeback/evolution instructions into the tool only where managed rendering is worth the ownership tradeoff.
|
|
243
|
+
5. Optionally scaffold MCP wrappers if you want an MCP entry that delegates to `fclt`.
|
|
237
244
|
|
|
238
245
|
```bash
|
|
239
246
|
# Scaffold reusable templates in the canonical store
|
|
@@ -592,7 +599,7 @@ fclt disable <name> [--for <tool1,tool2,...>]
|
|
|
592
599
|
fclt trust --all
|
|
593
600
|
fclt trust skills --all
|
|
594
601
|
fclt untrust mcp --all
|
|
595
|
-
fclt sync [tool] [--dry-run] [--builtin-conflicts overwrite]
|
|
602
|
+
fclt sync [tool] [--dry-run] [--adopt-live] [--builtin-conflicts overwrite]
|
|
596
603
|
fclt autosync install [tool] [--git-remote <name>] [--git-branch <name>] [--git-interval-minutes <n>] [--git-disable]
|
|
597
604
|
fclt autosync status [tool]
|
|
598
605
|
fclt autosync restart [tool]
|
package/package.json
CHANGED
package/src/manage.ts
CHANGED
|
@@ -137,6 +137,7 @@ export interface SyncOptions {
|
|
|
137
137
|
tool?: string;
|
|
138
138
|
dryRun?: boolean;
|
|
139
139
|
builtinConflictMode?: "warn" | "overwrite";
|
|
140
|
+
adoptLive?: boolean;
|
|
140
141
|
}
|
|
141
142
|
|
|
142
143
|
const MANAGED_VERSION = 1 as const;
|
|
@@ -2421,12 +2422,14 @@ async function syncSkillSymlinks({
|
|
|
2421
2422
|
rootDir,
|
|
2422
2423
|
tool,
|
|
2423
2424
|
dryRun,
|
|
2425
|
+
adoptLive,
|
|
2424
2426
|
}: {
|
|
2425
2427
|
homeDir: string;
|
|
2426
2428
|
toolSkillsDir: string;
|
|
2427
2429
|
rootDir: string;
|
|
2428
2430
|
tool: string;
|
|
2429
2431
|
dryRun?: boolean;
|
|
2432
|
+
adoptLive?: boolean;
|
|
2430
2433
|
}): Promise<SkillSymlinkPlan> {
|
|
2431
2434
|
const plan = await planSkillSymlinkChanges({
|
|
2432
2435
|
homeDir,
|
|
@@ -2438,10 +2441,12 @@ async function syncSkillSymlinks({
|
|
|
2438
2441
|
return plan;
|
|
2439
2442
|
}
|
|
2440
2443
|
|
|
2441
|
-
const adoptedConflicts =
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2444
|
+
const adoptedConflicts = adoptLive
|
|
2445
|
+
? await adoptSkillSymlinkConflictsIntoCanonical({
|
|
2446
|
+
rootDir,
|
|
2447
|
+
conflicts: plan.conflicts,
|
|
2448
|
+
})
|
|
2449
|
+
: [];
|
|
2445
2450
|
const adoptedNames = new Set(
|
|
2446
2451
|
adoptedConflicts.map((conflict) => conflict.name)
|
|
2447
2452
|
);
|
|
@@ -3646,7 +3651,8 @@ function logRenderedConflicts(
|
|
|
3646
3651
|
function logSkillSymlinkConflicts(
|
|
3647
3652
|
tool: string,
|
|
3648
3653
|
conflicts: SkillSymlinkConflict[],
|
|
3649
|
-
dryRun?: boolean
|
|
3654
|
+
dryRun?: boolean,
|
|
3655
|
+
mode: "adopt" | "skip" = "skip"
|
|
3650
3656
|
) {
|
|
3651
3657
|
for (const conflict of conflicts) {
|
|
3652
3658
|
const verb =
|
|
@@ -3654,9 +3660,13 @@ function logSkillSymlinkConflicts(
|
|
|
3654
3660
|
? dryRun
|
|
3655
3661
|
? "would preserve"
|
|
3656
3662
|
: "preserved"
|
|
3657
|
-
:
|
|
3658
|
-
?
|
|
3659
|
-
|
|
3663
|
+
: mode === "adopt"
|
|
3664
|
+
? dryRun
|
|
3665
|
+
? "would adopt"
|
|
3666
|
+
: "adopted"
|
|
3667
|
+
: dryRun
|
|
3668
|
+
? "would skip"
|
|
3669
|
+
: "skipped";
|
|
3660
3670
|
const state =
|
|
3661
3671
|
conflict.reason === "unmanaged"
|
|
3662
3672
|
? "it is not in canonical skill state"
|
|
@@ -3667,7 +3677,7 @@ function logSkillSymlinkConflicts(
|
|
|
3667
3677
|
? ` (canonical ${conflict.canonicalPath})`
|
|
3668
3678
|
: "";
|
|
3669
3679
|
console.warn(
|
|
3670
|
-
`${tool}: ${verb} skill ${conflict.name} from ${conflict.livePath}${canonical} because ${state}
|
|
3680
|
+
`${tool}: ${verb} skill ${conflict.name} from ${conflict.livePath}${canonical} because ${state}.${mode === "skip" && conflict.reason !== "disabled" ? ' Rerun with "--adopt-live" to import it into canonical state.' : ""}`
|
|
3671
3681
|
);
|
|
3672
3682
|
}
|
|
3673
3683
|
}
|
|
@@ -4470,6 +4480,7 @@ async function syncManagedToolEntry({
|
|
|
4470
4480
|
rootDir,
|
|
4471
4481
|
dryRun,
|
|
4472
4482
|
builtinConflictMode,
|
|
4483
|
+
adoptLive,
|
|
4473
4484
|
}: {
|
|
4474
4485
|
homeDir: string;
|
|
4475
4486
|
tool: string;
|
|
@@ -4477,6 +4488,7 @@ async function syncManagedToolEntry({
|
|
|
4477
4488
|
rootDir: string;
|
|
4478
4489
|
dryRun?: boolean;
|
|
4479
4490
|
builtinConflictMode?: "warn" | "overwrite";
|
|
4491
|
+
adoptLive?: boolean;
|
|
4480
4492
|
}) {
|
|
4481
4493
|
const correlationId = randomUUID();
|
|
4482
4494
|
const baseLedger = syncLedgerBase({
|
|
@@ -4515,14 +4527,15 @@ async function syncManagedToolEntry({
|
|
|
4515
4527
|
automationDir: entry.automationDir,
|
|
4516
4528
|
});
|
|
4517
4529
|
|
|
4518
|
-
const adoptedSkills =
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4530
|
+
const adoptedSkills =
|
|
4531
|
+
dryRun || !adoptLive
|
|
4532
|
+
? []
|
|
4533
|
+
: await repairManagedCanonicalContent({
|
|
4534
|
+
homeDir,
|
|
4535
|
+
rootDir,
|
|
4536
|
+
tool,
|
|
4537
|
+
entry,
|
|
4538
|
+
});
|
|
4526
4539
|
|
|
4527
4540
|
const skillPlan = entry.skillsDir
|
|
4528
4541
|
? await syncSkillSymlinks({
|
|
@@ -4531,6 +4544,7 @@ async function syncManagedToolEntry({
|
|
|
4531
4544
|
rootDir,
|
|
4532
4545
|
tool,
|
|
4533
4546
|
dryRun,
|
|
4547
|
+
adoptLive,
|
|
4534
4548
|
})
|
|
4535
4549
|
: { add: [], remove: [], conflicts: [], adopted: [] };
|
|
4536
4550
|
const skillLedgerEvents = collectSkillLedgerEvents({
|
|
@@ -4895,8 +4909,8 @@ async function syncManagedToolEntry({
|
|
|
4895
4909
|
logRenderedConflicts(tool, configRendered.conflicts);
|
|
4896
4910
|
logRenderedConflicts(tool, mcpRendered.conflicts);
|
|
4897
4911
|
logRenderedConflicts(tool, pluginRendered.conflicts);
|
|
4898
|
-
logSkillSymlinkConflicts(tool, skillPlan.adopted);
|
|
4899
|
-
logSkillSymlinkConflicts(tool, skillPlan.conflicts);
|
|
4912
|
+
logSkillSymlinkConflicts(tool, skillPlan.adopted, false, "adopt");
|
|
4913
|
+
logSkillSymlinkConflicts(tool, skillPlan.conflicts, false, "skip");
|
|
4900
4914
|
|
|
4901
4915
|
updateRenderedTargetState({
|
|
4902
4916
|
entry,
|
|
@@ -5004,6 +5018,7 @@ export async function syncManagedTools(opts: SyncOptions = {}) {
|
|
|
5004
5018
|
rootDir,
|
|
5005
5019
|
dryRun: opts.dryRun,
|
|
5006
5020
|
builtinConflictMode: opts.builtinConflictMode,
|
|
5021
|
+
adoptLive: opts.adoptLive,
|
|
5007
5022
|
});
|
|
5008
5023
|
}
|
|
5009
5024
|
|
|
@@ -5196,16 +5211,20 @@ export async function syncCommand(argv: string[]) {
|
|
|
5196
5211
|
console.log(`fclt sync — sync managed tools with canonical state
|
|
5197
5212
|
|
|
5198
5213
|
Usage:
|
|
5199
|
-
fclt sync [tool] [--dry-run] [--builtin-conflicts overwrite] [--root PATH|--global|--project]
|
|
5214
|
+
fclt sync [tool] [--dry-run] [--adopt-live] [--builtin-conflicts overwrite] [--root PATH|--global|--project]
|
|
5200
5215
|
|
|
5201
5216
|
Options:
|
|
5202
5217
|
--dry-run Show what would change
|
|
5218
|
+
--adopt-live Import live tool content into canonical state before rendering
|
|
5203
5219
|
--builtin-conflicts overwrite Replace locally modified builtin-backed rendered files
|
|
5204
5220
|
`);
|
|
5205
5221
|
return;
|
|
5206
5222
|
}
|
|
5207
5223
|
const tool = parsed.argv.find((arg) => !arg.startsWith("-"));
|
|
5208
5224
|
const dryRun = parsed.argv.includes("--dry-run");
|
|
5225
|
+
const adoptLive =
|
|
5226
|
+
parsed.argv.includes("--adopt-live") ||
|
|
5227
|
+
parsed.argv.includes("--adopt-live-skills");
|
|
5209
5228
|
const builtinConflictIndex = parsed.argv.indexOf("--builtin-conflicts");
|
|
5210
5229
|
let builtinConflictMode: "warn" | "overwrite" | undefined;
|
|
5211
5230
|
if (builtinConflictIndex !== -1) {
|
|
@@ -5221,6 +5240,7 @@ Options:
|
|
|
5221
5240
|
await syncManagedTools({
|
|
5222
5241
|
tool,
|
|
5223
5242
|
dryRun,
|
|
5243
|
+
adoptLive,
|
|
5224
5244
|
builtinConflictMode,
|
|
5225
5245
|
rootDir: resolveCliContextRoot({
|
|
5226
5246
|
rootArg: parsed.rootArg,
|