## Status

Accepted (2026-08-21). Hub decision `147beec6-7fe7-4837-8e3a-4264a240379d` ("Glas contract 1.0 makes execution constellation selection explicit").

## Context

ACT-ADR-005 gave internal scheduled automation a claimable `ops_run` plane. What an ops_run said about how to execute was `approach_hint` — free text, interpreted by the claiming executor at claim time.

That binding is too late. Live failure, railiance01 2026-08-17:

    state=failed  attempt=1  claim_owner=rein-aharness@railiance01
    title=Run SBOM rescan for binect-js
    failure=no approach matched labels/definition;
            labels=['sbom','security','automated']

The run was claimed and leased, then died because nothing could execute it. A claim was consumed to discover the request was unroutable.

`glas-harness` GLAS-WP-0004 closed contract 1.0 and proved it by running one bounded task through two different reins (`rein-aharness`, `rein-openweights`) via an explicit `harness_profile_ref`, with real commits and verified sandbox destruction. Meanwhile every activity-core claim in the week to 2026-08-21 was `rein-aharness@railiance01` — a coupling that is now avoidable rather than inherent.

Two shapes were considered: keep the pull queue and carry the profile as payload, or have activity-core call the Glas gateway directly. glas-harness, which owns the contract, advised the first for the initial migration.

## Decision

### 1. The queue stays; the payload changes

activity-core continues to insert `ops_run(open)` and executors continue to claim under lease. Scheduling topology does not change. What changes is that a queued run carries an exact versioned `harness_profile_ref` plus the correlation / assignment / role / duty / goal / resource-envelope references. The claiming executor passes that request into Glas, which resolves or refuses it before sandbox creation.

This changes the execution contract without simultaneously changing the scheduling topology — one variable at a time. A direct activity-core → Glas call may be evaluated later, independently, if pull delivery stops meeting operational needs.

### 2. `harness_profile_ref` is authoritative; `approach_hint` is legacy

The two coexist with distinct semantics, not as fallbacks for one another:

- `harness_profile_ref` is the authoritative execution-constellation selector.
- `approach_hint` remains only a legacy activity/definition-matching hint while producers and consumers migrate.

`approach_hint` must not override, synthesize, or fall back from an absent or invalid `harness_profile_ref` on governed execution. A missing profile is an error, never an invitation to guess from a hint. Once inventory shows no caller depends on `approach_hint` for runtime selection, that use is deprecated.

### 3. activity-core does not mirror the profile catalog

The catalog in glas-harness is authoritative. activity-core must not maintain an independent list, which would drift and produce a second, disagreeing opinion about what is executable.

Consequence, accepted knowingly: Glas exposes deterministic validation through its package and CLI but no network validation service today, so activity-core cannot remotely validate a profile ref at emission time. We therefore validate only what is local and structural — that a ref is present and well-formed for governed execution — and rely on the execution-side Glas resolver as the mandatory fail-closed check.

This is weaker than refusing at emission, and deliberately so: an unreachable or absent validation service must never downgrade into "emit anything". If emit-time remote validation is later required, it needs a separately scoped Glas API and its own decision — not a mirrored catalogue here.

Even unvalidated at emit, this is strictly better than the 2026-08-17 failure: refusal happens deterministically before sandbox creation rather than after a claim and lease were consumed.

### 4. activity-core does not become an executor

We emit an authorized, profile-named request and record normalized evidence. We do not select reins, provision sandboxes, acquire credentials, or run any inner agentic loop. Glas owns profile resolution and the outer loop; the rein owns its inner loop; `sand-boxer` owns isolation. This is SCOPE drift risk #1 ("convenience execution") and this ADR does not relax it.

The attribution references we carry (`assignment_ref`, `role_ref`, `duty_ref`, `goal_refs`, `resource_envelope_refs`) are passed through, not authored here. Their vocabulary belongs to `info-tech-canon`; activity-core must not invent org roles (ACTIVITY-WP-0029 responsibility map).

ACT-ADR-007's bounded-operation exception does not alter this decision. A code-registered fixed maintenance operation is not a Glas/rein execution constellation, and the exception cannot be used to run an agent loop or execute an `ops_run` inside activity-core.

## Consequences

- `ops_runs` grows `harness_profile_ref` and the attribution refs; the emission path, queue projection, and run artefacts carry them.
- Definitions declare a profile; rules pass it through.
- Unroutable requests fail before sandbox creation instead of at claim time.
- activity-core is no longer coupled to one rein in practice.
- Emit-time validation remains a known gap, owned by a future Glas API.
- Implementation: ACTIVITY-WP-0032.