Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,45 @@ Broad managed mode is deprecated and contained by default because it can own or
tool-home surfaces without a transaction receipt. Keep using inventory and previews while the
per-asset deployment replacement is built.

Build a read-only plan for one exact canonical asset and one exact destination:

```bash
fclt deploy plan \
--asset instruction:WORK_UNITS \
--destination instructions/WORK_UNITS.md \
--tool codex \
--adapter-version v1 \
--root /tmp/fclt-proof/.ai \
--target-root /tmp/fclt-proof/codex-home \
--state-root /tmp/fclt-proof/state \
--scope global \
--expected-current-hash absent \
--json
```

`deploy plan` reads canonical, target, and ownership state directly and never writes them. The
content-addressed JSON plan fails closed on stale hashes, unsupported adapters, unresolved
variables, lossy translation, corrupt ownership state, and path escape. Ownership is keyed by the
exact tool and destination, so an asset or adapter change cannot silently claim an already-owned
path. The primary identity losslessly encodes platform path semantics and the verified canonical
path. A separate v2 portability key applies separator normalization, NFC, and the full default
Unicode case fold pinned by `unicode-case-folding@1.1.1`; it detects collisions without conflating
distinct physical paths. True filesystem aliases share ownership; ambiguous case, separator, or
normalization collisions fail closed. Older collision-key contracts require an explicit future
migration. Every persisted identity is recomputed before records are grouped, and unknown keys are
rejected at every level of the exact ownership-state schema. Canonical, target, and snapshot files
are read twice through bounded no-follow descriptors and must retain the same device/inode,
metadata, bytes, canonical identity, and physical containment. The deployment-state directory is
opened once with no-follow directory semantics; enumeration and record opens stay bound to that
descriptor. Its scan is limited to 128 entries, 256 KiB per record, and 4 MiB total. Platforms
without the descriptor-relative primitives fail closed. A shared state root may contain multiple
target roots; unrelated records are structurally validated but do not inherit the current plan's
target boundary. Persisted destination and rollback paths must be absolute, normalized, and safe.
Existing rollback targets are preserved, and snapshot targets must still match their recorded
hash. Ownership transfer is reserved for a future explicit migration command. This slice has no
apply subcommand; any future executor must repeat the safe reads and reverify every plan hash
immediately before mutation.

```bash
fclt setup codex-plugin
fclt manage codex --dry-run
Expand Down Expand Up @@ -543,6 +582,7 @@ fclt index [--force]
Legacy managed-mode inspection:

```bash
fclt deploy plan --help
fclt setup codex-plugin [--dry-run] [--json] [--no-codex-install]
fclt manage <tool> --dry-run
fclt sync [tool] --dry-run
Expand Down
3 changes: 3 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,38 @@ fclt index [--force]

Use these to create or normalize canonical capability in `~/.ai` or `<repo>/.ai`.

## Per-asset deployment planning

```bash
fclt deploy plan --asset instruction:<name>|snippet:<path> \
--destination <relative-path> --tool codex --adapter-version v1 \
--root <canonical-root> --target-root <tool-root> --state-root <state-root> \
--scope global|project [--expected-source-hash sha256:<hex>] \
[--expected-current-hash absent|sha256:<hex>] --json
```

This is a read-only, one-asset/one-destination planning boundary. It emits a deterministic,
content-addressed plan and has no executor. The planner scans canonical ownership records and
allows at most one claim for the exact tool and physical destination. Primary identity is a
lossless, platform-qualified encoding of the verified canonical path. The separate v2 portability
collision key applies slash normalization, NFC, and the full default Unicode case fold pinned by
`unicode-case-folding@1.1.1`: true aliases resolve to one physical identity, while distinct paths in
the same collision class fail closed. Older key contracts require explicit migration. The planner
recomputes both identities for every structurally safe state record before filtering or grouping,
and the persisted schema rejects unknown root, binding, and rollback fields. Canonical, target, and
rollback-snapshot files are limited to 16 MiB and read twice through a no-follow descriptor.
Deployment-state enumeration and record opens are anchored to one no-follow directory descriptor;
the scan allows at most 128 entries, 256 KiB per record, and 4 MiB in aggregate. Device/inode,
metadata, bytes, canonical identity, and physical-root containment must remain stable; platforms
without the required descriptor-relative primitives fail closed. Shared state roots may hold
records for multiple target roots. Persisted destination and rollback paths must be non-empty,
NUL-free, absolute, and normalized before they can be resolved or reused. Existing rollback targets
survive no-op and update replans; recorded snapshots are required and hash-verified. Asset or
adapter ownership transfer fails closed until a separate, explicitly reviewed migration command
exists. Use isolated roots while this boundary is being proven; broad managed apply remains
deprecated and contained. This slice has no executor. Any future executor must repeat the same safe
reads and reverify every recorded plan hash immediately before mutation.

## Legacy managed mode

```bash
Expand Down
10 changes: 6 additions & 4 deletions docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ This roadmap tracks remaining product direction for `fclt`.
- Keep vendor integrations export-based and optional rather than adding credentials to core.
- Make renamed-source and unavailable-source recovery easier to understand.

4. Add a structured sync plan.
- Group writes, updates, removals, skips, conflicts, and repairs.
- Expose the same plan as JSON.
- Explain source refs and policy reasons.
4. Extend immutable per-asset deployment planning beyond the first Codex instruction/snippet slice.
- Keep planning read-only and exact-bound while adapters are added.
- Add an explicit destination ownership migration/transfer contract before allowing asset or
adapter claims to move.
- Build an apply executor only after transaction, approval, receipt, and recovery contracts exist.
- Keep deprecated broad managed mutation contained.

5. Improve project onboarding.
- Add a primary `fclt init project` flow.
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
"@clack/prompts": "^1.0.0",
"@opentui/core": "^0.1.75",
"jsonc-parser": "^3.3.1",
"unicode-case-folding": "1.1.1",
"yaml": "^2.8.2"
}
}
Loading
Loading