Skip to content
Open
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
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ fclt ai loop activity --project
fclt ai loop activity --project --json
fclt ai loop activity --all --json
fclt ai loop resolve <activity-action-locator> --json
fclt ai loop decide <activity-action-locator> --decision accept \
--expected-revision <n> --actor <id> --approval-ref <ref> --approve --json
fclt ai loop history --project --since 2026-01-01T00:00:00Z --json
```

Expand All @@ -219,6 +221,10 @@ report so later writeback edits cannot rewrite history.
Aggregate actionable items may carry an opaque locator. Resolution revalidates
the exact current scope and lifecycle revision and returns a plain-language
plan without guessing a root or performing a mutation.
For signal-family items, `loop decide` records one explicitly approved,
revision-bound `accept`, `redirect`, `reject`, or `defer` receipt. It writes
only machine-local decision history; canonical capability, Git, trackers,
proposals, tasks, and external systems remain unchanged.

Use `loop history` for a bounded multi-run timeline. It returns append-only
event lineage, opaque cross-scope identities, cursor pagination, and explicit
Expand Down
9 changes: 9 additions & 0 deletions assets/packs/facult-operating-model/instructions/EVOLUTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,12 @@ mutate an external tracker or automatically apply canonical changes. Treat
project auto-apply as plan-only until a hash-bound transaction, validation,
rollback, and durable receipt exist; keep global and plugin changes
proposal-only.

Signal-family decisions are a separate machine-local lifecycle. Resolve the
current opaque activity locator, then record `accept`, `redirect`, `reject`, or
`defer` only with explicit approval and the exact queue revision. The append-only
receipt preserves bounded work-unit context but does not apply capability,
mutate Git or an external tracker, spawn a task, or grant authority beyond the
recorded decision. Current-source completion may close already-landed families;
hold/defer remains visible and unimplemented. Treat coverage completeness and
cursor freshness as independent review facts.
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ fclt ai evolve apply EV-00001
fclt ai writeback link WB-00001 --issue TEAM-123
fclt ai writeback disposition WB-00001 --type task --target TEAM-123
fclt ai evolve verify EV-00001 --effectiveness improved --evidence test:post-apply
fclt ai loop activity --json
fclt ai loop resolve <activity-action-locator> --json
fclt ai loop decide <activity-action-locator> --decision accept \
--expected-revision <queue-revision> --actor <actor-id> \
--approval-ref <source-approval-ref> --approve --json
```

For an explicitly enabled scheduled loop, use:
Expand All @@ -69,6 +74,14 @@ check observed execution health. The loop may prepare writebacks and proposals,
but canonical apply remains plan-only and external task mutation remains a
separate approved integration.

For a signal-family activity item, resolve its opaque locator before recording
an operator decision. Record `accept`, `redirect`, `reject`, or `defer` only
with explicit source approval and the exact current queue revision. The receipt
is durable handoff evidence, not implementation authority: accepted work still
belongs in the external task/orchestration system, and fclt must not edit Git,
trackers, canonical capability, or spawn work on the receipt's behalf. Refresh
activity after any stale, replayed, moved-root, or duplicate-identity refusal.

The writeback queue alone cannot prove an empty window. Run configured source
reconciliation first and preserve its coverage, exclusions, correlations,
linked work, and dispositions. If any source is stale or unavailable, report a
Expand Down
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Start with [Writeback and evolution](./writeback-evolution.md) for the product's
- [Built-in pack](./built-in-pack.md): the packaged operating-model layer for writeback and evolution.
- [Built-in pack upgrades](./pack-upgrades.md): non-destructive refresh behavior for existing `.ai` roots.
- [Codex plugin](./codex-plugin.md): installable Codex skills and MCP tools for fclt workflows.
- [Activity action locators](./activity-action-locators.md): resolve one aggregate activity item to a verified current target without guessing roots or performing mutation.
- [Activity action locators](./activity-action-locators.md): resolve one aggregate activity item without guessing roots, then atomically record an explicitly approved signal-family decision without canonical or external mutation.
- [Managed mode](./managed-mode.md): when to let `fclt` write tool files, and how adoption works.
- [Security and trust](./security-trust.md): source trust, audit, secrets, and commit hygiene.
- [Automations](./automations.md): recurring Codex loops for learning review, evolution review, and tool-call audit.
Expand Down
65 changes: 54 additions & 11 deletions docs/activity-action-locators.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@ The CLI/JSON contract is authoritative:
```bash
fclt ai loop activity --json
fclt ai loop resolve <activity-action-locator> --json
fclt ai loop decide <activity-action-locator> \
--decision accept \
--expected-revision <queue-revision> \
--actor <actor-id> \
--approval-ref <source-approval-ref> \
--approve --json
```

