feat(handoffs): publish owner task interfaces

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a023c0-a0a3-7c03-b395-5a0d2757214d
This commit is contained in:
tegwick 2026-08-22 14:15:48 +02:00
parent a3952113d5
commit 890f3b05b5
12 changed files with 754 additions and 38 deletions

View file

@ -17,7 +17,7 @@
| workplan | RMGR-WP-0007 | finished | — | workplans/RMGR-WP-0007-greenfield-rapp-wrap-efficiency.md | | workplan | RMGR-WP-0007 | finished | — | workplans/RMGR-WP-0007-greenfield-rapp-wrap-efficiency.md |
| workplan | RMGR-WP-0008 | finished | — | workplans/RMGR-WP-0008-work-record-and-register-receiving-surface.md | | workplan | RMGR-WP-0008 | finished | — | workplans/RMGR-WP-0008-work-record-and-register-receiving-surface.md |
| workplan | RMGR-WP-0009 | finished | — | workplans/RMGR-WP-0009-coding-assistant-commit-provenance.md | | workplan | RMGR-WP-0009 | finished | — | workplans/RMGR-WP-0009-coding-assistant-commit-provenance.md |
| workplan | RMGR-WP-0010 | active | — | workplans/RMGR-WP-0010-authoritative-workload-references.md | | workplan | RMGR-WP-0010 | finished | — | workplans/RMGR-WP-0010-authoritative-workload-references.md |
| task | RMGR-WP-0001-T01 | done | — | workplans/RMGR-WP-0001-foundation.md | | task | RMGR-WP-0001-T01 | done | — | workplans/RMGR-WP-0001-foundation.md |
| task | RMGR-WP-0001-T02 | done | — | workplans/RMGR-WP-0001-foundation.md | | task | RMGR-WP-0001-T02 | done | — | workplans/RMGR-WP-0001-foundation.md |
| task | RMGR-WP-0001-T03 | done | — | workplans/RMGR-WP-0001-foundation.md | | task | RMGR-WP-0001-T03 | done | — | workplans/RMGR-WP-0001-foundation.md |
@ -83,9 +83,9 @@
| task | RMGR-WP-0010-T01 | done | — | workplans/RMGR-WP-0010-authoritative-workload-references.md | | task | RMGR-WP-0010-T01 | done | — | workplans/RMGR-WP-0010-authoritative-workload-references.md |
| task | RMGR-WP-0010-T02 | done | — | workplans/RMGR-WP-0010-authoritative-workload-references.md | | task | RMGR-WP-0010-T02 | done | — | workplans/RMGR-WP-0010-authoritative-workload-references.md |
| task | RMGR-WP-0010-T03 | done | — | workplans/RMGR-WP-0010-authoritative-workload-references.md | | task | RMGR-WP-0010-T03 | done | — | workplans/RMGR-WP-0010-authoritative-workload-references.md |
| task | RMGR-WP-0010-T04 | wait | — | workplans/RMGR-WP-0010-authoritative-workload-references.md | | task | RMGR-WP-0010-T04 | done | — | workplans/RMGR-WP-0010-authoritative-workload-references.md |
| task | RMGR-WP-0010-T05 | wait | — | workplans/RMGR-WP-0010-authoritative-workload-references.md | | task | RMGR-WP-0010-T05 | done | — | workplans/RMGR-WP-0010-authoritative-workload-references.md |
| task | RMGR-WP-0010-T06 | wait | — | workplans/RMGR-WP-0010-authoritative-workload-references.md | | task | RMGR-WP-0010-T06 | done | — | workplans/RMGR-WP-0010-authoritative-workload-references.md |
| task | RMGR-WP-0010-T07 | wait | — | workplans/RMGR-WP-0010-authoritative-workload-references.md | | task | RMGR-WP-0010-T07 | done | — | workplans/RMGR-WP-0010-authoritative-workload-references.md |
| intake | RMGR-IN-0001 | open | — | intakes/intakes.md | | intake | RMGR-IN-0001 | open | — | intakes/intakes.md |
| intake | RMGR-IN-0002 | open | — | intakes/intakes.md | | intake | RMGR-IN-0002 | open | — | intakes/intakes.md |

View file

