| name | measure |
| position | both |
| description | Write a SLICE's measure lens as a grounding doc (measure.md) — the delivery-measurement focus, the metrics that prove it (baseline / target / proof, triangle-primary speed/tokens/cognition), and what is out of scope — then, when all seven lens docs line up, stamp the slice realized on the spine. The DELIVER pipe of realize (runs last): it opens its own branch (start-change) and closes it (commit → propose → review → merge). Reads the hub from the spine; the single play that flips a slice to realized — the marker /grill checks. |
| user-invocable | true |
measure
Write a shaped slice's measure lens as the grounding doc measure.md — what delivery the slice is
proving, the metrics that prove it (each a baseline, a target, and a proof; triangle-primary on
speed/tokens/cognition), and what is out of scope — and, when the slice lines up (all seven lens
docs present), stamp it realized. /measure reads the slice's hub — its functionalities'
grounding docs plus the profile, both from the spine. It is the deliver lens, the last of the
three realize pipes, and the one play that flips a slice's status to realized on the spine — the
single marker /grill checks before it cuts delivery work.
Pipeline position: both. /measure is the DELIVER pipe — a single-play pipe that runs last (after
the functional pipe ux → agentic → marketing and the non-functional pipe architecture → quality → run
have merged to main). The D2 rule prepends start-change (opens the deliver issue, cuts a fresh
branch off main, inits STM) and, after the lens is persisted, the realized stamp is made, and both are
verified, appends the close sequence commit-change → propose-change → review-change → merge-change,
merging the realized slice to main. (#437; 3-pipe realize 2026-06-26)
Compiled From
This play was compiled from the measure ICE (reference/ice.md) by play-editor (#466 Batch C,
Level 3 rollout per ADR 025). Intent defines constraints (C1–C13) and failure conditions (F1–F14);
the expectation defines success scenarios (S1–S6), a Done means (D1–D4, baked to
stop-condition.yaml — D4 counts BOTH stamp outcomes as done), and one recovery entry per failure
condition. To modify this play, update reference/ice.md and recompile with play-editor. Do NOT
edit this file manually — it is a compiled artifact.
(#467 Batch B) checkpoint upgraded to a conditional learned gate; see gate-config.md.
Role
You are the orchestrator. You own the workflow and step order. You delegate the domain work —
authoring the measure lens grounding doc — to the product-os-keeper agent via a JSON contract over
files on disk, and you run the mechanical checks (readiness/hub resolution, the shape linter, the
content-quality eval, grounding + coverage, KB grounding, the allowlisted apply, the lines-up gate,
the realized stamp, the verify) through bundled scripts and an isolated judge. You never write the
lens yourself, you never stamp a slice that has not lined up, and you never persist before the single
checkpoint's gate resolves (C11) — a typed approval, a recorded config skip, or a recorded policy
auto-pass.
Forbidden: hand-writing the lens or a decision; writing anything other than this slice's
measure.md, a decision, and (on lines-up) the one realized status field (C2); stamping the slice
realized when a lens doc is missing (C8); reading or grounding on another realize lens (C7); persisting
or stamping by any route other than scripts/apply_measure.py + scripts/stamp_slice.py; persisting
before the checkpoint; closing COMPLETED without the stop-condition verdict reading held (C13/F13).
Agent boundaries:
| Agent | Domain | Skill it invokes | Phases |
|---|
product-os-keeper | Author the slice's measure lens (focus / metrics / out-of-scope) from the hub + KB measurement-frame grounding | kb-search, author-measure-lens | Draft |
product-os-keeper is the single domain agent this play uses (1 of the ≤5 budget). The
content-quality judge always runs as an isolated, clean-context sub-agent (optionally on a configured
different model) — never the orchestrator's own context.
Pre-flight
| Check | Constraint | Action on Failure |
|---|
Resolve config + product_base (.garura/core/config.yaml) | — | Hard halt |
Resolve grounding-eval.judge (optional model override) | C4 | Default: sub-agent on the session model |
Slice ready + hub resolves (check_ready_slice.py) | C1 | Hard halt (REC1) |
Resolve the pre-flight facts mechanically with the bundled resolver:
python3 scripts/preflight.py --play measure --config .garura/core/config.yaml
Then resolve the slice and its hub from the spine — the readiness gate every realize lens shares:
python3 scripts/check_ready_slice.py --product-base <product_base> --slice <slice-id>
It asserts the profile is set (from the spine), resolves the slice record, and resolves every
functionality_ref through the spine to its functionality.md grounding doc — the hub. If the slice
is absent, a functionality does not resolve, or the profile is not firmed, hard halt (C1/REC1).
The run's working root (<working> below) is {stm_base}_realize/measure/ — the draft dir, the
manifests, the captured verify output (measure-checks.json), the lines-up capture, the stamp record
(stamp-record.json), and the status/ markers all live under it; the stop condition evaluates
against it.
Right after the resolver, record the session identity stamp's start marker (#463 — soft-fail, never
a halt):
python3 scripts/session_stamp.py --phase start \
--marker "{stm_base}_realize/measure/status/session-stamp-measure.json" \
--cwd "$(pwd)" --branch "$(git branch --show-current)"
Resume check: if {stm_base}_realize/measure/status/<slice-id>.json exists, resume — skip
completed steps, reset any in-progress step to pending, continue.
Task DAG
Create ALL tasks immediately after resolving config — before any domain work.
[T0] start-change (injected — start head) blockedBy: []
[T1] Draft the lens blockedBy: [T0]
[T2] Validate the draft blockedBy: [T1]
[T3] Checkpoint (approval) blockedBy: [T2]
[T4] Persist + stamp blockedBy: [T3]
[T5] Verify persisted blockedBy: [T4]
[TE1] commit-change (injected — end #1) blockedBy: [T5]
[TE2] propose-change (injected — end #2) blockedBy: [TE1]
[TE3] review-change (injected — end #3) blockedBy: [TE2]
[TE4] merge-change (injected — end #4) blockedBy: [TE3]
[T6] Scenario Validation blockedBy: [TE4]
[T7] Close blockedBy: [T6]
Mark each task in-progress before its step and completed right after its eval passes.
Workflow
Phase: Start (injected — D2 position: start)
Step 0 — start-change · Owner: start-change (sub-play) · Depends on: pre-flight
Run the start-of-pipeline member as a sub-play, dispatched with parent_run_id so it emits only its
own C1 evidence and this play's close absorbs it. It resolves or creates the deliver-pipe issue, cuts a
fresh branch off main, sets up a worktree iff config calls for it, and initializes the STM workspace.
{ "play": "start-change", "parent_run_id": "<this run id>", "inputs": { "title": "realize (deliver): <slice>" }, "outputs": { "result": "{stm_base}_realize/measure/start/start-change.json" } }
start-change owns its own evals (issue anchored, branch off latest main, worktree per config, STM
initialized); they are not re-checked here.
Phase: Draft
Step 1 — Draft the lens · Owner: product-os-keeper · Depends on: Step 0
The agent invokes author-measure-lens to draft the slice's measure.md (focus / metrics / out of
scope, per the Measure lens template) from the hub (the functionality grounding docs + the profile) and
KB measurement-frame grounding, plus a measure-manifest.yaml (the grounding map) and any material
decision:
{
"task": "author the slice's measure lens (focus / metrics baseline-target-proof / out-of-scope) from its hub; ground each metric in the functionalities + profile and the frames in the KB",
"inputs": { "slice_ref": "<domain>/<slice>",
"slice_file": "<slice record>",
"functionality_groundings": "<from check_ready_slice>",
"profile": "<spine profile>", "product_base": "<product_base>",
"lens_rel": "product-os/<domain>/slices/<slice>/lens/measure.md" },
"outputs": { "draft_dir": "<working>/draft/", "manifest": "<working>/draft/measure-manifest.yaml" }
}
The skill reads the hub read-only and writes only the draft (the measure.md, the manifest, any
decision, any KB proposals).
Phase: Validate
Step 2 — Validate the draft · Owner: play · Depends on: Step 1
Run the guards over the draft before the checkpoint — shape first, then content, then grounding.
python3 scripts/lint_grounding.py --doc <working>/draft/product-os/<domain>/slices/<slice>/lens/measure.md
python3 scripts/validate_measure.py --draft <working>/draft --manifest <working>/draft/measure-manifest.yaml --slice-file <product_base>/<slice_file>
python3 scripts/check_kb_grounding.py --manifest <working>/draft/measure-manifest.yaml --kb-root <kb_root> --proposals-dir <working>/draft/proposals
Then run the content-quality eval over measure.md: spawn an isolated, clean-context sub-agent
handed the judge prompt (standards/rules/grounding-eval.md), the doc, and the Measure lens
per-section guidance, on the model from grounding-eval.judge.model. Gate the verdict:
python3 scripts/grounding_gate.py --verdict <verdict.json>
SE-1 (F1/C1): check_ready_slice.py passed at pre-flight — the slice is ready and its hub
resolves; an unready slice halted (REC1).
SE-2 (F3/C3): lint_grounding.py exits 0 — measure.md conforms to the Measure lens template
(Focus / Metrics / Out of scope), no missing/extra/empty section.
SE-3 (F4/C4): the content-quality eval gate (grounding_gate.py) passes — measure.md is
self-explaining and clears the stranger test.
SE-4 (F5/C5): validate_measure.py — every metric grounds in a functionality's acceptance or a
profile outcome (the manifest grounds), and a material choice names a decision that resolves.
SE-5 (F6/C6): validate_measure.py — every functionality the slice bundles is considered.
SE-6 (F7/C7): validate_measure.py — the metrics ground on no other realize lens.
SE-7 (F12/C12): check_kb_grounding.py exits 0 — the measurement-frame choices trace to a KB
learning or a recorded proposal.
On any GAP, apply the matching recovery (REC3–REC7, REC12) and re-run before the checkpoint.
Phase: Checkpoint (conditional gate, class: standard, C11)
Step 3 — Human review (conditional gate, class: standard) · Owner: play · Depends on: Step 2
This is the single checkpoint (C11) — the agent never skips it on its own judgment. It is a
conditional gate per standards/rules/gate-config.md (#467 — /measure is one of the eleven
conditional document plays). Resolve, first match wins: pinned (n/a here) → gates.plays.measure →
the learned policy → gates.classes.standard → gates.default (absent ⇒ on). When config resolves
it off, record gate skipped by config (<resolution path>) as a Checkpoint Decisions row in the
evidence and proceed on the validated draft.
For the policy leg, classify the draft-vs-live change shape mechanically:
python3 scripts/classify_change.py --play measure --draft <working>/draft --live <product_base> --out <working>/shape.json
Look the shape key up in the config-resolved learned policy (gates.conditional.policy →
gate-policy.yaml). Shape in auto: AND not in never_auto: AND no blocking finding (a Step 2
lint gap or content-eval fail) → auto-pass: record gate auto-passed by learned policy (shape: <shape-key>, policy v<version>) as a Checkpoint Decisions row plus the draft's diff summary
(the axis counts from shape.json), append the ledger line, and proceed — no wait:
python3 scripts/gate_eval.py append --ledger <gates.conditional.ledger> --play measure \
--issue <issue> --shape <shape-key> --predicted auto --human auto_pass \
--ts <run ts> --policy-version <policy version>
Anything else → gate: render the approval prompt — the proposed focus, metrics, and out-of-scope
inline, plus any decision, AND the realized stamp this run will make — or, if a lens doc is
missing, the lenses still outstanding (the slice will not be stamped) — and wait for the typed
response. Approve → persist; cancel → halt, nothing written. Then append the ledger line with the
human's real action:
python3 scripts/gate_eval.py append --ledger <gates.conditional.ledger> --play measure \
--issue <issue> --shape <shape-key> --predicted gate \
--human approved_clean|approved_edited|rejected --ts <run ts>
<run ts> is the run's own timestamp, derived the same way the close derives ts (date -u) and
passed by the orchestrator — the script never reads the wall clock. EVERY crossing appends exactly
one live-eval ledger line, gated or auto.
SE-11 (F11/C11): the lens and the stamp are persisted only after this gate resolves — a typed
approval, a recorded config skip, or a recorded policy auto-pass; Step 4 is the sole writer and
depends on this step.
SE-13 (F14/C11): every conditional-gate crossing appended exactly one live-eval ledger line
(gate_eval.py append), and an auto-pass fired only for a shape the policy lists in auto: (and not
in never_auto:) with no blocking finding.
Phase: Apply
Step 4 — Persist + stamp · Owner: play · Depends on: Step 3
First snapshot the live spine and the slice folder so Step 5 can verify (cp the spine to
<working>/spine-before.yaml; cp -R the slice folder to <working>/slice-before). Persist the lens
on the fixed allowlist — only this slice's measure.md (re-derive) and decisions (skip-if-exists):
python3 scripts/apply_measure.py --draft <working>/draft --product-base <product_base> --out-manifest <working>/apply-manifest.json
Then run the lines-up gate over the live slice and resolve the stamp — stamp_slice.py reads the
lines-up capture, stamps realized ONLY on a pass, and EITHER WAY writes the stamp record
(stamp-record.json, the stop condition's D4 input):
python3 scripts/lines_up.py --product-base <product_base> --slice <slice-id> > <working>/lines-up.json
python3 scripts/stamp_slice.py --product-base <product_base> --slice <slice-id> \
--lines-up <working>/lines-up.json --record <working>/stamp-record.json
When the gate passes (all seven lens docs present) the slice is stamped and the record reads
{stamp_resolved: true, stamped: true}; when a lens is missing the stamp is explicitly skipped, the
record reads {stamp_resolved: true, stamped: false, missing: [...]}, and the missing-lens list is
carried into the report — the slice stays un-realized. Both outcomes are resolved outcomes; an
unwritten record is an unresolved stamp and blocks the close (C13).
SE-8 (F8/C8): the slice is stamped realized only when lines_up.py reports every one of the
seven lens docs present; a missing lens leaves the status unchanged and is reported — and either
outcome is recorded in stamp-record.json (stamp_resolved: true, stamped true/false with the
missing lenses).
Phase: Verify
Step 5 — Verify persisted · Owner: play · Depends on: Step 4
Verify the persist and the stamp were surgical (pass --expect-realized iff the stamp record reads
stamped: true) — capture the checker's JSON output; its ok field is the stop condition's D3
input:
python3 scripts/check_measure.py --cap-before <working>/slice-before --cap-dir <product_base>/product-os/<domain>/slices/<slice> --spine-before <working>/spine-before.yaml --spine-after <product_base>/product-os/_spine.yaml --slice <slice-id> --expect-realized > <working>/measure-checks.json
SE-9 (F2/F9/C2/C9): the only file changed in the slice folder is lens/measure.md (decisions may
be added, never edited in place); on the spine, the ONLY change is this slice's status → realized
(or none, when not stamped) — every other slice, field, and collection byte-identical.
SE-10 (F10/C10): the run is non-destructive — no accepted decision edited in place, no file removed.
Phase: End sequence (injected — D2 position: end)
After the lens is persisted, the stamp is made (or skipped), and both are verified, the D2 rule injects
the close sequence — each a sub-play dispatched with parent_run_id, resolving its own context — to
commit the deliver pipe, raise the PR, take the verdict, and merge the realized slice to main.
Step E1 — commit-change · blockedBy: Step 5
{ "play": "commit-change", "parent_run_id": "<this run id>", "inputs": {}, "outputs": { "result": "{stm_base}_realize/measure/end/commit-change.json" } }
Step E2 — propose-change · blockedBy: E1
{ "play": "propose-change", "parent_run_id": "<this run id>", "inputs": {}, "outputs": { "result": "{stm_base}_realize/measure/end/propose-change.json" } }
Step E3 — review-change · blockedBy: E2
{ "play": "review-change", "parent_run_id": "<this run id>", "inputs": {}, "outputs": { "result": "{stm_base}_realize/measure/end/review-change.json" } }
Step E4 — merge-change · blockedBy: E3
{ "play": "merge-change", "parent_run_id": "<this run id>", "inputs": {}, "outputs": { "result": "{stm_base}_realize/measure/end/merge-change.json" } }
Each end member owns its own evals (commit grouped by concern, PR opened, verdict posted, branch merged
- cleaned); they are not re-checked here. A review-change reject stops the chain before merge.
Phase: Scenario Validation
Step 6 — Scenario evals · Owner: play · Depends on: the end sequence
- SCE-1 (S1 — delivery analyst, first run):
measure.md is a valid Measure Lens doc clearing the
linter + the content eval, grounded in the hub.
- SCE-2 (S2 — delivery owner, the realized stamp): with all six other lens docs present, the slice
is stamped
realized on the spine and that is the only spine change.
- SCE-3 (S3 — reviewer, not-yet-lined-up): with a lens missing,
measure.md is written but the
slice is NOT stamped; the missing lens is named and the status unchanged.
- SCE-4 (S4 — architect, hub-only): every metric grounds in a functionality or the profile, never
another lens.
- SCE-5 (S5 — delivery owner, re-run): a re-run re-derives only
measure.md and re-affirms the
stamp; everything else byte-identical; no accepted decision edited in place.
- SCE-6 (S6 — reviewer, the checkpoint): the checkpoint showed the lens and the stamp inline, and
no product-model file was written before approval — or, on the auto-pass path, the shape was
policy-listed and the recorded auto-pass, the ledger line, and the diff summary stood in for the
wait (nothing written before the gate resolved).
Phase: Evidence & Close
Step 7 — Close · Owner: play · Depends on: Step 6
Run the Standard Play Close. /measure is a slice-realize play — record evidence per the D1 rule.
SE-12 (F13/C13): the stop-condition verdict is held before the run closes COMPLETED — including
D4, the resolved stamp record (either outcome); a close over an unmet or unevaluable verdict reads
HALTED, never COMPLETED (REC13).
evidence_template=$(cat "${ltm_project_target}standards/templates/evidence-file.md")
delivery_template=$(cat "${ltm_project_target}standards/templates/delivery-report.md")
ts=$(date -u +%Y%m%d-%H%M%S)
evidence_dest="${evidence_base}${ts}.md"
mkdir -p "$(dirname "$evidence_dest")"
session_stamp=$(python3 scripts/session_stamp.py --phase close \
--marker "${stm_base}_realize/measure/status/session-stamp-measure.json")
python3 scripts/check_stop_condition.py \
--manifest "<play-dir>/stop-condition.yaml" \
--base "${stm_base}_realize/measure/" \
--out "${stm_base}_realize/measure/status/stop-condition-measure.yaml"
sc_exit=$?
python3 scripts/distill_gate_policy.py --ledger "${gates_ledger}" --policy "${gates_policy}" \
--streak "${gates_streak}" --project "${project_name}" || true
/measure opens its own deliver-pipe issue (position start), so it is project-scoped:
evidence_base="${stm_base}${issue}/evidence/measure/" and slug="#${issue}".
Step C0 — bind the verdict. sc_exit == 0 (held) permits status: COMPLETED. Anything else
closes HALTED with exit_reason: stop_condition_unmet and the evidence's Stop Condition section
names every unmet clause. A not-stamped run whose record names the missing lenses is a DONE run (D4
held); an UNRESOLVED stamp — no record — is not; fix the state per REC13 (re-run the verify capture,
or re-run the stamp step so the record names one of the two outcomes) and re-evaluate; the close
stays HALTED until the verdict reads held. An unevaluable verdict is never a pass.
Step C1 — Write evidence file. Gated by the resolved evidence.record flag. When false, skip and
record evidence skipped (record=false). Otherwise fill the evidence-file.md slots (play measure,
run_id measure-${ts}, slice slug, started/completed, status per C0, exit_reason; artifacts: the
slice's measure.md, the manifest, any decision, the lines-up result, the stamp record (stamped or
explicitly not-stamped with the missing lenses), the stop-condition verdict; the content-eval verdict;
step + scenario evals SE-1…SE-13 / SCE-1…SCE-6; checkpoint decision (incl. any gate skipped by config or gate auto-passed by learned policy row, with the diff summary and the ledger line); the
end-sequence results; the session identity stamp fields from $session_stamp (#463):
session_id, ledger_file, ledger_start_offset, ledger_end_offset (null when unresolved — never blocks
the close); and stop_condition per C0 with the Stop Condition section filled) and write to
$evidence_dest. Do NOT hand-author the body.
Step C2 — Render delivery report. Also render the Next line: resolve this play in standards/rules/pipeline-next.md and emit **Next:** /<command> — <why>. Or run /next to see all recommended actions. (only /next pointer, or omit, when the mapped command is null), per play-close.md. Fill the delivery-report.md slots: ## measure Delivered — ${slug}, the Run Summary table, the Pipeline Steps table, the Artifacts Produced table (the measure
lens + any decision + whether the slice was stamped realized), Next Steps (if realized: run /grill to
cut this slice into epics; else: run the missing lens pipe), and a pointer to $evidence_dest. Always
emitted.
Scenario Validation
| Scenario | Persona | Eval |
|---|
| S1 — first run | delivery analyst | SCE-1 |
| S2 — the realized stamp | delivery owner | SCE-2 |
| S3 — not-yet-lined-up | reviewer | SCE-3 |
| S4 — hub-only | architect | SCE-4 |
| S5 — re-run | delivery owner | SCE-5 |
| S6 — the checkpoint | reviewer | SCE-6 |
Recovery
| For | Trigger | Direction | Handoff |
|---|
| F1 | the slice is absent, a functionality does not resolve, or the profile is not firmed | halt and route to /shape or /understand before /measure runs | human |
| F2 | a write touched something beyond this slice's measure.md, a decision, or the one realized status field | revert the out-of-scope write; /measure writes only those | autonomous |
| F3 | measure.md fails the template/shape | re-emit to the Measure lens template (Focus / Metrics / Out of scope only) | autonomous |
| F4 | measure.md fails the content-quality eval | rewrite the failing section to the judge's cited fixes and re-judge until the gate passes | autonomous |
| F5 | a metric lacks a baseline/target/proof or grounds in nothing the slice delivers | re-draft the metric as a concrete baseline + target + proof tied to the hub | autonomous |
| F6 | a functionality is neither measured nor named out of scope | add a metric for it or name it in out-of-scope with the reason | autonomous |
| F7 | the assessment read or grounded on another lens | remove the dependency; derive only from the slice's hub | autonomous |
| F8 | the slice was stamped realized when a lens doc was missing | revert the stamp, report the missing lens, route to the pipe that owns it | human |
| F9 | the stamp changed more than this slice's status on the spine | restore the spine and re-apply only the single status flip | human |
| F10 | a non-lens/non-decision file changed, or an accepted decision was edited in place | restore it and re-apply only measure.md and the new decision, after a human confirms the restore | human |
| F11 | the lens or stamp was persisted before the checkpoint gate resolved | revert the premature write and re-present the checkpoint; persist only after the gate resolves (a typed approval, a recorded config skip, or a recorded policy auto-pass) | human |
| F12 | a measurement frame with no KB learning and no recorded proposal | search the KB via kb-search and ground the frame, or raise a KB-learning-gap proposal | autonomous |
| F13 | the run is about to close COMPLETED with the Done means unmet | close HALTED (stop_condition_unmet) with the unmet clauses named; fix the state — re-run the verify capture, or re-run the stamp step so the record names one of the two outcomes — and re-evaluate; the close stays HALTED until the verdict reads held | autonomous |
| F14 | a conditional-gate crossing left no live-eval ledger line, or an auto-pass fired for a shape the policy does not list as auto (or that carried a blocking finding) | re-append the missing ledger line from the recorded crossing; when the auto-pass was unearned, re-run the gate as a live wait (render the prompt, take the typed verdict) and append the corrected line | autonomous |
Pause and Resume
Steps run top to bottom. On entry, resolve config, resolve the target slice, check the status marker,
skip completed steps, reset any in-progress step to pending, and continue.
Compilation Metadata
| Field | Value |
|---|
| fingerprint | sha256:0bac8299871a0d9b072941b301ed1d922ff90fee34503d24567dc11e2ec907fc (of reference/ice.md) |
| compiled_by | play-editor (#466 Batch C; #467 Batch B — conditional learned gate) |
| pipeline_position | both (deliver pipe — injects start-change head and commit → propose → review → merge close) |
| workflow_structure | A (single checkpoint — conditional learned gate, class: standard, per gate-config.md #467; stop-condition gated close) |
| stop_condition | stop-condition.yaml (D1–D4; D4 counts both stamp outcomes), gate live at Step C0 |
| domain_agents | 1 (product-os-keeper) |
| utility_agents | 0 |
| skills_used | kb-search, author-measure-lens |
| scripts | 15 (preflight, check_ready_slice, lint_grounding, grounding_gate, validate_measure, check_kb_grounding, apply_measure, lines_up, stamp_slice, check_measure, check_stop_condition, session_stamp, classify_change + gate_eval + distill_gate_policy — #467 conditional gate) |
| step_evals | 13 (SE-1…SE-13) |
| scenario_evals | 6 (SCE-1…SCE-6) |
| recovery_entries | 14 (one per failure condition; 8 autonomous / 6 human) |