feat: publish reviewed architecture and ADR batch
Some checks failed
Build and publish policy-nexus image / build-and-push (push) Failing after 19s

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a058f3-8ba0-7692-a042-9a870fc3d663
This commit is contained in:
tegwick 2026-08-31 21:34:23 +02:00
parent 023badb512
commit 93608c1f17
120 changed files with 17791 additions and 727 deletions

View file

@ -1,7 +1,7 @@
<!doctype html>
<html lang="en"><meta charset="utf-8">
<meta name="policy-source-revision" content="41a3fb8b81bd521a5fa21af114975c54532df3ad">
<meta name="policy-source-digest" content="81ccfde427525f9a8d47f93c346813bc2d4003a990b503343e27c842a81a2ea6">
<meta name="policy-source-revision" content="b72fdb5452bff51a867a0316edb994723b35f268">
<meta name="policy-source-digest" content="f1017730074727bcb0c68309c445ffb219ef647c8c5604adbfff76c4aa3f9d66">
<title>Rule vs. Instruction Model and Expression DSL</title>
<style>
:root{
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
</style>
<div class="wrap"><header><div class="eyebrow"><span>ACT-ADR-003</span> <span class="stat">accepted · accepted-1</span> <span>activity-core</span> <span>reviewed 2026-05-14</span><span>generated from canonical source — do not edit</span></div><h1>Rule vs. Instruction Model and Expression DSL</h1><p class="sub">Source: <code>activity-core · docs/adr/adr-003-rule-instruction-model.md · 41a3fb8b81bd521a5fa21af114975c54532df3ad</code></p><p class="sub">Review due: 2026-11-14</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
<div class="wrap"><header><div class="eyebrow"><span>ACT-ADR-003</span> <span class="stat">accepted · accepted-2</span> <span>activity-core</span> <span>reviewed 2026-05-14</span><span>generated from canonical source — do not edit</span></div><h1>Rule vs. Instruction Model and Expression DSL</h1><p class="sub">Source: <code>activity-core · docs/adr/adr-003-rule-instruction-model.md · b72fdb5452bff51a867a0316edb994723b35f268</code></p><p class="sub">Review due: 2026-11-14</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
<p>Accepted.</p>
</section>
<section id="context"><h2>Context</h2>
@ -250,7 +250,7 @@ trusted_fields: # REQUIRED — explicit allowlist of payload
- event.attributes.domain
- event.attributes.tags
model: claude-sonnet-4-6
review_required: false # true | false — curator gate for output
review_advisory: false # true | false — advisory evidence, not a gate
prompt: |
{prompt template — only trusted_fields may be interpolated}
output_schema: {path to JSON schema file}</pre>
@ -261,16 +261,16 @@ output_schema: {path to JSON schema file}</pre>
<h3>Output schema enforcement</h3>
<p>The LLM response is validated against <code>output_schema</code> using JSON Schema validation. If validation fails, the instruction retries once with the schema error appended to the prompt. If the second attempt also fails, the instruction records an <code>instruction_output_error</code> audit event and emits no tasks. Tasks are <strong>never created from unvalidated output</strong>.</p>
<p>Structured output mode (tool_use / JSON mode) is used where the model supports it. The output schema must define <code>List[TaskSpec]</code> or a compatible envelope.</p>
<h3><code>review_required: true</code></h3>
<p>When set today, the instruction's task/report output is marked with <code>review_required=true</code> in activity-core audit metadata. For report-producing instructions, this flag is also persisted in configured report sinks so an operator can distinguish validated-but-review-worthy output from routine output.</p>
<p>activity-core does <strong>not</strong> currently route proposed tasks to a pending review queue. That queue must be owned by issue-core, because issue-core owns task lifecycle state. Until issue-core exposes a review contract, <code>review_required</code> is metadata only; it must not be treated as evidence that live task creation was held for approval.</p>
<p>Future issue-core review integration may use the same field, but that change must update the issue sink contract and tests before any ActivityDefinition relies on queue routing.</p>
<h3><code>review_advisory: true</code></h3>
<p>ACTIVITY-WP-0035 selected advisory-only semantics because no downstream owner currently exposes an acknowledged proposal/decision/release contract. The instruction's task/report evidence is marked <code>review_advisory=true</code> and <code>review_gate_applied=false</code> so an operator can distinguish review-worthy output without interpreting it as held for approval.</p>
<p>The legacy input name <code>review_required</code> is accepted during migration and normalized to <code>review_advisory</code>; new definitions must not use it. activity-core does <strong>not</strong> route proposals to a pending-review queue and does not own review lifecycle state. A future hold/release design requires a named downstream owner, an idempotent release reference, an ADR update, and fail-closed emission tests.</p>
<h3>Evaluation semantics</h3>
<ul><li>Instructions are evaluated <strong>after</strong> all rules in the ActivityDefinition.</li><li>The optional <code>condition</code> field on an instruction uses the same Rule DSL as a first-pass filter — if the condition is false, the LLM is not called. This avoids LLM cost for events that clearly do not need instruction judgement.</li><li>Instructions are <strong>not</strong> first-match-only; all instructions whose conditions pass fire. An ActivityDefinition may have zero instructions.</li></ul>
<h3>Audit trail</h3>
<p>Every task emission records:</p>
<div class="scroll"><table><thead><tr><th>Field</th><th>Rule</th><th>Instruction</th></tr></thead><tbody><tr><td><code>source_type</code></td><td><code>&quot;rule&quot;</code></td><td><code>&quot;instruction&quot;</code></td></tr><tr><td><code>source_id</code></td><td>rule <code>id</code> from definition</td><td>instruction <code>id</code> from definition</td></tr><tr><td><code>source_version</code></td><td>ActivityDefinition version</td><td>ActivityDefinition version</td></tr><tr><td><code>triggering_event_id</code></td><td>event UUID</td><td>event UUID</td></tr><tr><td><code>condition_matched</code></td><td>expression string</td><td>expression string (pre-filter)</td></tr><tr><td><code>prompt_hash</code></td><td>—</td><td>SHA-256 of rendered prompt</td></tr><tr><td><code>model</code></td><td>—</td><td>model ID used</td></tr><tr><td><code>output_validated</code></td><td>—</td><td><code>true</code> / <code>false</code></td></tr><tr><td><code>review_required</code></td><td>—</td><td><code>true</code> / <code>false</code></td></tr></tbody></table></div>
<div class="scroll"><table><thead><tr><th>Field</th><th>Rule</th><th>Instruction</th></tr></thead><tbody><tr><td><code>source_type</code></td><td><code>&quot;rule&quot;</code></td><td><code>&quot;instruction&quot;</code></td></tr><tr><td><code>source_id</code></td><td>rule <code>id</code> from definition</td><td>instruction <code>id</code> from definition</td></tr><tr><td><code>source_version</code></td><td>ActivityDefinition version</td><td>ActivityDefinition version</td></tr><tr><td><code>triggering_event_id</code></td><td>event UUID</td><td>event UUID</td></tr><tr><td><code>condition_matched</code></td><td>expression string</td><td>expression string (pre-filter)</td></tr><tr><td><code>prompt_hash</code></td><td>—</td><td>SHA-256 of rendered prompt</td></tr><tr><td><code>model</code></td><td>—</td><td>model ID used</td></tr><tr><td><code>output_validated</code></td><td>—</td><td><code>true</code> / <code>false</code></td></tr><tr><td><code>review_advisory</code></td><td>—</td><td><code>true</code> / <code>false</code>; no gate applied</td></tr></tbody></table></div>
<p>The audit trail is written to the <code>task_spawn_log</code> table in activity-core's database and referenced from the task record in issue-core.</p>
<p>The rendered prompt and provider response are deliberately not persisted. The prompt hash proves equality when an authorized operator can reconstruct the same input, but the audit contract does not promise reconstruction after source definitions or upstream event retention have changed. <code>activity_runs</code> retains the definition version and bounded context snapshot; reports may retain allowlisted route/usage metadata. Prompts, messages, tool output, credential fields, and provider blobs are excluded from run, progress, and public API evidence.</p>
<h3>Testing strategy</h3>
<p><strong>Rules</strong>: every rule can and should be unit-tested with fixture event payloads. A test helper <code>evaluate_rule(condition_str, event_fixture)</code> returns <code>bool</code> and raises on syntax errors. Tests live alongside ActivityDefinition files: <code>activity-definitions/{slug}.test.json</code> — a list of <code>{event, expected_rules_fired}</code> fixtures.</p>
<p><strong>Instructions</strong>: instructions cannot be deterministically unit-tested. Instead:</p>
@ -291,4 +291,4 @@ output_schema: {path to JSON schema file}</pre>
</section>
<section id="related"><h2>Related</h2>
<ul><li>ACT-ADR-001 — Event Bridge Architecture</li><li>ACT-ADR-002 — Definition format (where rule/instruction blocks live)</li><li>CUST-TFE-SCOPE-2026-000001 — task-flow-engine extraction (analogue pattern)</li><li><code>src/activity_core/rules/</code> — implementation home</li></ul>
</section><footer><span>ACT-ADR-003 · accepted-1 · accepted</span><span>activity-core · docs/adr/adr-003-rule-instruction-model.md · 41a3fb8b81bd521a5fa21af114975c54532df3ad</span></footer></main></div></div></html>
</section><footer><span>ACT-ADR-003 · accepted-2 · accepted</span><span>activity-core · docs/adr/adr-003-rule-instruction-model.md · b72fdb5452bff51a867a0316edb994723b35f268</span></footer></main></div></div></html>