@ -0,0 +1,70 @@
---
id: RMGR-ADR-005
type: architecture-decision-record
title: "Owner-task interfaces for cross-repository adoption"
status: accepted
decided: "2026-08-22"
deciders: ["Bernd Worsch", "repo-manager"]
related:
- RMGR-WP-0010
- docs/owner-task-interface-contract_v1.md
- canon-work-record-types
---
# ADR-005: Owner-task interfaces for cross-repository adoption
## Status
**Accepted** (2026-08-22).
## Context
A producer can identify work that belongs in another repository before the
owner has created a task for it. Sending only a prose request makes the next
coding agent reconstruct the objective, inputs, constraints, and acceptance
criteria. Keeping a duplicate waiting task in the producer workplan then makes
two agents carry one todo.
The fleet work-record registry is deliberately closed. An interface offer must
therefore not become a new task-like lifecycle or a second backlog.
## Decision
1. A producer may publish an `OwnerTaskInterface`: a versioned, immutable
proposal containing the complete owner-ready objective, authoritative
inputs, deliverables, constraints, acceptance criteria, and verification.
2. The interface is not a work record. It has no assignee or lifecycle status
and does not replace the target owner's workplan/task/decision.
3. The target owner records `approved`, `amended`, or `rejected` in its own
authoritative work record. Approval cites the interface id and exact Git
revision. An amendment records the delta rather than silently changing the
imported meaning.
4. Once the producer publishes and routes a complete interface, its handoff
task is done. Adoption and implementation are tracked only in the target
owner's work record; the producer does not retain a duplicate todo.
5. Dependencies that still block producer-owned implementation remain normal
producer tasks. The interface pattern is only for work whose implementation
authority has crossed the repository boundary.
6. Interfaces contain no credentials, secret values, mutable environment
state, or copied authority. They reference authoritative contracts and
evidence by stable path/id and revision.
## Consequences
- Owners can approve and use the supplied task specification directly.
- Later agents do not need to recover intent from messages or re-plan the work.
- Owner amendments stay explicit and auditable.
- Work queues contain one implementation todo, in the repository that can
actually complete it.
- Messages become routing notifications; they are not the only copy of the
implementation contract.
## Rejected alternatives
- **Duplicate tasks in producer and consumer workplans.** They drift and need
manual closure coordination.
- **Prose-only messages.** They are useful routing evidence but too weak to be
an executable interface.
- **A new `handoff-task` work-record kind.** The existing task, intake, and
decision kinds already own lifecycle; adding another would create a parallel
backlog ontology.

View file

@ -0,0 +1,92 @@
---
id: RMGR-CONTRACT-OWNER-TASK-INTERFACE-0001
type: contract
title: "Owner-task interface contract"
version: "1"
status: active
created: "2026-08-22"
updated: "2026-08-22"
related:
- RMGR-ADR-005
- RMGR-WP-0010
---
# Owner-task interface contract v1
An owner-task interface is a complete proposal that another repository can
approve and adopt by reference. It transports implementation intent, not task
lifecycle.
## Required shape
```yaml
apiVersion: helixforge.repo-manager/v1
kind: OwnerTaskInterface
metadata:
id: helixforge.example.consumer-port.v1
title: Adopt the example consumer port
source:
repo: producing-repo
workplan_task: PRODUCER-WP-0001-T04
target:
repo: consuming-repo
owner_agent: consuming-repo
approval:
dispositions: [approved, amended, rejected]
record_in: target owner work record
task:
title: Adopt the example consumer port
priority: medium
objective: Consume the producer contract without copying its authority.
inputs:
- ref: producing-repo/docs/example-contract_v1.md
authority: producing-repo
deliverables:
- Implement the consumer adapter.
constraints:
- Do not infer missing identity.
acceptance:
- A contract fixture passes through the consumer boundary.
verification:
- make test
```
`inputs`, `constraints`, and `verification` are optional. The objective,
deliverables, and acceptance criteria are mandatory and owner-ready.
## Approval and adoption
The target owner records one disposition in its existing workplan task or
decision:
```yaml
interface_id: helixforge.example.consumer-port.v1
source_revision: <Git commit containing the interface>
disposition: approved # approved | amended | rejected
```
This may be prose or structured metadata according to the target repository's
existing convention. `amended` must cite the delta. The target task remains the
only lifecycle-bearing implementation record.
The source task is complete after the validated interface is committed and its
owner is notified. A later producer task is warranted only if an approved
amendment requires producer-side changes.
## Discovery
```bash
rmgr owner-interface validate --path interfaces
rmgr owner-interface validate --path interfaces --owner ops-warden
```
The command validates all interface files before returning their content. An
owner filter matches either `target.repo` or `target.owner_agent`.
## Authority and safety
- The Git revision plus `metadata.id` pins the offered meaning.
- Referenced records remain authoritative in their source repositories.
- Interface files never contain secrets or mutable runtime observations.
- An interface must not contain `status`, State Hub ids, or an assignee: those
would turn it into an unregistered work-record lifecycle.

