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
62 changes: 61 additions & 1 deletion docs/concepts/interaction-pattern-catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ Map P0/P1 catalog rows to canary archetypes before picking commands:
| Family | P0/P1 Pattern Coverage | Default Canary Archetypes | Trigger Surfaces | Minimum Useful Fixture | Failure Meaning |
| --- | --- | --- | --- | --- | --- |
| Work Routing | IP-001, IP-002, IP-003, IP-007, IP-008, IP-021, IP-029 | Hot-path route canary; Planning governance canary when cadence or repair is involved | `quota should-run`, `interaction_contract`, `work_lane_contract`, scheduler hint, handoff todo state | one eligible delivery fixture, one blocked/fallback fixture, one quiet or monitor fixture | agent turn routing is unsafe: it may spend, wait, notify, or choose fallback incorrectly |
| Human Decision | IP-004, IP-014, IP-017, IP-027 | Scoped decision canary; Product/readiness canary when first-screen human copy changes | user todos, decision scope, operator-gate/reward preview, deferred resume candidates | one concrete user ask, one scoped non-blocking gate, one preview-or-append dry run | humans may be asked the wrong question, or an agent may continue without the needed decision |
| Human Decision | IP-004, IP-014, IP-017, IP-027, IP-030 | Scoped decision canary; Product/readiness canary when first-screen human copy changes | user todos, decision scope, operator-gate/reward preview, deferred resume candidates | one concrete user ask, one scoped non-blocking gate, one preview-or-append dry run | humans may be asked the wrong question, or an agent may continue without the needed decision |
| State And Boundary | IP-005, IP-006, IP-011, IP-016, IP-019, IP-020, IP-022, IP-023, IP-025, IP-026, IP-028 | Projection and boundary canary; Hot-path route canary when the projection feeds quota/status | active state, todo metadata, task graph, authority source, claim lease, connector runtime policy, public/private scan | fixture state plus structured projection check; boundary scan for touched public files | compact state and executable truth diverge, so dashboards and agents may trust stale or unsafe authority |
| Evidence Lifecycle | IP-012, IP-015 | Evidence lifecycle canary; Product/readiness canary when evidence is rendered | external handle observation, benchmark lifecycle reducer, compact result projection | compact public-safe evidence fixture with raw-material exclusion assertions | progress evidence may be missing, double-counted, or represented with unsafe raw material |
| Planning Governance | IP-010, IP-013, IP-018, IP-024 | Planning governance canary; Hot-path route canary when cadence changes affect execution | stalled run history, autonomous replan obligation, repair delta, cadence hint, plan-to-todo writeback | two-turn stalled fixture plus repair/writeback delta assertion | the agent may keep planning in prose while the machine-visible frontier stays unchanged |
Expand Down Expand Up @@ -320,6 +320,7 @@ Human asks, approvals, interventions, and reward-derived lessons.
| P0 | IP-027 | Deferred Gate Resume | Status/quota plus controller | notify only when the resume gate is still user-held | keep deferred work visible after open lanes; when ready, require lifecycle replan instead of no-candidate wait |
| P0 | IP-014 | Decision Write Preview And Append | User/operator | explicit preview/apply decision | append only exact run-bound reward or gate decision event |
| P1 | IP-017 | User Reward Lesson Promotion | User plus LoopX | acknowledge only when lesson changes route/priority/boundary | promote correction into durable lesson, todo, or projection before continuing |
| P1 | IP-030 | Machine Configuration Preview And Revision-Guarded Apply | User plus agent | require explicit approval of the exact plan revision | preview the exact change, then apply, remove, or roll back only the matching revision |
| P2 | IP-009 | Active User Assistance | User simulator / operator | bounded intervention | inject audited user help without leaking reward/oracle signals |

### State And Boundary
Expand Down Expand Up @@ -1187,6 +1188,65 @@ main blocker or keeps following a stale local-only benchmark staging todo.
explicit operating lessons are projected into `recommended_action`,
active `Agent Todo`, or a state-projection repair warning.

#### IP-030 Machine Configuration Preview And Revision-Guarded Apply

**Trigger**

- a typed machine-configuration namespace is about to change; the built-in
namespaces are `change_quality_qualification`, `manager_runtime`,
`periodic_report`, `pull_request_review`, and `todo_replan_cadence`. The
public catalog returned by `loopx machine-config describe` is authoritative,
so this inventory has to stay complete rather than approximate;
- `pull_request_review` carries `review_priority`, which defaults to
`other-developers-first` and accepts `owner-first` as an explicit opt-in that
changes review ordering only;
- `loopx machine-config preview` returns a `plan_revision` for the exact
envelope, namespace patch, removal, or rollback that would be applied;
- a Goal-level override and a live machine default may both be in scope.

**Expected behavior**

The control plane separates the preview from the effect. `preview` computes the
exact resulting configuration and returns a `plan_revision` derived from that
plan identity. `apply`, `remove`, and `rollback` re-derive the plan and refuse to
write unless `--expected-plan-revision` still matches, so an owner decision is
bound to the exact revision that was shown. A namespace-scoped patch preserves
every sibling namespace; a whole-envelope write must name them explicitly. A
Goal override wins over the machine default, and clearing the override restores
the live machine default rather than a stale snapshot. Unknown namespaces,
unknown envelope fields, and private fields inside a public update fail closed
before any effect.

**Visual Model**

```mermaid
sequenceDiagram
participant U as User or operator
participant A as Agent
participant M as machine-config store
A->>M: preview exact change
M-->>A: plan_revision for the resulting plan
A->>U: show exact change and revision
U-->>A: approve that revision
A->>M: apply --expected-plan-revision --execute
M-->>A: applied, or rejected when the plan no longer matches
```

**Bad smell**

The agent applies a revision the owner never saw, or reuses a `plan_revision`
after another writer changed the plan, so the applied configuration no longer
matches what was previewed. A namespace patch is written as a whole envelope and
silently drops sibling namespaces, or a machine default replaces an explicit
Goal override instead of the override winning.

**Validation**

- `tests/capabilities/test_machine_configuration_contract.py`
- `tests/capabilities/test_machine_configuration_goal_defaults.py`
- `loopx machine-config preview` and `loopx machine-config apply --help` for the
exact `--expected-plan-revision` and `--execute` contract

#### IP-009 Active User Assistance

**Trigger**
Expand Down
20 changes: 20 additions & 0 deletions examples/interaction-pattern-catalog-smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,17 @@

from __future__ import annotations

import sys
from pathlib import Path


REPO_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO_ROOT))

from loopx.capabilities.machine_configuration.builtins import ( # noqa: E402
build_builtin_machine_configuration_registry,
)

CATALOG = REPO_ROOT / "docs" / "concepts" / "interaction-pattern-catalog.md"
STATE_MODEL = REPO_ROOT / "docs" / "state-interaction-model.md"
SELF_REPAIR_PATTERNS = (
Expand Down Expand Up @@ -157,6 +164,19 @@ def main() -> int:
source=SELF_REPAIR_PATTERNS,
)

# Every registered built-in machine-configuration namespace must be
# discoverable from the catalog, so a new capability cannot land as a
# silent omission in the IP-030 inventory.
registered_namespaces = sorted(
build_builtin_machine_configuration_registry().namespace_ids
)
undocumented = [ns for ns in registered_namespaces if ns not in catalog]
assert not undocumented, (
f"{CATALOG}: built-in machine-configuration namespaces missing from the "
f"catalog: {undocumented}; document them in IP-030 or record an explicit "
"intentional omission"
)

print("interaction-pattern-catalog-smoke: ok")
return 0

Expand Down