The Codex plugin exposes the same read-only resolver as `fclt_registry` action
`activity_resolve`. Its input is exactly one `locator` string. It rejects
caller-supplied scope, cwd, root, path, argv, endpoint, token, token-env,
credential, approval, and mutation fields.
The Codex plugin exposes the read-only resolver as `fclt_registry` action
`activity_resolve` and the signal decision command as `activity_decide`. Both
use closed schemas. Neither accepts caller-supplied scope, cwd, root, path,
argv, endpoint, token, token-env, credential, or external mutation fields.

## Version 1 contract

Expand Down Expand Up @@ -79,13 +85,45 @@ A successful version 1 response returns:
- a plain-language plan
- an explicit statement that no mutation was performed
- an explicit `available: false` mutation state
- the requirements a future separate mutation command must satisfy: explicit
- the requirements the separate signal decision command must satisfy: explicit
approval and an atomic expected-binding revision check

The action classes are `review`, `decide`, `apply`, `verify`, and `handoff`.
They describe the safe next workflow class; they do not grant permission to
execute it.

## Signal decision lifecycle

`loop decide` records one decision for one currently issued signal-family
activity revision. It supports `accept`, `redirect`, `reject`, and `defer`.
The command requires all of these in one call:

- the unchanged opaque locator
- the exact current queue revision from resolution
- an explicit `--approve`
- a bounded actor identifier
- exactly one portable `--approval-ref` or bounded `--note`
- one `--redirect-target` only when the decision is `redirect`

fclt revalidates the locator, root identity, runtime identity, activity run,
queue revision, resource identity, and issued activity item under the
evolution-loop lock. It then atomically appends one machine-local version 1
receipt. Replaying the same binding is rejected. A later decision for the same
family requires a genuinely newer queue revision and advances the lifecycle
revision without rewriting prior history.

The durable receipt contains the exact opaque scope and signal-family id,
decision, actor, approval reference or note, previous and new lifecycle
revisions, activity run and queue revision, binding revision, and timestamp.
It contains no root or absolute private path. Accepted output also preserves
the activity item's bounded targets, evidence summary, linked work, expected
outcome, verification state, and next action so an external orchestrator can
construct a work unit.

Recording a decision does not edit canonical capability, update Git or a task
tracker, apply a proposal, spawn work, or grant implementation authority. In
particular, `accept` is a durable approval/handoff receipt, not execution.

## Fail-closed errors

| Code | Meaning | Recovery |
Expand All @@ -96,14 +134,19 @@ execute it.
| `stale_revision` | The activity run, queue revision, resource lifecycle, runtime identity, or allowed action class changed. | Refresh activity and resolve the new locator. |
| `duplicate_identity` | More than one verified current target matched. | Repair duplicate registration; fclt will not choose one. |
| `locator_not_issued` | Current state matches, but the current aggregate snapshot did not issue that locator. | Refresh activity and use only the returned locator. |
| `approval_required` | Explicit approval was omitted. | Obtain approval for the exact current signal and retry with `--approve`. |
| `invalid_decision_input` | Decision fields are malformed, unsafe, incompatible, or unbounded. | Use the closed command shape and one portable approval source. |
| `not_signal_family` | The locator identifies a proposal or coverage item. | Use the proposal lifecycle or source reconciliation instead. |
| `replayed_decision` | This binding or an equal/older queue revision already has a receipt. | Read the existing receipt or wait for a newer signal revision. |
| `malformed_history` | The bounded machine-local decision journal is corrupt or incompatible. | Inspect and repair that journal before retrying. |
| `decision_conflict` | The loop lock or journal changed during commit. | Refresh activity after the competing operation completes. |