View file

@ -0,0 +1,49 @@
apiVersion: helixforge.repo-manager/v1
kind: OwnerTaskInterface
metadata:
id: helixforge.workloads.ops-warden-reference.v1
title: Add explicit workload references to ops-warden lanes
source:
repo: repo-manager
workplan_task: RMGR-WP-0010-T06
target:
repo: ops-warden
owner_agent: ops-warden
suggested_work_record: WARDEN-WP-0032
approval:
dispositions: [approved, amended, rejected]
record_in: WARDEN-WP-0032 task or an ops-warden owner decision
task:
title: Adopt explicit workload references in the lane catalog
priority: high
objective: >-
Let workload-applicable lanes point to authoritative rapp workload identity
while keeping the catalog a pointer layer.
inputs:
- ref: repo-manager/docs/workload-reference-contract_v1.md
authority: repo-manager
- ref: ops-warden/registry/routing/catalog.yaml
authority: ops-warden
deliverables:
- >-
Add workload_ref with required rapp_id and name and optional deployable to
every workload-applicable lane.
- >-
Add an explicit applicability representation that distinguishes
not-applicable from an unresolved or invalid workload reference.
- Validate every supplied reference through Repo Manager exact resolution.
- Preserve native typed identity for lanes that do not represent workloads.
constraints:
- Do not copy workload classification, criticality, readiness, or placement into the catalog.
- Do not infer workload identity from path_template, owner_repo, or repository names.
- An absent pointer must not ambiguously mean both unknown and not-applicable.
acceptance:
- Every workload-applicable lane resolves exactly or reports unknown with a reason.
- Every non-workload lane is explicitly not-applicable.
- Catalog validation fails on malformed, ambiguous, or undeclared references.
- Existing lane identity and routing authority remain owned by ops-warden.
verification:
- make test
- make lint
- >-
uv run --project /home/worsch/repo-manager rmgr workload index --root /home/worsch

View file

@ -0,0 +1,50 @@
apiVersion: helixforge.repo-manager/v1
kind: OwnerTaskInterface
metadata:
id: helixforge.workloads.rapp-coverage.v1
title: Clarify universal rapp coverage for managed deployables
source:
repo: repo-manager
workplan_task: RMGR-WP-0010-T05
target:
repo: railiance-master
owner_agent: railiance-master
suggested_work_record: owner-selected Railiance Master schema workplan task
approval:
dispositions: [approved, amended, rejected]
record_in: Railiance Master file-backed workplan task or decision
task:
title: Clarify universal rapp coverage for managed deployables
priority: high
objective: >-
Make the normative rapp contract explicit that every managed running
deployable, including operational and tooling workloads participating in
controls, belongs to exactly one rapp.
inputs:
- ref: railiance-master/docs/adr/ADR-0007-rapp-declaration-contract.md
authority: railiance-master
- ref: repo-manager/docs/adr-004-authoritative-workload-declarations.md
authority: repo-manager boundary ruling
deliverables:
- >-
Amend or clarify ADR-0007 and the rapp authoring guide with universal
managed-deployable coverage.
- >-
State that a pre-rapp running deployable is migration debt and remains
unknown to workload controls until declared.
- >-
Preserve native identity for human access, credential patterns, broker
actions, one-shot operations, and infrastructure resources that are not workloads.
- Keep Railiance Master as the sole owner of the normative rapp schema vocabulary.
constraints:
- Do not create a parallel generic workload declaration surface.
- Do not require one rapp per process when deployables share rollout and rollback fate.
- Do not turn non-workload operational subjects into fake workloads.
acceptance:
- Normative documentation answers whether operational and tooling deployables require rapps.
- The exactly-one-rapp invariant remains explicit and schema-compatible.
- Migration debt and not-applicable subjects are distinguishable.
- Existing valid rapp declarations continue to validate.
verification:
- tools/validate-family-declarations.py --repo /home/worsch/rapp-issue-core
- tools/validate-family-declarations.py --repo /home/worsch/rapp-qonto

