@kontourai/flow-agents 2.4.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/CODEOWNERS +8 -0
- package/.github/workflows/ci.yml +12 -0
- package/.github/workflows/trust-reconcile.yml +62 -4
- package/CHANGELOG.md +23 -0
- package/CONTEXT.md +21 -0
- package/build/src/cli/assignment-provider.d.ts +1 -0
- package/build/src/cli/assignment-provider.js +748 -0
- package/build/src/cli/effective-assignment-provider-settings.d.ts +1 -0
- package/build/src/cli/effective-assignment-provider-settings.js +125 -0
- package/build/src/cli/validate-workflow-artifacts.js +5 -1
- package/build/src/cli/workflow-sidecar.js +157 -110
- package/build/src/cli.js +6 -0
- package/build/src/tools/validate-source-tree.js +1 -0
- package/context/contracts/artifact-contract.md +2 -0
- package/context/contracts/assignment-provider-contract.md +239 -0
- package/context/contracts/builder-kit-workflow-state-contract.md +2 -0
- package/context/contracts/decision-registry-contract.md +2 -0
- package/context/contracts/delivery-contract.md +2 -0
- package/context/contracts/execution-contract.md +25 -0
- package/context/contracts/governance-adapter-contract.md +2 -0
- package/context/contracts/knowledge-store-contract.md +197 -0
- package/context/contracts/planning-contract.md +2 -0
- package/context/contracts/review-contract.md +2 -0
- package/context/contracts/sandbox-policy.md +2 -0
- package/context/contracts/standing-directives.md +13 -0
- package/context/contracts/verification-contract.md +2 -0
- package/context/contracts/work-item-contract.md +2 -0
- package/context/settings/assignment-provider-settings.json +33 -0
- package/docs/adr/0022-fail-closed-delivery-reconciliation-with-governed-exemptions.md +180 -0
- package/docs/context-map.md +1 -0
- package/docs/decisions/index.md +3 -0
- package/docs/decisions/knowledge-store-provider.md +51 -0
- package/docs/decisions/model-routing.md +63 -0
- package/docs/decisions/standing-directives.md +66 -0
- package/docs/fixture-ownership.md +1 -0
- package/docs/workflow-shared-contracts.md +2 -1
- package/docs/workflow-usage-guide.md +6 -0
- package/evals/ci/run-baseline.sh +6 -0
- package/evals/fixtures/assignment-provider/actor-a.json +6 -0
- package/evals/fixtures/assignment-provider/actor-b.json +6 -0
- package/evals/fixtures/assignment-provider/github-issue-claimed.json +27 -0
- package/evals/fixtures/assignment-provider/github-issue-unassigned.json +7 -0
- package/evals/fixtures/assignment-provider/liveness-fresh.json +9 -0
- package/evals/fixtures/assignment-provider/liveness-stale.json +9 -0
- package/evals/integration/test_assignment_provider_github.sh +318 -0
- package/evals/integration/test_assignment_provider_local_file.sh +222 -0
- package/evals/integration/test_critique_supersession_roundtrip.sh +182 -0
- package/evals/integration/test_fixture_retirement_audit.sh +2 -2
- package/evals/integration/test_publish_delivery.sh +21 -4
- package/evals/integration/test_pull_work_assignment_join.sh +132 -0
- package/evals/integration/test_pull_work_liveness_preflight.sh +14 -6
- package/evals/integration/test_reconcile_soundness.sh +33 -9
- package/evals/integration/test_trust_reconcile.sh +9 -8
- package/evals/integration/test_trust_reconcile_negatives.sh +608 -0
- package/evals/integration/test_workflow_sidecar_writer.sh +79 -0
- package/evals/run.sh +10 -0
- package/evals/static/test_flowdef_codeowners_coverage.sh +6 -0
- package/evals/static/test_knowledge_providers.sh +23 -0
- package/kits/builder/skills/deliver/SKILL.md +19 -0
- package/kits/builder/skills/pull-work/SKILL.md +78 -10
- package/kits/knowledge/kit.json +35 -0
- package/kits/knowledge/providers/conformance/fixtures/git-repo/CONTEXT.md +12 -0
- package/kits/knowledge/providers/conformance/fixtures/git-repo/docs/decisions/old-sprocket-shape.md +13 -0
- package/kits/knowledge/providers/conformance/fixtures/git-repo/docs/decisions/sprocket-shape.md +14 -0
- package/kits/knowledge/providers/conformance/fixtures/git-repo/docs/decisions/widget-format.md +14 -0
- package/kits/knowledge/providers/conformance/fixtures/git-repo/docs/learnings/fixture-learning.md +7 -0
- package/kits/knowledge/providers/conformance/fixtures/work-item/issues.json +30 -0
- package/kits/knowledge/providers/conformance/suite.test.js +125 -0
- package/kits/knowledge/providers/git-repo/index.js +236 -0
- package/kits/knowledge/providers/health/health-pass.test.js +99 -0
- package/kits/knowledge/providers/health/index.js +153 -0
- package/kits/knowledge/providers/index.js +24 -0
- package/kits/knowledge/providers/lib/model.js +91 -0
- package/kits/knowledge/providers/lib/schema-validate.js +119 -0
- package/kits/knowledge/providers/markdown-vault/index.js +169 -0
- package/kits/knowledge/providers/work-item/index.js +204 -0
- package/package.json +4 -2
- package/schemas/assignment-provider-settings.schema.json +125 -0
- package/schemas/knowledge/edge.schema.json +54 -0
- package/schemas/knowledge/health-report.schema.json +45 -0
- package/schemas/knowledge/node.schema.json +49 -0
- package/schemas/knowledge/proposal.schema.json +53 -0
- package/scripts/ci/trust-reconcile.js +521 -24
- package/src/cli/assignment-provider.ts +845 -0
- package/src/cli/effective-assignment-provider-settings.ts +112 -0
- package/src/cli/validate-workflow-artifacts.ts +5 -1
- package/src/cli/workflow-sidecar.ts +147 -106
- package/src/cli.ts +6 -0
- package/src/tools/validate-source-tree.ts +1 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Workflow Artifact Contract
|
|
2
2
|
|
|
3
|
+
> Read [`context/contracts/standing-directives.md`](standing-directives.md) — ratified owner directives that override default engineering conservatism.
|
|
4
|
+
|
|
3
5
|
Workflow artifacts are the resumable local handoff surface between orchestrators, workers, verifiers, hooks, evals, and future sessions.
|
|
4
6
|
|
|
5
7
|
## Artifact Root
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# Assignment Provider Contract
|
|
2
|
+
|
|
3
|
+
This contract defines the provider-neutral vocabulary for durable work-item ownership: who has
|
|
4
|
+
claimed a subject, how that claim is represented, and how it is read back safely. It formalizes
|
|
5
|
+
[ADR 0021: Assignment Leases and Stale-Claim Takeover](../../docs/adr/0021-assignment-leases-and-stale-claim-takeover.md)
|
|
6
|
+
as the third provider leg beside `WorkItemProvider` and `BoardProvider`
|
|
7
|
+
(`context/contracts/work-item-contract.md`) and `ChangeProvider`. GitHub is the first concrete
|
|
8
|
+
mapping for this contract, not the generic vocabulary — Linear, Jira, GitLab, and a local-file
|
|
9
|
+
provider for tracker-less repos and evals all map the same operations.
|
|
10
|
+
|
|
11
|
+
## Terminology: three distinct "claim" concepts
|
|
12
|
+
|
|
13
|
+
This repository uses the word "claim" for three unrelated things. Always qualify in prose; never
|
|
14
|
+
write bare "claim" where the meaning is not obvious from surrounding context:
|
|
15
|
+
|
|
16
|
+
| Term | Layer | Meaning | Where it lives |
|
|
17
|
+
| --- | --- | --- | --- |
|
|
18
|
+
| **assignment claim** | this contract | Durable, provider-recorded ownership of a work item | `AssignmentProvider.claim()`, this doc |
|
|
19
|
+
| **liveness claim** | ADR 0012 | Ephemeral, TTL-reaped presence/heartbeat event | `liveness claim` (`workflow-sidecar.ts`), `freshHolders` (`liveness-read.js`) |
|
|
20
|
+
| **trust claim** | ADR 0010 / ADR 0017 | A Hachure `trust.bundle` evidence claim (kit-typed, verification status) | `workflow-sidecar.ts claim <id> <dir>` (`claimLookup`) |
|
|
21
|
+
|
|
22
|
+
An assignment claim's *effective state* is never computed from the assignment layer alone — it is
|
|
23
|
+
always joined against a liveness claim's freshness (see the join table below).
|
|
24
|
+
|
|
25
|
+
## AssignmentProvider Operations
|
|
26
|
+
|
|
27
|
+
Provider-neutral interface, verbatim from ADR 0021 §2:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
AssignmentProvider:
|
|
31
|
+
claim(subjectId, actor, meta) # assign + attach machine-readable claim record
|
|
32
|
+
release(subjectId, actor, meta) # unassign + handoff note
|
|
33
|
+
supersede(subjectId, from, to, meta) # reassign with audit trail
|
|
34
|
+
status(subjectId) -> {assignee?, actor?, claimedAt?, meta?}
|
|
35
|
+
list(actor?) -> [subjectId]
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
| Operation | Arguments | Effect | Returns |
|
|
39
|
+
| --- | --- | --- | --- |
|
|
40
|
+
| `claim` | `subjectId`, `actor`, `meta` | Records durable ownership: assignee (or local-file record), a claim marker, and a versioned claim record carrying the full actor struct. | void (caller re-reads via `status` to confirm) |
|
|
41
|
+
| `release` | `subjectId`, `actor`, `meta` | Clears durable ownership and leaves a handoff note. Normally invoked by the incumbent actor at clean session end. | void |
|
|
42
|
+
| `supersede` | `subjectId`, `from`, `to`, `meta` | Reassigns ownership from a lapsed actor to a successor, with an audit-trail note explaining why (staleness, explicit human confirmation). | void |
|
|
43
|
+
| `status` | `subjectId` | Reads current assignment state without joining liveness. | `{ assignee?, actor?, claimedAt?, meta? }` — the raw assignment-layer read |
|
|
44
|
+
| `list` | `actor?` (optional filter) | Enumerates subject ids currently claimed, optionally filtered to one actor. | `[subjectId]` |
|
|
45
|
+
|
|
46
|
+
`status()` alone is **assignment-layer truth only** — it does not tell a caller whether the claim
|
|
47
|
+
is fresh. Callers that need to decide "is this work available" must compute the join described
|
|
48
|
+
next, not call `status()` in isolation.
|
|
49
|
+
|
|
50
|
+
**Actor identity is runtime-agnostic**: `{ runtime, session_id, host, human? }`. Claude Code,
|
|
51
|
+
codex, opencode, and pi sessions, and humans, are all actors. Reuse the exact struct
|
|
52
|
+
`scripts/hooks/lib/actor-identity.js`'s `resolveActor`/`serializeActor` already define — do not
|
|
53
|
+
fork a second actor concept. `subject_id` reuses `workItemSlug`'s `owner/repo#id` convention
|
|
54
|
+
(the same string the deterministic session slug derives from) rather than inventing a second
|
|
55
|
+
identifier scheme.
|
|
56
|
+
|
|
57
|
+
## The assignment ⋈ liveness join
|
|
58
|
+
|
|
59
|
+
Effective claim state is always a **join** of two layers with distinct jobs. Neither layer is
|
|
60
|
+
trusted alone:
|
|
61
|
+
|
|
62
|
+
| Layer | Records | Lifetime | Medium |
|
|
63
|
+
| --- | --- | --- | --- |
|
|
64
|
+
| **Assignment** | intent / ownership | durable, survives crashes | provider (issue assignee/label/comment, or local-file record) |
|
|
65
|
+
| **Liveness** | presence / freshness | ephemeral, TTL-reaped | ADR 0012 claim stream (`freshHolders`) |
|
|
66
|
+
|
|
67
|
+
Readers compute the join from `{ assignment: AssignmentStatus, freshHolders: FreshHolder[] }` to
|
|
68
|
+
one of five effective states:
|
|
69
|
+
|
|
70
|
+
| Assignment | Liveness | Effective state | `pull-work` treatment |
|
|
71
|
+
| --- | --- | --- | --- |
|
|
72
|
+
| assigned | fresh heartbeat | **held** | excluded |
|
|
73
|
+
| assigned | stale / absent | **reclaimable** | offered, via takeover protocol (ADR 0021 §5, out of this contract's scope) |
|
|
74
|
+
| assigned (human) | n/a (humans don't heartbeat) | **human-held** | surfaced, never auto-taken (see below) |
|
|
75
|
+
| unassigned | fresh (claim only) | **held** (assignment lagging) | excluded |
|
|
76
|
+
| unassigned | absent | **free** | offered |
|
|
77
|
+
|
|
78
|
+
This join rule is what makes lost locks structurally impossible: staleness — not assignment — is
|
|
79
|
+
what excludes, so an orphaned assignee/label/record from a dead session can never gate work.
|
|
80
|
+
|
|
81
|
+
The join is a pure function; reuse `scripts/hooks/lib/liveness-read.js`'s exported
|
|
82
|
+
`freshHolders(events, slug, selfActor, nowMs)` for the liveness half rather than re-implementing
|
|
83
|
+
TTL/staleness arithmetic. The join table itself (assignment status × liveness freshness →
|
|
84
|
+
effective state) is the only new logic — it has no other implementation in this repository.
|
|
85
|
+
|
|
86
|
+
## Lazy-correction transition table
|
|
87
|
+
|
|
88
|
+
Nothing updates the provider on a timer; every mutation has a responsible actor, invoked at a
|
|
89
|
+
specific lifecycle moment (ADR 0021 §4). This table names every transition for completeness; it
|
|
90
|
+
also records which issue implements each row so a future reader does not assume any single issue
|
|
91
|
+
delivers all four:
|
|
92
|
+
|
|
93
|
+
| Transition | Mutator | When | Owning issue |
|
|
94
|
+
| --- | --- | --- | --- |
|
|
95
|
+
| `claim` | the claiming session | at selection | **#290 (this issue)** |
|
|
96
|
+
| `clean_release` | the incumbent (Stop hook / terminal `advance-state`) | session end — unassign + handoff comment | #292 |
|
|
97
|
+
| `supersede` | the successor, inside the takeover protocol | after the grace beat | #294 |
|
|
98
|
+
| `crash_no_successor` | nobody, initially; corrected by the next actor to want the subject, or the janitor | lazily, or on a janitor sweep | out of scope — the Console relay's first cross-machine duty (ADR 0021 §4/§7) |
|
|
99
|
+
|
|
100
|
+
Lazy correction is *safe* by the join rule above (stale assignment excludes nothing), but leaves
|
|
101
|
+
the human-visible board stale in the crash case until the next claim attempt or a janitor sweep
|
|
102
|
+
corrects it.
|
|
103
|
+
|
|
104
|
+
## Human-assignee ask-first policy
|
|
105
|
+
|
|
106
|
+
Humans do not heartbeat, so `assigned-to-human + no-liveness` is **normal, not stale** — it must
|
|
107
|
+
never be treated as `reclaimable`. Agents surface idle human assignments ("assigned to `brian` 3
|
|
108
|
+
days ago, no linked activity — reclaim?") and act only on explicit confirmation.
|
|
109
|
+
|
|
110
|
+
- Default behavior: `ask_first`.
|
|
111
|
+
- The threshold (`idle_threshold_days`, default `3`, matching ADR 0021 §6's own illustrative
|
|
112
|
+
example) and behavior (`ask_first` | `never_reclaim`) are a policy knob in
|
|
113
|
+
`assignment-provider-settings.schema.json` (`policy.human_assignee_policy`), not a hardcoded
|
|
114
|
+
constant.
|
|
115
|
+
- **Non-goal:** never auto-supersede a human. The join function must gate on the actor struct's
|
|
116
|
+
`human` field being present (not absent/null) — never on a heuristic over the GitHub login name
|
|
117
|
+
— so a human assignee is always classified `human-held`, regardless of idle duration, and is
|
|
118
|
+
never silently reclaimed by any automated path.
|
|
119
|
+
- This contract and its settings schema define the policy knob and the read-side data a caller
|
|
120
|
+
needs to surface the question (assignee identity, idle duration). The actual "ask the user"
|
|
121
|
+
interaction belongs to whichever skill consumes the join result (`pull-work`), which records it
|
|
122
|
+
as an alignment question rather than a new UI surface.
|
|
123
|
+
|
|
124
|
+
## Versioned claim-record format
|
|
125
|
+
|
|
126
|
+
The durable claim record is a single JSON object, versioned via `schema_version` so a reader can
|
|
127
|
+
detect an incompatible future shape before parsing fields it does not understand:
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{
|
|
131
|
+
"schema_version": "1.0",
|
|
132
|
+
"role": "AssignmentClaimRecord",
|
|
133
|
+
"subject_id": "kontourai/flow-agents#290",
|
|
134
|
+
"actor": { "runtime": "claude-code", "session_id": "...", "host": "...", "human": null },
|
|
135
|
+
"claimed_at": "2026-07-02T00:00:00Z",
|
|
136
|
+
"ttl_seconds": 1800,
|
|
137
|
+
"branch": "agent/<actor>/<slug>",
|
|
138
|
+
"artifact_dir": ".kontourai/flow-agents/<slug>",
|
|
139
|
+
"status": "claimed"
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
| Field | Required | Description |
|
|
144
|
+
| --- | --- | --- |
|
|
145
|
+
| `schema_version` | yes | Version of this record shape, `"1.0"`. |
|
|
146
|
+
| `role` | yes | Constant `"AssignmentClaimRecord"`, for readers scanning mixed content (e.g. a GitHub comment thread) for this record type. |
|
|
147
|
+
| `subject_id` | yes | The claimed work item, in `owner/repo#id` form — the same string `workItemSlug` derives the deterministic session slug from. |
|
|
148
|
+
| `actor` | yes | `{ runtime, session_id, host, human? }` — the exact struct `actor-identity.js` defines. `human` is set (non-null) only for a human assignee; its presence, not a username heuristic, gates the human-held join state. |
|
|
149
|
+
| `claimed_at` | yes | ISO-8601 timestamp the claim was recorded. Mirrors the liveness stream's own claim-event field so a reader compares freshness with one mental model across both layers, even though the two are stored in different media. |
|
|
150
|
+
| `ttl_seconds` | yes | Same field name/semantics as the liveness stream's `ttlSeconds` (default `1800`). |
|
|
151
|
+
| `branch` | yes | The branch this actor is working on, per the `agent/<actor>/<slug>` convention. |
|
|
152
|
+
| `artifact_dir` | yes | The deterministic workflow artifact directory for this subject, so a successor inherits the same session. |
|
|
153
|
+
| `status` | yes | `"claimed"` today; future transitions may add `"released"` / `"superseded"` values as the corresponding mutator (see the transition table) is implemented. |
|
|
154
|
+
|
|
155
|
+
**Versioning rule:** bump `schema_version` only on an incompatible change (matching
|
|
156
|
+
`artifact-contract.md`'s existing sidecar rule: "Keep `schema_version` at `1.0` until the schema
|
|
157
|
+
changes incompatibly"). Additive, optional fields do not require a bump.
|
|
158
|
+
|
|
159
|
+
### GitHub mapping
|
|
160
|
+
|
|
161
|
+
The GitHub implementation represents the record as:
|
|
162
|
+
|
|
163
|
+
- **assignee**: the notification/board hook.
|
|
164
|
+
- **a single `agent:claimed` label** (default name, configurable via
|
|
165
|
+
`policy.label_name`): the board filter.
|
|
166
|
+
- **a machine-readable claim comment**: human-readable prose above a fenced JSON block containing
|
|
167
|
+
the record above, located via a fixed marker (default
|
|
168
|
+
`<!-- flow-agents:assignment-claim -->`, configurable via `policy.claim_comment_marker`) so the
|
|
169
|
+
board stays legible to a human without tooling, while remaining machine-parseable.
|
|
170
|
+
|
|
171
|
+
The comment carries identity because the assignee field cannot: N agent sessions typically share
|
|
172
|
+
one GitHub account, so per-session identity lives in the attached record. Each provider decides
|
|
173
|
+
what it can natively represent versus what goes in the record.
|
|
174
|
+
|
|
175
|
+
### local-file mapping
|
|
176
|
+
|
|
177
|
+
For tracker-less repos and evals, the same record is written to a JSON file under the artifact
|
|
178
|
+
root (`<artifact-root>/assignment/<sanitized-subject-id>.json`), full read-modify-write, no
|
|
179
|
+
external process involved. This path is the one that does real I/O inside the CLI, since there is
|
|
180
|
+
no external mutation to defer to a skill.
|
|
181
|
+
|
|
182
|
+
**`--actor-json` asymmetry (fix-plan iteration 1, F5, intentional):** local-file `claim`/`release`
|
|
183
|
+
falls back to auto-resolving the actor from the live environment (`resolveActor(process.env)`) when
|
|
184
|
+
`--actor-json` is omitted; `render-claim`/`render-supersede` (GitHub) always require `--actor-json`
|
|
185
|
+
explicitly and fail loud without it. This is intentional, not a footgun to fix later — the
|
|
186
|
+
currently-wired `pull-work` skill always passes `--actor-json` for both provider kinds, so the
|
|
187
|
+
asymmetry has no effect on the shipped path today, but a future direct-CLI caller relying on
|
|
188
|
+
local-file `claim` to fail the same way `render-claim` does when the actor can't be determined
|
|
189
|
+
should pass `--actor-json` explicitly rather than relying on the auto-resolve fallback.
|
|
190
|
+
|
|
191
|
+
## Implementation Note
|
|
192
|
+
|
|
193
|
+
`schemas/assignment-provider-settings.schema.json` is the settings schema companion to this
|
|
194
|
+
contract — it configures `provider.kind` (`github` | `local-file`), the label name, the claim
|
|
195
|
+
comment marker, and the human-assignee policy knob described above.
|
|
196
|
+
|
|
197
|
+
The GitHub write path follows this repository's `publish-change-helper.ts` precedent — **render,
|
|
198
|
+
don't execute**: the CLI emits the exact, deterministic `gh` argv and comment body for a mutation
|
|
199
|
+
as a pure function; the calling skill runs that exact argv via its Bash tool (never freehand `gh`
|
|
200
|
+
text), then re-fetches and feeds the result back into the CLI's `status` parser to close the round
|
|
201
|
+
trip. This is a deliberate divergence from a literal "CLI shells out to `gh` itself" design: it
|
|
202
|
+
matches the one existing same-shaped precedent in this repository, keeps operational concerns
|
|
203
|
+
(auth, rate limiting, retries, partial-failure sequencing across separate `gh` calls) at the skill
|
|
204
|
+
layer where Bash-tool error handling already lives, and avoids introducing this repository's first
|
|
205
|
+
`execFileSync`-to-`gh` code path inside compiled code without a dedicated decision. A future
|
|
206
|
+
implementer of the GitHub mutation path should read this note, not re-derive the reasoning from
|
|
207
|
+
scratch — see the `#290` plan artifact's Design Decision 1 for the full evidence trail if more
|
|
208
|
+
detail is needed.
|
|
209
|
+
|
|
210
|
+
**`gh_commands` execution contract (fix-plan iteration 1, F4):** every `render-*` subcommand's
|
|
211
|
+
`gh_commands` field is a JSON array of **argv arrays** (one element per `gh` argument), not a
|
|
212
|
+
shell-command string. The calling skill MUST execute each entry as argv — every element passed as
|
|
213
|
+
its own separate Bash-tool argument — and MUST NOT concatenate the elements into a single shell
|
|
214
|
+
string or run them via `bash -c`/shell re-interpretation. This matters specifically because
|
|
215
|
+
`claim_comment_body` (and, for `render-supersede`, `previous_record`) can carry attacker-influenced
|
|
216
|
+
text: any GitHub user who can comment on the issue can post a forged claim-marker comment (see the
|
|
217
|
+
sanitization note below), and reconstructing a shell string from that content would reintroduce a
|
|
218
|
+
shell-injection surface the render/execute split is designed to avoid. This is stated explicitly in
|
|
219
|
+
`kits/builder/skills/pull-work/SKILL.md`'s "Assignment Claim On Selection" section as well — this
|
|
220
|
+
paragraph is the contract-side mirror of that instruction, not a duplicate source of truth to drift
|
|
221
|
+
from it.
|
|
222
|
+
|
|
223
|
+
**Untrusted claim-record fields (fix-plan iteration 1, F2):** `extractClaimRecord()` parses the
|
|
224
|
+
fenced JSON claim record out of *any* issue comment matching the claim marker — posting a comment
|
|
225
|
+
requires no elevated access, unlike the assignee/label mutations this contract otherwise gates. Its
|
|
226
|
+
returned record's string fields (`subject_id`, `branch`, `artifact_dir`, `actor.*`, including
|
|
227
|
+
`actor.human`, and each `audit_trail` entry's actor/`reason`) are therefore treated as untrusted
|
|
228
|
+
display input and are run through a control-character-strip + length-cap sanitizer (mirroring
|
|
229
|
+
`workflow-sidecar.ts`'s `stripControlCharsForDisplay`, the established #287/#320 mitigation for
|
|
230
|
+
this input class) before they leave the module in `status`/`list` output. This is display-only — it
|
|
231
|
+
never changes the assignment ⋈ liveness join's classification logic, only the surfaced string
|
|
232
|
+
content.
|
|
233
|
+
|
|
234
|
+
No part of this system writes to the provider on a timer or heartbeats to it (ADR 0021 §4/§7).
|
|
235
|
+
Every write is triggered by a specific lifecycle moment named in the transition table above. The
|
|
236
|
+
one optional exception is a comment-body refresh at an explicit phase transition
|
|
237
|
+
(`policy.comment_refresh_on_phase_transition`, default `false`) — cheap because it reuses the same
|
|
238
|
+
render path already built for `claim`, just called again with an updated `status`/`claimed_at`
|
|
239
|
+
field.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Builder Kit Workflow State Contract
|
|
2
2
|
|
|
3
|
+
> Read [`context/contracts/standing-directives.md`](standing-directives.md) — ratified owner directives that override default engineering conservatism.
|
|
4
|
+
|
|
3
5
|
This contract defines the durable routing state for Builder Kit build-flow pickup and resume. It keeps `state.json` limited to canonical Flow Agents workflow routing and stores rich pickup decisions in a documented Probe record sidecar referenced by `state.json`, `handoff.json`, and the session artifact.
|
|
4
6
|
|
|
5
7
|
Builder Kit owns product-level build-flow coordination. Flow Agents owns the workflow harness, artifact conventions, primitive execution, and evidence gates. Flow remains the owner of Flow gate semantics. Builder Kit contracts may route to Flow Agents primitives, but must not redefine pass, fail, approval, or release authority semantics.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Decision Registry Contract
|
|
2
2
|
|
|
3
|
+
> Read [`context/contracts/standing-directives.md`](standing-directives.md) — ratified owner directives that override default engineering conservatism.
|
|
4
|
+
|
|
3
5
|
Normative contract for the topic-keyed decision registry. This is the source of
|
|
4
6
|
truth for how NEW decisions are recorded in a Kontour repository. Numbered ADRs
|
|
5
7
|
under `docs/adr/` are frozen history and are never written for new decisions
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Delivery Contract
|
|
2
2
|
|
|
3
|
+
> Read [`context/contracts/standing-directives.md`](standing-directives.md) — ratified owner directives that override default engineering conservatism.
|
|
4
|
+
|
|
3
5
|
Delivery chains planning, execution, review, verification, Goal Fit, and final acceptance until the user-facing goal is genuinely handled.
|
|
4
6
|
|
|
5
7
|
## Workflow
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Execution Contract
|
|
2
2
|
|
|
3
|
+
> Read [`context/contracts/standing-directives.md`](standing-directives.md) — ratified owner directives that override default engineering conservatism.
|
|
4
|
+
|
|
3
5
|
Execution turns an approved plan artifact into code and local evidence while preserving parallel safety.
|
|
4
6
|
|
|
5
7
|
## Required Inputs
|
|
@@ -42,6 +44,29 @@ Execution may upgrade to a stronger mode when risk increases. Downgrades require
|
|
|
42
44
|
- Worker delegation must name the exact worker role (`tool-worker`) rather than spawning an unnamed/default implementation agent.
|
|
43
45
|
- After each wave, collect results, check conflicts, and update the session artifact before starting the next wave.
|
|
44
46
|
|
|
47
|
+
## Delegation: Model Routing
|
|
48
|
+
|
|
49
|
+
Model-routing policy is data, not code: `.datum/config.json` (schema:
|
|
50
|
+
`@kontourai/datum`, provider/role registry) is the source of truth for which
|
|
51
|
+
model backs which delegate role. This contract only says where to read it.
|
|
52
|
+
|
|
53
|
+
- When spawning a delegate, resolve its role via `npx @kontourai/datum resolve <role> --json`
|
|
54
|
+
(or the `@kontourai/datum` library's `resolve()`) and pass the resolved
|
|
55
|
+
`model` explicitly to the delegate invocation. Do not hardcode a model name
|
|
56
|
+
in a skill, agent definition, or generated file — the role name is the
|
|
57
|
+
stable reference; the model it resolves to can change without touching
|
|
58
|
+
delegation call sites.
|
|
59
|
+
- Role selection follows task shape, not delegate identity: fully-specified
|
|
60
|
+
mechanical tasks resolve `delegate-mechanical`; precisely-planned
|
|
61
|
+
implementation tasks resolve `delegate-implementation`; tasks needing design
|
|
62
|
+
latitude resolve `delegate-design`. The orchestrator's own model (planning,
|
|
63
|
+
gates, adversarial verification) resolves `orchestrator`, typically inherited
|
|
64
|
+
rather than overridden.
|
|
65
|
+
- When `datum` (the CLI/library) or `.datum/config.json` is absent or a role
|
|
66
|
+
fails to resolve, fall back to the runtime's inherited model and note the
|
|
67
|
+
fallback in the session/task artifact — do not block delegation on datum
|
|
68
|
+
being present.
|
|
69
|
+
|
|
45
70
|
## Completion Rules
|
|
46
71
|
|
|
47
72
|
Execution is complete only when:
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Governance Adapter Contract
|
|
2
2
|
|
|
3
|
+
> Read [`context/contracts/standing-directives.md`](standing-directives.md) — ratified owner directives that override default engineering conservatism.
|
|
4
|
+
|
|
3
5
|
Governance adapters let Flow Agents ask an external tool for policy, proof, or trust evidence without baking repo-specific policy into Flow Agents core.
|
|
4
6
|
|
|
5
7
|
## Boundary
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# Knowledge Store Provider Contract
|
|
2
|
+
|
|
3
|
+
Normative contract for the Knowledge Kit's typed graph MODEL and its pluggable
|
|
4
|
+
storage/sync PROVIDERS. The model (nodes, edges, provenance) is owned by the Kit;
|
|
5
|
+
storage and synchronisation are provider concerns. The same ingest/link/health
|
|
6
|
+
verbs run over every provider, so backlog hygiene is a knowledge-health pass over
|
|
7
|
+
the work-item provider rather than a bespoke tool.
|
|
8
|
+
|
|
9
|
+
Machine-checkable structure lives in `schemas/knowledge/*.schema.json`
|
|
10
|
+
(`node`, `edge`, `proposal`, `health-report`). Reference implementations live in
|
|
11
|
+
`kits/knowledge/providers/` (markdown-vault, git-repo, work-item) with health
|
|
12
|
+
verbs in `kits/knowledge/providers/health/` and the conformance suite in
|
|
13
|
+
`kits/knowledge/providers/conformance/`.
|
|
14
|
+
|
|
15
|
+
This contract applies the portfolio provider pattern (hachure format/adapters;
|
|
16
|
+
Builder Kit work-item contract/providers) to knowledge, which until now was fused
|
|
17
|
+
to one storage shape (the markdown vault).
|
|
18
|
+
|
|
19
|
+
## 1. Graph model
|
|
20
|
+
|
|
21
|
+
### 1.1 Node
|
|
22
|
+
|
|
23
|
+
A node is a typed, identified unit of knowledge. Validated by
|
|
24
|
+
`schemas/knowledge/node.schema.json`.
|
|
25
|
+
|
|
26
|
+
| Field | Required | Meaning |
|
|
27
|
+
| --- | --- | --- |
|
|
28
|
+
| `id` | yes | Provider-scoped stable id, unique within a single `readGraph` result. |
|
|
29
|
+
| `type` | yes | Node type (see §1.3). EXTENSIBLE. |
|
|
30
|
+
| `title` | yes | Human-readable title; the basis for duplicate detection. |
|
|
31
|
+
| `body` | no | Primary content; format is provider/type-specific. |
|
|
32
|
+
| `attributes` | no | Provider-specific structured fields (issue state/labels, decision status, note category/tags). |
|
|
33
|
+
| `provenance` | yes | Where this node was read from (§1.4). |
|
|
34
|
+
|
|
35
|
+
### 1.2 Edge
|
|
36
|
+
|
|
37
|
+
An edge is a typed, directed relationship. Validated by
|
|
38
|
+
`schemas/knowledge/edge.schema.json`.
|
|
39
|
+
|
|
40
|
+
| Field | Required | Meaning |
|
|
41
|
+
| --- | --- | --- |
|
|
42
|
+
| `id` | yes | Provider-scoped stable edge id. |
|
|
43
|
+
| `type` | yes | One of the CLOSED edge vocabulary (§1.3). |
|
|
44
|
+
| `from` | yes | Source node id. |
|
|
45
|
+
| `to` | yes | Target node id. |
|
|
46
|
+
| `resolved` | no | `true` (default) means `to` is expected to resolve to a node in the same graph (an internal dependency link); `false` marks a deliberate external reference (e.g. `evidence-of` a PR outside the store). |
|
|
47
|
+
| `attributes` | no | Provider-specific structured fields. |
|
|
48
|
+
| `provenance` | yes | Where this edge was derived from (§1.4). |
|
|
49
|
+
|
|
50
|
+
### 1.3 Vocabularies
|
|
51
|
+
|
|
52
|
+
**Node types are EXTENSIBLE.** The recommended core vocabulary is `note`,
|
|
53
|
+
`decision`, `issue`, `session`, `person`. Providers MAY emit additional types;
|
|
54
|
+
consumers MUST NOT reject unknown node types.
|
|
55
|
+
|
|
56
|
+
**Edge types are CLOSED** (schema-enforced enum):
|
|
57
|
+
|
|
58
|
+
| Edge type | Direction | Meaning |
|
|
59
|
+
| --- | --- | --- |
|
|
60
|
+
| `supersedes` | from → to | `from` replaces `to`. |
|
|
61
|
+
| `merged-into` | from → to | `from` was folded into `to`. |
|
|
62
|
+
| `blocks` | from → to | `from` must complete before `to`. |
|
|
63
|
+
| `evidence-of` | from → to | `from` is provenance/evidence for `to`. |
|
|
64
|
+
| `mentions` | from → to | `from` references `to` in prose. |
|
|
65
|
+
| `relates` | from → to | General association. |
|
|
66
|
+
|
|
67
|
+
Adding an edge type is a contract change (schema + this table), because health
|
|
68
|
+
verbs reason over the closed vocabulary (e.g. `blocks` is the dependency-link
|
|
69
|
+
relation).
|
|
70
|
+
|
|
71
|
+
### 1.4 Provenance
|
|
72
|
+
|
|
73
|
+
Provenance appears on BOTH nodes and edges. Every assertion in the graph is
|
|
74
|
+
traceable back to the store it came from — no orphan facts.
|
|
75
|
+
|
|
76
|
+
| Field | Required | Meaning |
|
|
77
|
+
| --- | --- | --- |
|
|
78
|
+
| `provider` | yes | Provider id that produced the element. |
|
|
79
|
+
| `source` | yes | Concrete origin: a file path, an issue ref, or a URL. |
|
|
80
|
+
| `locator` | no | Finer locator (line, anchor, frontmatter field, link kind). |
|
|
81
|
+
| `retrieved_at` | yes | ISO-8601 read timestamp. |
|
|
82
|
+
| `agent` | no | Agent/process id that performed the read. |
|
|
83
|
+
|
|
84
|
+
## 2. Provider interface
|
|
85
|
+
|
|
86
|
+
A provider is an ESM module exporting a default class constructed with a
|
|
87
|
+
provider-specific options object. Every provider implements the READ interface
|
|
88
|
+
and the PROPOSALS-ONLY write interface.
|
|
89
|
+
|
|
90
|
+
### 2.1 Read
|
|
91
|
+
|
|
92
|
+
| Method | Signature | Behaviour |
|
|
93
|
+
| --- | --- | --- |
|
|
94
|
+
| `capabilities()` | `() => Capabilities` | Static description (§2.3). Synchronous. |
|
|
95
|
+
| `readNodes(options?)` | `(o?) => Promise<Node[]>` | All nodes; `options.type` filters by node type. Every node schema-valid. |
|
|
96
|
+
| `readEdges()` | `() => Promise<Edge[]>` | All edges; every edge schema-valid and in the closed vocabulary. |
|
|
97
|
+
| `queryByType(type)` | `(t) => Promise<Node[]>` | Convenience: the nodes of one type (a consistent subset of `readNodes`). |
|
|
98
|
+
| `readGraph()` | `() => Promise<{nodes, edges}>` | The full graph. |
|
|
99
|
+
|
|
100
|
+
### 2.2 Write — proposals only
|
|
101
|
+
|
|
102
|
+
Knowledge stores are HUMAN-CURATED. No provider auto-writes to a store. The only
|
|
103
|
+
write surface is:
|
|
104
|
+
|
|
105
|
+
| Method | Signature | Behaviour |
|
|
106
|
+
| --- | --- | --- |
|
|
107
|
+
| `proposeWrite(intent)` | `(i) => Promise<Proposal>` | Returns a `Proposal` (§2.4) describing an intended change. MUST NOT mutate the store, disk, or the remote board. |
|
|
108
|
+
|
|
109
|
+
**How proposals-only is expressed structurally:** the `Proposal` schema fixes
|
|
110
|
+
`status` to the const `"proposed"`. A provider can never return an applied
|
|
111
|
+
proposal, and the conformance suite asserts that `readNodes()` is byte-stable
|
|
112
|
+
across a `proposeWrite` call. Enactment happens DOWNSTREAM of the provider:
|
|
113
|
+
|
|
114
|
+
- **git-repo** renders a decision-registry topic file (frontmatter compatible
|
|
115
|
+
with `schemas/decision-record.schema.json`) shaped for the **promote sub-flow**
|
|
116
|
+
(`docs/decisions/promotion-gate.md`). The promote step is the enactor.
|
|
117
|
+
- **work-item** renders a draft `gh issue comment` / `gh issue edit --add-label`
|
|
118
|
+
the operator files. The provider never runs a mutating `gh` command.
|
|
119
|
+
- **markdown-vault** renders a note in native frontmatter + `[[wikilink]]` form
|
|
120
|
+
for the Knowledge Kit ingest/compile flow to file.
|
|
121
|
+
|
|
122
|
+
This is the same proposals-only discipline as the store contract's
|
|
123
|
+
`propose → apply/reject` gate and the ADR-0003-style "proposals, never silent
|
|
124
|
+
writes to a curated store" precedent. A provider is the propose half; a human or
|
|
125
|
+
a gated flow is the apply half.
|
|
126
|
+
|
|
127
|
+
### 2.3 Capabilities
|
|
128
|
+
|
|
129
|
+
`capabilities()` returns `{ id, node_types, edge_types, writable, write_mode,
|
|
130
|
+
proposal_targets, source_of_truth }`. `writable` is always `false` and
|
|
131
|
+
`write_mode` is always `"proposals-only"` in this version — a graph-database
|
|
132
|
+
provider that owns its store is a separate, gated spike (issue #318), not a
|
|
133
|
+
loophole here.
|
|
134
|
+
|
|
135
|
+
### 2.4 Proposal
|
|
136
|
+
|
|
137
|
+
Validated by `schemas/knowledge/proposal.schema.json`.
|
|
138
|
+
|
|
139
|
+
| Field | Required | Meaning |
|
|
140
|
+
| --- | --- | --- |
|
|
141
|
+
| `schema_version` | yes | `"1.0"`. |
|
|
142
|
+
| `provider` | yes | Emitting provider id. |
|
|
143
|
+
| `kind` | yes | `create-node` \| `update-node` \| `add-edge` \| `comment` \| `label` \| `decision-topic`. |
|
|
144
|
+
| `target` | yes | Where the change would land (descriptive only). |
|
|
145
|
+
| `payload` | no | The structured node/edge/field proposed. |
|
|
146
|
+
| `rendered` | no | The provider-native form an enactor would apply. |
|
|
147
|
+
| `status` | yes | The const `"proposed"`. |
|
|
148
|
+
| `rationale` | no | Why the change is proposed. |
|
|
149
|
+
| `provenance` | yes | §1.4. |
|
|
150
|
+
|
|
151
|
+
## 3. Health verbs
|
|
152
|
+
|
|
153
|
+
Health verbs are PROVIDER-AGNOSTIC pure functions over a graph
|
|
154
|
+
(`{ nodes, edges }`) — they never inspect provider internals, which is what lets
|
|
155
|
+
one health command run identically over any provider (R4). Each returns a
|
|
156
|
+
schema-valid Knowledge Health Report
|
|
157
|
+
(`schemas/knowledge/health-report.schema.json`). Reference verbs live in
|
|
158
|
+
`kits/knowledge/providers/health/`.
|
|
159
|
+
|
|
160
|
+
| Verb | Report `check` | Behaviour |
|
|
161
|
+
| --- | --- | --- |
|
|
162
|
+
| `detectDuplicates(graph, o?)` | `duplicate-detection` | Flags node pairs whose titles match / are highly similar (token Jaccard ≥ `threshold`, default 0.7; same-type by default). |
|
|
163
|
+
| `checkDependencyLinkIntegrity(graph, o?)` | `dependency-link-integrity` | Flags dependency edges (default type `blocks`) whose endpoints are missing from the graph, unless the edge is `resolved:false` (deliberate external ref). |
|
|
164
|
+
|
|
165
|
+
Every finding cites its evidence (the compared titles + similarity, or the edge
|
|
166
|
+
+ which endpoint is missing). A report's `summary.finding_count` MUST equal
|
|
167
|
+
`findings.length`.
|
|
168
|
+
|
|
169
|
+
## 4. Reference providers
|
|
170
|
+
|
|
171
|
+
| Provider | Reads | Node types | Write proposal |
|
|
172
|
+
| --- | --- | --- | --- |
|
|
173
|
+
| `markdown-vault` | The existing Knowledge Kit store (markdown + frontmatter + `[[wikilinks]]` + graph index) via an existing store adapter — thin wrapper, existing skills unaffected. | `note`, `person` | `create-node` rendered as a native vault note. |
|
|
174
|
+
| `git-repo` | `docs/decisions/*` (tombstones → `supersedes`/`merged-into`; `evidence[]` → `evidence-of`), CONTEXT.md glossary, `docs/learnings/*`. | `decision`, `note` | `decision-topic` shaped for the promote sub-flow. |
|
|
175
|
+
| `work-item` | GitHub issues via an INJECTABLE runner (default `gh`), `flow-agents:work-item-metadata` blockers + prose refs → `blocks`/`relates`. | `issue` | `comment` / `label` draft. |
|
|
176
|
+
|
|
177
|
+
## 5. Conformance
|
|
178
|
+
|
|
179
|
+
`kits/knowledge/providers/conformance/suite.test.js` is the parameterized
|
|
180
|
+
conformance suite EVERY provider must pass (issue #317, AC3). It asserts:
|
|
181
|
+
capabilities declare proposals-only/non-writable; `readNodes` returns unique,
|
|
182
|
+
schema-valid nodes with provider provenance; `readEdges` returns schema-valid
|
|
183
|
+
edges in the closed vocabulary; `queryByType` is a consistent subset of
|
|
184
|
+
`readNodes`; `readGraph` returns `{nodes, edges}`; and `proposeWrite` returns a
|
|
185
|
+
schema-valid `"proposed"` proposal that mutates nothing.
|
|
186
|
+
|
|
187
|
+
`kits/knowledge/providers/health/health-pass.test.js` covers AC1 (the same
|
|
188
|
+
health command over vault + git-repo yields schema-valid reports) and AC2 (a
|
|
189
|
+
backlog pass over the work-item adapter, driven by a SEEDED fixture, flags a
|
|
190
|
+
duplicate and a broken blocker link — never the real board).
|
|
191
|
+
|
|
192
|
+
## 6. Non-goals
|
|
193
|
+
|
|
194
|
+
Graph-database provider (issue #318 spike; adoption gated on a real query failing
|
|
195
|
+
over files); embeddings; auto-writes to any human-curated store; personal-vault
|
|
196
|
+
feature changes. This contract adds a model + read/propose interface over stores
|
|
197
|
+
operated today; it does not change how those stores are curated.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Planning Contract
|
|
2
2
|
|
|
3
|
+
> Read [`context/contracts/standing-directives.md`](standing-directives.md) — ratified owner directives that override default engineering conservatism.
|
|
4
|
+
|
|
3
5
|
Planning turns a user goal into an executable implementation plan without writing production code.
|
|
4
6
|
|
|
5
7
|
## Required Inputs
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Review Contract
|
|
2
2
|
|
|
3
|
+
> Read [`context/contracts/standing-directives.md`](standing-directives.md) — ratified owner directives that override default engineering conservatism.
|
|
4
|
+
|
|
3
5
|
Review is report-only critique. It asks whether the changed code is maintainable, secure, consistent with project standards, and structurally sound before verification proves behavior.
|
|
4
6
|
|
|
5
7
|
## Purpose
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Sandbox Policy Contract
|
|
2
2
|
|
|
3
|
+
> Read [`context/contracts/standing-directives.md`](standing-directives.md) — ratified owner directives that override default engineering conservatism.
|
|
4
|
+
|
|
3
5
|
Workflow artifacts must name the execution boundary required for the work. The sandbox mode is a planning and delegation contract, not a substitute for the runtime permission model.
|
|
4
6
|
|
|
5
7
|
## Canonical Modes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Standing Directives Contract
|
|
2
|
+
|
|
3
|
+
Ratified owner directives are corrections and policies the owner has explicitly settled across sessions. They override default engineering conservatism (e.g. "keep the old path working just in case") wherever they apply. Each directive below is a durable, quotable statement — cite the number, not a paraphrase from memory. This file exists so a delegated agent that only sees one task in a plan still receives the same standing policy the orchestrator ratified; correction that lives only in one session's ephemeral context does not reach the agents who need it.
|
|
4
|
+
|
|
5
|
+
Read this file alongside the phase contract for the work you are doing. When a standing directive and a phase contract's default guidance conflict, the standing directive wins; if you believe a directive does not fit the situation, stop and report the conflict rather than silently picking a side.
|
|
6
|
+
|
|
7
|
+
## Directives
|
|
8
|
+
|
|
9
|
+
1. **No legacy fallbacks: migrate hard.** A compatibility path that keeps defective or superseded behavior reachable is prohibited regardless of how short-lived or self-healing it is; the remedy for old artifacts is a loud typed error naming the regeneration command. (Ratified July 2026. Evidence: [datum#3](https://github.com/kontourai/datum/pull/3) hard cutover to `.datum/config.json`; the fallback-removal follow-up to [flow-agents#344](https://github.com/kontourai/flow-agents/pull/344), tracked as [flow-agents#347](https://github.com/kontourai/flow-agents/issues/347).)
|
|
10
|
+
2. **Durable vs runtime paths: never invert them.** `.kontourai/` is gitignored runtime state; `.<product>/` (e.g. `.veritas/`, `.datum/`) is a product's durable, committed directory in consuming repos. (Ratified July 2026. Evidence: `.veritas/` precedent and the `.kontourai/` vs `.veritas/` distinction in [docs/repository-structure.md](../../docs/repository-structure.md); [datum#3](https://github.com/kontourai/datum/pull/3) `.datum/config.json`; [surface#110](https://github.com/kontourai/surface/issues/110), [surface#113](https://github.com/kontourai/surface/pull/113).)
|
|
11
|
+
3. **Evidence must be executable.** Check summaries/excerpts are runnable-from-repo-root commands (`true # ...` for prose that has no command); probe scripts live inside the session dir; reconcilable claims use manifest-exact bare labels. (Ratified July 2026.)
|
|
12
|
+
4. **Standalone-first, then integrate.** Build pieces to provide value alone, then push them through a real product integration to pressure-test the abstractions; file upstream issues for friction found during integration rather than working around it. (Ratified July 2026.)
|
|
13
|
+
5. **Regression rule for cutovers.** Proper before/after tests are required for any cutover; large regressions (e.g. more than 40% record loss, or a whole field-class disappearing) are surfaced as an explicit owner decision with data, never papered over — but a large regression does not block the cutover by default. (Ratified July 2026.)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Verification Contract
|
|
2
2
|
|
|
3
|
+
> Read [`context/contracts/standing-directives.md`](standing-directives.md) — ratified owner directives that override default engineering conservatism.
|
|
4
|
+
|
|
3
5
|
Verification is report-only. It proves whether the implementation satisfies the plan, the Definition Of Done, and the original user outcome.
|
|
4
6
|
|
|
5
7
|
## Required Inputs
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Work Item Contract
|
|
2
2
|
|
|
3
|
+
> Read [`context/contracts/standing-directives.md`](standing-directives.md) — ratified owner directives that override default engineering conservatism.
|
|
4
|
+
|
|
3
5
|
This contract defines the provider-neutral vocabulary for selecting, planning, and handing off backlog work. It is the source shape for provider-backed workflows such as `pull-work`; provider-specific adapters map into this model without making GitHub, Jira, Linear, or any other provider the generic language.
|
|
4
6
|
|
|
5
7
|
## Provider Roles
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../../schemas/assignment-provider-settings.schema.json",
|
|
3
|
+
"schema_version": "1.0",
|
|
4
|
+
"projects": [
|
|
5
|
+
{
|
|
6
|
+
"project": {
|
|
7
|
+
"repo": {
|
|
8
|
+
"owner": "kontourai",
|
|
9
|
+
"name": "flow-agents",
|
|
10
|
+
"url": "https://github.com/kontourai/flow-agents"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"provider": {
|
|
14
|
+
"kind": "github",
|
|
15
|
+
"repo": {
|
|
16
|
+
"owner": "kontourai",
|
|
17
|
+
"name": "flow-agents",
|
|
18
|
+
"url": "https://github.com/kontourai/flow-agents"
|
|
19
|
+
},
|
|
20
|
+
"capabilities": ["assignees", "labels", "comments"]
|
|
21
|
+
},
|
|
22
|
+
"policy": {
|
|
23
|
+
"label_name": "agent:claimed",
|
|
24
|
+
"claim_comment_marker": "<!-- flow-agents:assignment-claim -->",
|
|
25
|
+
"human_assignee_policy": {
|
|
26
|
+
"behavior": "ask_first",
|
|
27
|
+
"idle_threshold_days": 3
|
|
28
|
+
},
|
|
29
|
+
"comment_refresh_on_phase_transition": false
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|