glas-harness answered both open questions from ACTIVITY-WP-0032, so T01 is resolved as option A: the ops_run pull queue stays and carries the versioned harness_profile_ref plus attribution refs. The claiming executor passes the request into Glas, which resolves or refuses before sandbox creation. This changes the execution contract without also changing scheduling topology. Two answers shaped the plan: - harness_profile_ref and approach_hint coexist with distinct semantics. approach_hint must never override, synthesize, or fall back from an absent or invalid profile ref on governed execution — T02 must enforce that in code. - The glas-harness catalog is authoritative and must not be mirrored. Glas has no network validation service today, so emit-time remote validation is not available. T03 is corrected accordingly: validate locally and structurally, rely on the execution-side Glas resolver as the mandatory fail-closed check, and record the residual gap rather than papering over it with a mirrored catalogue. Hub decision 147beec6-7fe7-4837-8e3a-4264a240379d. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
197 lines
7.9 KiB
Markdown
197 lines
7.9 KiB
Markdown
---
|
|
id: ACTIVITY-WP-0032
|
|
type: workplan
|
|
title: "Adopt the Glas profile-driven execution contract"
|
|
domain: infotech
|
|
repo: activity-core
|
|
status: active
|
|
owner: claude
|
|
topic_slug: activity-core
|
|
priority: medium
|
|
created: "2026-08-21"
|
|
updated: "2026-08-21"
|
|
related:
|
|
- ACT-ADR-006
|
|
- ACTIVITY-WP-0026
|
|
- ACTIVITY-WP-0029
|
|
- ACTIVITY-WP-0031
|
|
- ACT-ADR-005
|
|
- GLAS-WP-0004
|
|
- REIN-A-0002
|
|
---
|
|
|
|
# Adopt the Glas profile-driven execution contract
|
|
|
|
## Origin
|
|
|
|
`glas-harness` reported (2026-08-20) that GLAS-WP-0004 contract 1.0 is
|
|
implemented and proven: the same bounded task completed through **two**
|
|
different reins (`rein-aharness`, `rein-openweights`) via an explicit
|
|
`harness_profile_ref`, with real commits and verified sandbox destruction.
|
|
Their guidance to us: activity-core stays scheduler and task source, and should
|
|
name an **approved profile**, never a concrete rein.
|
|
|
|
ACTIVITY-WP-0026 is `finished`, so this does not belong as an amendment to it.
|
|
|
|
## Why this is worth doing
|
|
|
|
Today an ops_run carries `approach_hint` (`orm.py:172`), a free-text string the
|
|
executor interprets at claim time. That binding is too late and too weak. Live
|
|
example from 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'] def='2969816c-…'
|
|
```
|
|
|
|
The run was claimed, then died because nothing could execute it. A
|
|
`harness_profile_ref` is resolved and **refused before sandbox creation**, so
|
|
an unroutable request fails at emission with a clear reason instead of
|
|
consuming a claim and a lease.
|
|
|
|
Second motivation: we are currently coupled to one backend in practice —
|
|
every claim in the last week is `rein-aharness@railiance01`. The dual-rein
|
|
proof means that coupling is now avoidable rather than inherent.
|
|
|
|
## Boundary (must not drift)
|
|
|
|
activity-core stays **when / what / where**. Adopting this contract must not
|
|
turn it into an executor — SCOPE drift risk #1 ("convenience execution"). We
|
|
emit an authorized, profile-named request and record normalized evidence. We do
|
|
not select reins, provision sandboxes, acquire credentials, or run the inner
|
|
agentic loop. Glas owns profile resolution and the outer loop; the rein owns its
|
|
own inner loop; `sand-boxer` owns isolation.
|
|
|
|
We also do not author the attribution refs the contract accepts
|
|
(`assignment_ref`, `role_ref`, `duty_ref`, `goal_refs`,
|
|
`resource_envelope_refs`). Those come from workforce/leadership vocabulary in
|
|
`info-tech-canon`; activity-core carries them through, and must not invent org
|
|
roles here (ACTIVITY-WP-0029 responsibility map).
|
|
|
|
## Answered by glas-harness (2026-08-21)
|
|
|
|
Both questions are settled; recorded as **ACT-ADR-006**, hub decision
|
|
`147beec6-7fe7-4837-8e3a-4264a240379d`.
|
|
|
|
1. **Coexistence with distinct semantics.** `harness_profile_ref` is the
|
|
authoritative execution-constellation selector. `approach_hint` stays only as
|
|
a legacy activity/definition-matching hint and must **not** override,
|
|
synthesize, or fall back from an absent/invalid profile ref on governed
|
|
execution. Deprecate that use once inventory shows no caller depends on it.
|
|
2. **The glas-harness catalog is authoritative — do not mirror it.** Glas
|
|
exposes deterministic validation through its package and CLI but **no network
|
|
validation service** today. Emit-time remote validation would need a
|
|
separately scoped Glas API. The execution-side Glas resolver is the mandatory
|
|
fail-closed check.
|
|
|
|
Transport: **preserve the pull queue** in the first migration slice. The exact
|
|
versioned profile ref and attribution refs go in the queued payload; the
|
|
claiming executor passes the request into Glas, which resolves or refuses before
|
|
sandbox creation. This changes the execution contract without also changing
|
|
scheduling topology. A direct activity-core → Glas call can be evaluated
|
|
independently later.
|
|
|
|
## Decide the invocation shape
|
|
|
|
```task
|
|
id: ACTIVITY-WP-0032-T01
|
|
status: done
|
|
priority: high
|
|
```
|
|
|
|
Resolved 2026-08-21 as **option A — the queue carries the profile**, on the
|
|
advice of glas-harness as contract owner. `ops_run` grows `harness_profile_ref`
|
|
plus attribution refs; lease semantics, durability, and the operator console are
|
|
unchanged; activity-core stays behind the executor boundary.
|
|
|
|
Option B (activity-core calls the Glas gateway directly) was rejected for this
|
|
slice: it would discard the claim/lease/retry machinery ACTIVITY-WP-0026 just
|
|
built and change scheduling topology at the same time as the execution contract.
|
|
It remains available as an independent later evaluation.
|
|
|
|
Written up as `docs/adr/adr-006-glas-profile-execution.md`.
|
|
|
|
## Carry the profile and attribution refs
|
|
|
|
```task
|
|
id: ACTIVITY-WP-0032-T02
|
|
status: todo
|
|
priority: high
|
|
```
|
|
|
|
Add `harness_profile_ref` and the correlation/attribution refs
|
|
to the ops_run model, emission path (`activities.py`), queue projection
|
|
(`ops_run_queue.py`), and run artefacts (`run_artifacts.py`), with a migration.
|
|
Definitions declare the profile; rules pass it through. Per ACT-ADR-006 the two
|
|
fields **coexist with distinct semantics**: enforce in code that `approach_hint`
|
|
cannot override, synthesize, or fall back from an absent/invalid
|
|
`harness_profile_ref` on governed execution, and cover that with a test — a
|
|
silent fallback is exactly the failure this workplan removes.
|
|
|
|
## Validate what we can, fail closed on the rest
|
|
|
|
```task
|
|
id: ACTIVITY-WP-0032-T03
|
|
status: todo
|
|
priority: medium
|
|
```
|
|
|
|
Depends on T02. **Corrected after the glas-harness answer:** emit-time *remote*
|
|
validation is not available — Glas has no network validation service, and
|
|
mirroring its catalogue is explicitly forbidden. So:
|
|
|
|
- Validate locally and structurally at definition sync and run emission: a
|
|
governed run has a profile ref, and it is well-formed and versioned.
|
|
- Do **not** resolve the ref against a mirrored list. The execution-side Glas
|
|
resolver is the authority and the mandatory fail-closed check.
|
|
- An absent or malformed ref is an error at emission. It must never degrade into
|
|
"emit anything" or fall back to `approach_hint`.
|
|
|
|
Record the residual gap honestly: a well-formed but unknown profile is still
|
|
caught at execution rather than emission. That is weaker than refusing at emit,
|
|
and still strictly better than the claim-time failure of 2026-08-17, because
|
|
Glas refuses before sandbox creation. If emit-time remote validation becomes
|
|
necessary, raise it as a capability request against glas-harness rather than
|
|
solving it locally.
|
|
|
|
## Record normalized execution evidence
|
|
|
|
```task
|
|
id: ACTIVITY-WP-0032-T04
|
|
status: wait
|
|
priority: medium
|
|
```
|
|
|
|
Depends on T02. Glas emits normalized, non-secret execution evidence. Land it in
|
|
`ops_runs.result` and the evidence sink so the production status surface
|
|
(ACTIVITY-WP-0031-T03) shows what actually executed, through which profile and
|
|
rein. Keep the field allowlist discipline from ACTIVITY-WP-0031: no provider
|
|
blobs, no credential material in run artefacts.
|
|
|
|
## Prove on one definition
|
|
|
|
```task
|
|
id: ACTIVITY-WP-0032-T05
|
|
status: wait
|
|
priority: low
|
|
```
|
|
|
|
Depends on T03/T04. Convert exactly one low-risk definition, run it on
|
|
railiance01, and capture evidence. Do not convert the fleet before one
|
|
definition is proven end to end. Note that FI and Binky are unsuitable as the
|
|
pilot while ACTIVITY-WP-0031-T01 is unresolved — their failures are currently
|
|
provider-credential failures and would mask the result.
|
|
|
|
## Acceptance
|
|
|
|
- [x] Invocation shape decided and recorded as an ADR, with the boundary stated
|
|
(ACT-ADR-006; pull queue preserved)
|
|
- [ ] ops_run carries an approved `harness_profile_ref`; no definition names a
|
|
concrete rein
|
|
- [ ] Malformed/absent profile refs are refused at emission; unknown-but-well-formed
|
|
refs are refused by Glas before sandbox creation, never at claim
|
|
- [ ] `approach_hint` cannot override or substitute for a profile ref, proven by test
|
|
- [ ] Normalized Glas evidence is visible in production status
|
|
- [ ] One definition proven on railiance01 end to end
|