View file

@ -0,0 +1,47 @@
apiVersion: helixforge.repo-manager/v1
kind: OwnerTaskInterface
metadata:
id: helixforge.workloads.projection-transport.v1
title: Transport the authoritative workload projection
source:
repo: repo-manager
workplan_task: RMGR-WP-0010-T04
target:
repo: hub-core
owner_agent: hub-core
suggested_work_record: owner-selected hub-core projection workplan task
approval:
dispositions: [approved, amended, rejected]
record_in: hub-core file-backed workplan task or decision
task:
title: Transport the Repo Manager workload projection
priority: medium
objective: >-
Add a hub-core projection port for Repo Manager workload records without
transferring semantic authority or exposing Repo Manager persistence.
inputs:
- ref: repo-manager/docs/workload-reference-contract_v1.md
authority: repo-manager
- ref: repo-manager/src/repo_manager/workloads.py
authority: repo-manager
deliverables:
- >-
Ingest normalized workload records keyed by rapp_id and
workload_identity.name, with optional deployable membership.
- >-
Retain source repository, declaration path, source Git revision, and a
canonical UTC observation timestamp.
- Expose read-only cross-repository query through the existing projection port.
- Make the projection rebuildable from authoritative declarations.
constraints:
- hub-core transports and queries the projection but does not own workload semantics.
- Do not expose or depend on Repo Manager private persistence models.
- Do not infer workload identity from repository names or paths.
acceptance:
- A nine-declaration Repo Manager fixture can be ingested and queried by exact reference.
- Deleting and rebuilding the projection from source yields equivalent records.
- Unknown references remain unknown and are not repaired by aliases or path parsing.
- All observation timestamps are canonical UTC.
verification:
- make test
- make conformance

View file

@ -0,0 +1,49 @@
apiVersion: helixforge.repo-manager/v1
kind: OwnerTaskInterface
metadata:
id: helixforge.workloads.zone-engine-resolution.v1
title: Consume explicit workload references without inference
source:
repo: repo-manager
workplan_task: RMGR-WP-0010-T07
target:
repo: zone-engine
owner_agent: zone-engine
suggested_work_record: ZONE-WP-0001-T07
approval:
dispositions: [approved, amended, rejected]
record_in: ZONE-WP-0001-T07 or a Zone Engine owner decision
task:
title: Prove Zone Engine workload resolution without inference
priority: high
objective: >-
Join ops-warden lane pointers to authoritative Repo Manager workload
projections and expose unresolved workload identity without guessing.
inputs:
- ref: repo-manager/docs/workload-reference-contract_v1.md
authority: repo-manager
- ref: helixforge.workloads.ops-warden-reference.v1
authority: ops-warden after approval
- ref: zone-engine/docs/security-zones_v0.1.md
authority: zone-engine draft pending canon adoption
deliverables:
- Consume exact rapp_id and workload name pairs plus optional deployable.
- Preserve resolved, unknown, and owner-asserted not-applicable as distinct states.
- Join authoritative projection data to explicit catalog references only.
- Emit evidence that name and path drift cannot change zone membership.
constraints:
- Do not parse repository slugs, owner_repo, credential paths, or path templates as identity.
- Unknown must fail closed wherever zone policy requires workload identity.
- Zone Engine does not author workload identity or ops-warden lane pointers.
acceptance:
- A valid exact reference resolves to one authoritative workload projection.
- A mismatched qonto versus rapp-qonto name remains unknown.
- A non-workload lane remains not-applicable rather than becoming unknown.
- No fallback identity path exists in implementation or fixtures.
verification:
- >-
uv run --project /home/worsch/repo-manager rmgr workload resolve --root
/home/worsch --rapp-id rapp-issue-core --name issue-core --deployable issue-core
- >-
uv run --project /home/worsch/repo-manager rmgr workload resolve --root
/home/worsch --rapp-id rapp-qonto --name rapp-qonto