## Mutation boundary

Resolution never reviews, accepts, rejects, applies, verifies, edits canonical
capability, writes project or tool-home files, changes workflow state, or
mutates an external system. Those operations remain separate closed commands.
Locator-bound mutation is withheld in version 1 because existing lifecycle
commands do not accept an expected locator binding revision. A consumer must
not translate a plan into those commands. A future mutation contract must
atomically require explicit approval and the expected current binding; a
locator alone is never mutation authority.
mutates an external system. Signal decision recording is the one narrow
locator-bound review mutation: it writes only the append-only machine-local
decision journal after explicit approval and stale-binding checks. Proposal
lifecycle, canonical apply, cross-scope mutation, task creation, Git, and
external systems remain separate and are never inferred from a locator.
19 changes: 18 additions & 1 deletion docs/codex-plugin-capability-matrix.json
Original file line number Diff line number Diff line change
Expand Up @@ -772,10 +772,27 @@
"risk": "read_only",
"scope": "verified machine-local Global or project runtime identity selected only by the locator",
"preview": "revalidates the latest activity run, queue revision, current resource lifecycle, project/runtime identity, and allowed action class before returning a plain-language plan",
"apply": "withheld; version 1 exposes no locator-bound mutation because existing lifecycle commands do not accept the expected locator binding revision",
"apply": "resolution remains read-only; signal-family decisions use the separate activity_decide contract with explicit approval and expected revision",
"rollback": "not_applicable; resolution performs zero canonical, tool-home, project, workflow, or external mutation",
"verification": "no-write snapshots, duplicate-id and duplicate-worktree isolation, cross-scope replay refusal, moved-root and missing-state refusal, stale lifecycle/run rejection, incompatible-version rejection, raw-field exclusion, and published typed-tool discovery"
},
{
"id": "evolution_loop.activity_decision_lifecycle",
"cli": "ai loop decide <activity-action-locator> --decision <accept|redirect|reject|defer> --expected-revision <n> --actor <id> (--approval-ref <ref>|--note <text>) --approve --json",
"cliAvailability": "available",
"mcp": {
"disposition": "exposed",
"tool": "fclt_registry",
"action": "activity_decide",
"reason": "the closed router accepts one issued locator, one decision, the exact expected queue revision, explicit approval, a bounded actor, and exactly one portable approval source"
},
"risk": "review_producing",
"scope": "verified machine-local Global or project runtime identity selected only by the locator",
"preview": "use activity_resolve and the current activity item before deciding; the decision command revalidates all bindings under the evolution-loop lock",
"apply": "atomically appends one machine-local signal decision receipt; canonical capability, Git, trackers, tasks, proposals, and external systems are unchanged",
"rollback": "append-only history is retained; a later decision requires a genuinely newer signal revision and cannot rewrite prior approval evidence",
"verification": "accept, redirect, reject, and defer receipts; stale and replay refusal; malformed history and unsafe input refusal; duplicate identity, moved-root, cross-scope, and non-signal refusal; bounded accepted work-unit output; no canonical or external mutation"
},
{
"id": "autosync.mutation",
"cli": "autosync status|cleanup|uninstall|run --once",
Expand Down
10 changes: 9 additions & 1 deletion docs/codex-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ The plugin exposes:
- `fclt_sync`: managed-state inspection and dry-run sync preview
- `fclt_registry`: source search/verification, strict-trust install/update preview,
bounded reconciliation status/review through a closed scope/window/source-id schema,
and read-only resolution of one opaque activity action locator
read-only resolution of one opaque activity action locator, and atomic
recording of one revision-bound signal-family decision
- `fclt_audit`: structured, redacted, non-interactive security audit with zero report or index writes
- `fclt_automation`: read-only autosync status plus scheduled evolution-loop status and preview
- `fclt_status`
Expand All @@ -53,6 +54,13 @@ trust-policy mutation, destructive migration, and background-service mutation
remain deliberately withheld until their CLI APIs provide transaction-safe
preview, precondition, verification, and rollback contracts.

`fclt_registry` action `activity_decide` is a narrow review-producing
exception to the otherwise read-only registry surface. It requires one issued
locator, `accept|redirect|reject|defer`, the exact expected queue revision, a
bounded actor, exactly one approval reference or note, and `approve: true`.
It records only a machine-local receipt. It cannot select a root, mutate
canonical capability or external systems, apply proposals, or spawn tasks.

The evolution-loop actions exposed through `fclt_automation` are
`loop_status`, `loop_activity`, and `loop_preview`. `loop_activity` defaults to
`all` and returns one portable activity set across Global and every configured
Expand Down
10 changes: 10 additions & 0 deletions docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ fclt ai loop disable [--dry-run] [--json]
fclt ai loop status [--json]
fclt ai loop activity [--all|--global|--project] [--json]
fclt ai loop resolve <activity-action-locator> [--json]
fclt ai loop decide <activity-action-locator> --decision <accept|redirect|reject|defer> --expected-revision <n> --actor <id> (--approval-ref <ref>|--note <text>) [--redirect-target <target>] --approve [--json]
fclt ai loop history [--all|--global|--project] [--since <date>] [--until <date>] [--item <id>] [--scope-id <opaque-id>] [--event <type>] [--limit <1-200>] [--cursor <cursor>] [--json]
fclt ai loop run [--since <date>] [--until <date>] [--source <id>] [--dry-run] [--scheduled] [--json]
```
Expand Down Expand Up @@ -205,6 +206,15 @@ Older or non-actionable items without a locator remain handoff-only. See
[Activity action locators](./activity-action-locators.md) for versioning and
error semantics.

For a current signal-family item, `loop decide` atomically records an explicit
`accept`, `redirect`, `reject`, or `defer` receipt in machine-local history. It
accepts no root or scope flag and requires the exact expected queue revision,
explicit approval, a bounded actor, and exactly one approval reference or
note. The command revalidates the locator under the loop lock, refuses stale or
replayed bindings, and performs no canonical, Git, tracker, proposal-apply, or
task-spawn mutation. Accepted JSON preserves bounded work-unit context for a
separate orchestrator.

`loop history` is the bounded version 1 multi-run timeline and lineage
contract. It stores immutable per-run event segments in machine-local runtime
state and returns delta events rather than copying current activity items.
Expand Down
14 changes: 14 additions & 0 deletions docs/writeback-evolution.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,13 @@ Actionable items may include an opaque `actionLocator`. Resolve it with
`fclt ai loop resolve <locator> --json` to obtain a read-only plan for the
verified current scope and resource. Missing locators remain handoff-only;
consumers must never infer roots from scope labels or internal ids.
After resolving a current signal family, record an explicitly approved
decision with `fclt ai loop decide <locator> --decision
<accept|redirect|reject|defer> --expected-revision <n> --actor <id>
(--approval-ref <ref>|--note <text>) --approve --json`. This appends one
revisioned machine-local receipt and does not implement the decision. Accepted
output carries bounded target, evidence, linked-work, expected-outcome,
verification, and next-action fields for an external work-unit orchestrator.
Each item also identifies its global or project context, typed capability
targets such as an instruction, skill, prompt, or automation, the reason for
the decision, and bounded HTTP(S) evidence links when the source supplied one.
Expand All @@ -289,6 +296,13 @@ or unavailable sources remain visible. A complete empty run means configured
coverage was checked; degraded or failed empty runs never claim that nothing is
pending.

Coverage completeness and source cursor freshness remain independent. A
complete review can still report one or more stale cursors, and each stale
cursor remains visible as its own coverage activity item. Current-source
terminal work or exact default-branch containment resolves a previously open
family; an explicit hold/defer remains unresolved and is never materialized as
implementation.

## Evolution

Review accumulated signal:
Expand Down
Loading
Loading