View file

@ -0,0 +1,72 @@
$schema: https://json-schema.org/draft/2020-12/schema
$id: https://helixforge.local/repo-manager/owner-task-interface.schema.yaml
title: HelixForge owner-task interface
type: object
additionalProperties: false
required: [apiVersion, kind, metadata, source, target, approval, task]
properties:
apiVersion:
const: helixforge.repo-manager/v1
kind:
const: OwnerTaskInterface
metadata:
type: object
additionalProperties: false
required: [id, title]
properties:
id: {type: string, minLength: 1}
title: {type: string, minLength: 1}
source:
type: object
additionalProperties: false
required: [repo, workplan_task]
properties:
repo: {type: string, minLength: 1}
workplan_task: {type: string, minLength: 1}
target:
type: object
additionalProperties: false
required: [repo, owner_agent]
properties:
repo: {type: string, minLength: 1}
owner_agent: {type: string, minLength: 1}
suggested_work_record: {type: string, minLength: 1}
approval:
type: object
additionalProperties: false
required: [dispositions, record_in]
properties:
dispositions:
const: [approved, amended, rejected]
record_in: {type: string, minLength: 1}
task:
type: object
additionalProperties: false
required: [title, priority, objective, deliverables, acceptance]
properties:
title: {type: string, minLength: 1}
priority: {enum: [high, medium, low]}
objective: {type: string, minLength: 1}
inputs:
type: array
items:
type: object
additionalProperties: false
required: [ref, authority]
properties:
ref: {type: string, minLength: 1}
authority: {type: string, minLength: 1}
deliverables:
type: array
minItems: 1
items: {type: string, minLength: 1}
constraints:
type: array
items: {type: string, minLength: 1}
acceptance:
type: array
minItems: 1
items: {type: string, minLength: 1}
verification:
type: array
items: {type: string, minLength: 1}

View file

@ -382,6 +382,21 @@ def main(argv: list[str] | None = None) -> int:
p_workload_resolve.add_argument("--name", required=True) p_workload_resolve.add_argument("--name", required=True)
p_workload_resolve.add_argument("--deployable", default=None) p_workload_resolve.add_argument("--deployable", default=None)
p_owner_interface = sub.add_parser(
"owner-interface",
help="Inspect validated owner-consumable task interfaces",
)
owner_interface_sub = p_owner_interface.add_subparsers(dest="owner_interface_command")
p_owner_interface_validate = owner_interface_sub.add_parser(
"validate", help="Validate and return owner task interfaces"
)
p_owner_interface_validate.add_argument(
"--path", default="interfaces", help="One interface YAML or an interface directory"
)
p_owner_interface_validate.add_argument(
"--owner", default=None, help="Return interfaces for this target repo or owner agent"
)
args = parser.parse_args(argv) args = parser.parse_args(argv)
if args.version or args.command in (None, "version"): if args.version or args.command in (None, "version"):
@ -847,6 +862,16 @@ def main(argv: list[str] | None = None) -> int:
print(json.dumps(result, indent=2)) print(json.dumps(result, indent=2))
return 0 if result.get("ok") else 1 return 0 if result.get("ok") else 1
if args.command == "owner-interface":
if not args.owner_interface_command:
p_owner_interface.print_help()
return 2
from repo_manager.owner_interfaces import validate_owner_interfaces
result = validate_owner_interfaces(Path(args.path), owner=args.owner)
print(json.dumps(result, indent=2))
return 0 if result.get("ok") else 1
parser.print_help() parser.print_help()
return 0 return 0

View file

@ -0,0 +1,177 @@
"""Validation and rendering for owner-consumable task interfaces."""
from __future__ import annotations
from pathlib import Path
from typing import Any
import yaml
API_VERSION = "helixforge.repo-manager/v1"
KIND = "OwnerTaskInterface"
DISPOSITIONS = ("approved", "amended", "rejected")
PRIORITIES = frozenset({"high", "medium", "low"})
def _error(code: str, path: Path, message: str) -> dict[str, str]:
return {"code": code, "path": str(path), "message": message}
def _text(value: Any) -> str | None:
if not isinstance(value, str):
return None
value = value.strip()
return value or None
def _string_list(value: Any) -> list[str] | None:
if not isinstance(value, list) or not value:
return None
values = [_text(item) for item in value]
if any(item is None for item in values):
return None
return [item for item in values if item is not None]
def _interface_paths(path: Path) -> list[Path]:
path = path.expanduser().resolve()
if path.is_file():
return [path]
return sorted(path.glob("*.yaml"))
def validate_owner_interfaces(path: Path, *, owner: str | None = None) -> dict[str, Any]:
"""Validate task interfaces and return their directly consumable content."""
path = path.expanduser().resolve()
errors: list[dict[str, str]] = []
interfaces: list[dict[str, Any]] = []
seen_ids: set[str] = set()
paths = _interface_paths(path)
if not paths:
errors.append(_error("interface_not_found", path, "no interface YAML files found"))
for interface_path in paths:
try:
raw = yaml.safe_load(interface_path.read_text(encoding="utf-8")) or {}
except (OSError, yaml.YAMLError) as exc:
errors.append(_error("interface_invalid", interface_path, str(exc)))
continue
if not isinstance(raw, dict):
errors.append(_error("interface_invalid", interface_path, "root must be a mapping"))
continue
if raw.get("apiVersion") != API_VERSION or raw.get("kind") != KIND:
errors.append(
_error(
"interface_kind_invalid",
interface_path,
f"expected apiVersion {API_VERSION!r} and kind {KIND!r}",
)
)
continue
metadata = raw.get("metadata")
source = raw.get("source")
target = raw.get("target")
approval = raw.get("approval")
task = raw.get("task")
if not all(isinstance(item, dict) for item in (metadata, source, target, approval, task)):
errors.append(
_error(
"interface_shape_invalid",
interface_path,
"metadata, source, target, approval, and task must be mappings",
)
)
continue
interface_id = _text(metadata.get("id"))
title = _text(metadata.get("title"))
source_repo = _text(source.get("repo"))
source_task = _text(source.get("workplan_task"))
target_repo = _text(target.get("repo"))
owner_agent = _text(target.get("owner_agent"))
task_title = _text(task.get("title"))
objective = _text(task.get("objective"))
priority = _text(task.get("priority"))
deliverables = _string_list(task.get("deliverables"))
acceptance = _string_list(task.get("acceptance"))
dispositions = approval.get("dispositions")
required = {
"metadata.id": interface_id,
"metadata.title": title,
"source.repo": source_repo,
"source.workplan_task": source_task,
"target.repo": target_repo,
"target.owner_agent": owner_agent,
"task.title": task_title,
"task.objective": objective,
}
missing = [name for name, value in required.items() if value is None]
if missing:
errors.append(
_error(
"interface_required_field_missing",
interface_path,
"missing non-empty fields: " + ", ".join(missing),
)
)
continue
if priority not in PRIORITIES:
errors.append(
_error(
"interface_priority_invalid",
interface_path,
"task.priority must be high, medium, or low",
)
)
continue
if deliverables is None or acceptance is None:
errors.append(
_error(
"interface_task_invalid",
interface_path,
"task.deliverables and task.acceptance must be non-empty string lists",
)
)
continue
if dispositions != list(DISPOSITIONS):
errors.append(
_error(
"interface_approval_invalid",
interface_path,
"approval.dispositions must be [approved, amended, rejected]",
)
)
continue
if "status" in raw or "status" in metadata:
errors.append(
_error(
"interface_lifecycle_forbidden",
interface_path,
"an interface is not a work record and must not carry lifecycle status",
)
)
continue
if interface_id in seen_ids:
errors.append(
_error("interface_id_duplicate", interface_path, f"duplicate id {interface_id!r}")
)
continue
seen_ids.add(interface_id)
if owner is None or owner in {target_repo, owner_agent}:
document = dict(raw)
document["path"] = str(interface_path)
interfaces.append(document)
return {
"ok": not errors,
"apiVersion": API_VERSION,
"kind": KIND,
"root": str(path),
"interface_count": len(interfaces),
"interfaces": interfaces,
"errors": errors,
}

View file

@ -0,0 +1,74 @@
from __future__ import annotations
from pathlib import Path
from repo_manager.owner_interfaces import validate_owner_interfaces
def _write_interface(path: Path, *, interface_id: str = "example.port.v1") -> None:
path.write_text(
f"""apiVersion: helixforge.repo-manager/v1
kind: OwnerTaskInterface
metadata:
id: {interface_id}
title: Example port
source:
repo: repo-manager
workplan_task: RMGR-WP-0010-T04
target:
repo: hub-core
owner_agent: hub-core
approval:
dispositions: [approved, amended, rejected]
record_in: target owner work record
task:
title: Adopt the example port
priority: medium
objective: Consume the published contract without copying its authority.
deliverables:
- Add the consumer port.
acceptance:
- Prove an authoritative record can be consumed.
""",
encoding="utf-8",
)
def test_validates_and_filters_owner_consumable_interface(tmp_path: Path) -> None:
_write_interface(tmp_path / "example.yaml")
result = validate_owner_interfaces(tmp_path, owner="hub-core")
assert result["ok"] is True
assert result["interface_count"] == 1
assert result["interfaces"][0]["metadata"]["id"] == "example.port.v1"
def test_valid_interface_for_another_owner_is_not_returned(tmp_path: Path) -> None:
_write_interface(tmp_path / "example.yaml")
result = validate_owner_interfaces(tmp_path, owner="ops-warden")
assert result["ok"] is True
assert result["interfaces"] == []
def test_rejects_lifecycle_status_because_interface_is_not_work_record(tmp_path: Path) -> None:
path = tmp_path / "example.yaml"
_write_interface(path)
path.write_text(path.read_text(encoding="utf-8") + "status: wait\n", encoding="utf-8")
result = validate_owner_interfaces(path)
assert result["ok"] is False
assert result["errors"][0]["code"] == "interface_lifecycle_forbidden"
def test_rejects_duplicate_interface_ids(tmp_path: Path) -> None:
_write_interface(tmp_path / "one.yaml")
_write_interface(tmp_path / "two.yaml")
result = validate_owner_interfaces(tmp_path)
assert result["ok"] is False
assert result["errors"][0]["code"] == "interface_id_duplicate"

View file

@ -4,7 +4,7 @@ type: workplan
title: "Authoritative workload declarations and explicit references" title: "Authoritative workload declarations and explicit references"
domain: infotech domain: infotech
repo: repo-manager repo: repo-manager
status: active status: finished
owner: codex owner: codex
topic_slug: infotech topic_slug: infotech
created: "2026-08-22" created: "2026-08-22"
@ -13,6 +13,7 @@ related:
- ZONE-WP-0001 - ZONE-WP-0001
- RMASTER-ADR-0007 - RMASTER-ADR-0007
- WARDEN-WP-0032 - WARDEN-WP-0032
- RMGR-ADR-005
state_hub_workstream_id: "f1fdfd70-76e0-5133-8365-4e68b9e9ca12" state_hub_workstream_id: "f1fdfd70-76e0-5133-8365-4e68b9e9ca12"
--- ---
@ -73,70 +74,80 @@ declarations, rejects duplicate deployable ownership, reports missing rapp
declarations, and returns `unknown` rather than guessing. Unit tests cover declarations, and returns `unknown` rather than guessing. Unit tests cover
positive resolution and fail-closed cases. positive resolution and fail-closed cases.
## Publish the normalized projection port ## Publish the normalized projection owner interface
```task ```task
id: RMGR-WP-0010-T04 id: RMGR-WP-0010-T04
status: wait status: done
priority: medium priority: medium
state_hub_task_id: "187fed63-63ab-57b3-92cb-83acf5870977" state_hub_task_id: "187fed63-63ab-57b3-92cb-83acf5870977"
``` ```
Expose the v1 index through the Repo Manager observation contract and hub-core Supply hub-core with a directly adoptable task interface for the v1 projection,
port with source revision, declaration path, and observation timestamp. Do not including provenance, canonical UTC observation time, rebuild semantics, and
expose private persistence models. the private-persistence boundary.
**Handoff (2026-08-22):** sent hub-core message **Result (2026-08-22):**
`1ea93859-7cdf-4c8e-86d6-003e93e70eef`; waiting for its owner workplan/task `interfaces/workload-projection-transport-v1.yaml` is the complete owner-ready
identifier. interface. Initial routing message:
`1ea93859-7cdf-4c8e-86d6-003e93e70eef`.
## Add authoritative estate coverage ## Publish the authoritative estate-coverage owner interface
```task ```task
id: RMGR-WP-0010-T05 id: RMGR-WP-0010-T05
status: wait status: done
priority: high priority: high
state_hub_task_id: "71a4dae7-8484-57f7-96b9-c2ef93aa4642" state_hub_task_id: "71a4dae7-8484-57f7-96b9-c2ef93aa4642"
``` ```
Join declarations to an authoritative runtime/deployable observation source and Supply Railiance Master with a directly adoptable schema-owner task clarifying
report running units lacking rapp coverage. Repository names are insufficient universal managed-deployable coverage, migration debt, and the non-workload
evidence. Separate non-workload operational subjects from undeclared workloads. boundary.
**Handoff (2026-08-22):** sent Railiance Master message **Result (2026-08-22):** `interfaces/rapp-workload-coverage-v1.yaml` is the
`d8e64195-9117-4439-bc67-d2e7696a9bf5` for the normative coverage clarification complete owner-ready interface. Initial routing message:
and an owner work record. Runtime observation-source selection remains open. `d8e64195-9117-4439-bc67-d2e7696a9bf5`. Runtime observation-source selection
belongs in the adopting owner work record, not as a duplicate Repo Manager todo.
## Adopt explicit ops-warden references ## Publish the ops-warden reference owner interface
```task ```task
id: RMGR-WP-0010-T06 id: RMGR-WP-0010-T06
status: wait status: done
priority: high priority: high
state_hub_task_id: "72aa51a0-2a06-571c-967d-fb18ee96b30f" state_hub_task_id: "72aa51a0-2a06-571c-967d-fb18ee96b30f"
``` ```
Ops-warden owns its catalog schema. Add an explicit workload reference and an Supply ops-warden with the exact catalog adoption task, including field
unambiguous not-applicable/unknown distinction, then validate every resolved semantics, owner boundary, validation, and no-inference acceptance tests.
reference through Repo Manager. Do not copy classification or criticality.
**Handoff (2026-08-22):** sent ops-warden message **Result (2026-08-22):**
`ca18c1ab-540f-4765-89ba-43c068bb49d2`; waiting for its adoption workplan/task `interfaces/ops-warden-workload-reference-v1.yaml` is directly adoptable by
identifier. `WARDEN-WP-0032`. Initial routing message:
`ca18c1ab-540f-4765-89ba-43c068bb49d2`.
## Prove Zone Engine consumption ## Publish the Zone Engine consumption owner interface
```task ```task
id: RMGR-WP-0010-T07 id: RMGR-WP-0010-T07
status: wait status: done
priority: high priority: high
state_hub_task_id: "b68f40b1-cf63-589f-96ee-c6c1098d9802" state_hub_task_id: "b68f40b1-cf63-589f-96ee-c6c1098d9802"
``` ```
Zone Engine consumes the declaration projection and explicit catalog references, Supply Zone Engine with a directly adoptable join-and-proof task that consumes
reports unknown subjects without inference, and demonstrates that path/repo-name the declaration projection and explicit catalog references, reports unknown
drift cannot alter membership. subjects, and prohibits path/repository-name inference.
**Handoff (2026-08-22):** replied through Zone Engine message **Result (2026-08-22):**
`a271dc75-b2c9-4c9a-a91c-20aaa1cfb5dc`; waiting for its adoption/proof task `interfaces/zone-engine-workload-resolution-v1.yaml` is directly adoptable by
identifier. `ZONE-WP-0001-T07`, which already links `RMGR-WP-0010-T07`. Initial routing
message: `a271dc75-b2c9-4c9a-a91c-20aaa1cfb5dc`.
## Completion
The Repo Manager boundary is complete. `RMGR-ADR-005` makes interface
publication the producer-side terminal action: approval, amendment, and
implementation live only in each target owner's file-backed work record. No
cross-owner implementation todo remains duplicated in this workplan.