@momentiq/dark-factory-cli 2.13.1 → 2.14.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.
@@ -0,0 +1,220 @@
1
+ ---
2
+ name: objectives
3
+ description: Use at PLAN TIME for any PR that implements a cycle or issue's acceptance criteria — author the verifiable objectives contract before writing code. Run `df objectives derive --cycle <N> --apply` to generate .darkfactory/objectives.yaml from the linked cycle doc's Exit criteria, bind each objective's attestedBy to a real route or test, surface the manifest in your plan for agreement, then declare victory at closeout with `df prove` (not free-text "done").
4
+ ---
5
+
6
+ # /objectives — plan-time verifiable objectives authoring
7
+
8
+ Verifiable objectives make "this PR is done" a **derived claim backed by
9
+ evidence**, not a free-text assertion. This skill tells you how to author
10
+ that contract at plan time for {{REPO_NAME}} so the gate has something to
11
+ prove — and how to close the loop at PR completion.
12
+
13
+ ## When this runs
14
+
15
+ At **plan time** — before writing implementation code — for any PR that
16
+ implements a cycle or issue's acceptance criteria. Objectives are the
17
+ explicit, agreed contract of the work; they belong in the plan, not appended
18
+ after the fact at PR close.
19
+
20
+ The full flow:
21
+
22
+ 1. **Derive** — generate the manifest from the cycle doc's Exit criteria.
23
+ 2. **Bind** — fill each objective's `attestedBy` with real proof (route / test).
24
+ 3. **Agree** — surface objectives in the plan; plan approval is the agreement.
25
+ 4. **Check** — verify locally before committing.
26
+ 5. **Prove** — declare victory at closeout with `df prove`.
27
+
28
+ ## 1. Derive — don't hand-write
29
+
30
+ Run `df objectives derive` to generate `.darkfactory/objectives.yaml` from
31
+ the linked cycle doc's `## Exit criteria` section. Each criterion becomes one
32
+ `Objective`, bound to its verbatim text via a `text-hash` `sourceCriterion`:
33
+
34
+ ```bash
35
+ # Resolve the PR's linked cycle doc and derive objectives from its Exit criteria.
36
+ # --apply writes .darkfactory/objectives.yaml (default prints to stdout).
37
+ df objectives derive --cycle <N> --apply
38
+ ```
39
+
40
+ The command reads `docs/roadmap/cycles/cycle<N>-*.md`, extracts every
41
+ `- EC<k>: …` list item, and emits a manifest like:
42
+
43
+ ```yaml
44
+ schemaVersion: 1
45
+ objectives:
46
+ - id: "cycle23#ec1"
47
+ source: { kind: cycle, ref: "23" }
48
+ text: "Route table is populated from the diff in under 500 ms."
49
+ attestedBy: [] # ← fill this in step 2
50
+ enforced: false
51
+ sourceCriterion:
52
+ kind: text-hash
53
+ locator: exit_criteria#ec1
54
+ sha256: <sha256 of canonicalizeCriterion(text)>
55
+ ```
56
+
57
+ **Idempotence:** re-running `derive` on an existing manifest preserves each
58
+ objective's `attestedBy` bindings — it never clobbers evidence you filled in.
59
+
60
+ ## 2. Bind — real proof, not wishful labels
61
+
62
+ Each objective needs an `attestedBy` entry that actually proves the criterion
63
+ rather than just restating that the PR shipped. Two kinds of real proof:
64
+
65
+ ```yaml
66
+ attestedBy:
67
+ # A `df verify` route — diff-bound exit code from a named producer.
68
+ - kind: route
69
+ routeId: targeted-tests # or: terraform, playwright, docker, …
70
+
71
+ # A named test or test pattern inside a route's output.
72
+ - kind: test
73
+ testId: "services/worker/**/*.test.ts"
74
+ ```
75
+
76
+ **Why `critic` bindings are a weak on-ramp only:**
77
+
78
+ ```yaml
79
+ attestedBy:
80
+ - kind: critic
81
+ criticId: codex # ← on-ramp only — see caveat below
82
+ ```
83
+
84
+ The worker reads `.darkfactory/objectives.yaml` *after* critics run and
85
+ joins verdicts post-hoc. A `critic` binding therefore only proves "the gate
86
+ passed" per objective — it does **not** verify that the specific criterion
87
+ was satisfied by this change. Use it only when no route or test yet covers
88
+ the criterion and you want the objective tracked from day one. Always label
89
+ critic-only bindings as an on-ramp and plan to upgrade them to route/test
90
+ evidence.
91
+
92
+ **Prefer route + test:** a `route` binding is diff-bound (`df verify` stamps
93
+ `diffHash`-bound `QualityGateEvidence`); a `test` binding names the exact
94
+ check. Both prove the criterion independently, not merely "critic approved."
95
+
96
+ ## 3. Agree — plan approval is the contract
97
+
98
+ Surface the derived objectives in your plan. Example plan entry:
99
+
100
+ ```
101
+ ## Objectives (.darkfactory/objectives.yaml)
102
+ Generated from Cycle 23 exit criteria — 3 objectives:
103
+
104
+ - cycle23#ec1 — Route table populated (attestedBy: route:targeted-tests)
105
+ - cycle23#ec2 — Panel renders in under 500 ms (attestedBy: route:playwright)
106
+ - cycle23#ec3 — Bypass is audited (attestedBy: test:audit-trail.test.ts)
107
+
108
+ Plan approval = agreement on these objectives.
109
+ ```
110
+
111
+ **Why agreement matters:** the objectives manifest is the agreed contract.
112
+ If the plan is approved without reviewing objectives, criterion drift goes
113
+ undetected — a critic later flags "done but not verified" precisely because
114
+ no one agreed what "verified" meant up front.
115
+
116
+ ## 4. Verify locally before committing
117
+
118
+ ```bash
119
+ # Mirror the gate's text-hash verification — catches criterion drift early.
120
+ df objectives check
121
+ ```
122
+
123
+ Exit-code contract:
124
+ - **0** — all `text-hash` bindings match the in-repo cycle doc. `inferred`
125
+ objectives emit an informational note (not a failure). Also returned when
126
+ no `.darkfactory/objectives.yaml` exists — missing manifest is not a
127
+ failure ("nothing to check").
128
+ - **1** — one or more `text-hash` sha256 values don't match (the criterion
129
+ text drifted from the manifest). Re-run `df objectives derive` or fix the
130
+ manifest, then re-check.
131
+ - **2** — usage error (bad flags).
132
+
133
+ Run this after every edit to objectives.yaml and before the final commit.
134
+
135
+ ## 5. Provenance ladder
136
+
137
+ Every objective has a `sourceCriterion` that records how the binding was
138
+ established:
139
+
140
+ | `kind` | Meaning | Gate behavior |
141
+ |---|---|---|
142
+ | `text-hash` | Criterion text is verbatim + sha256-bound to the cycle doc. | Gate verifies the hash. |
143
+ | `inferred` | Criteria were LLM-drafted but not yet ratified by a human. | Non-blocking note — never a gate failure. |
144
+ | `human-reviewed` | A human reviewed the criterion text (no hash required). | Passes the provenance check. |
145
+ | `agent-asserted` | No `sourceCriterion` set — agent-created without binding. | Weakest — upgrade to `text-hash`. |
146
+
147
+ **Ratification flow (when criteria were inferred):**
148
+
149
+ 1. A human reads the `text:` field in `objectives.yaml` — is the criterion
150
+ correct and complete?
151
+ 2. If yes, flip `kind: inferred` → `kind: text-hash` (same `locator` + `sha256`).
152
+ This is an auditable diff: the changed line is the ratification event.
153
+ 3. Re-run `df objectives check` — it now verifies the hash.
154
+
155
+ ```yaml
156
+ # Before ratification (non-blocking note):
157
+ sourceCriterion:
158
+ kind: inferred
159
+ locator: exit_criteria#ec1
160
+ sha256: <sha256 of canonicalizeCriterion(text)>
161
+
162
+ # After ratification (gate-verified):
163
+ sourceCriterion:
164
+ kind: text-hash
165
+ locator: exit_criteria#ec1
166
+ sha256: <sha256 of canonicalizeCriterion(text)>
167
+ ```
168
+
169
+ If you need the sha256 for a criterion text you have in hand:
170
+
171
+ ```bash
172
+ df objectives hash --text "- **EC1**: Route table populated from diff."
173
+ ```
174
+
175
+ ## 6. Closeout — declare victory with proof, not "done"
176
+
177
+ At PR closeout, run `df prove` to join each objective against the evidence
178
+ and report, per objective, **proven / pending / failed**:
179
+
180
+ ```bash
181
+ df prove # human readout: per-objective proven/pending/failed
182
+ df prove --json # BoundProofRecord (for agents / the df_prove MCP tool)
183
+ df prove --strict # exit 1 if ANY objective is not proven (gate form)
184
+ ```
185
+
186
+ An agent's final turn runs `df prove` and **cites that readout as the
187
+ completion claim** — evidence-backed, not free-text "done."
188
+
189
+ - **`proven`** — all `attestedBy` bindings produced passing evidence.
190
+ - **`pending`** — a `critic` binding is pending until the fleet runs; a
191
+ `route` binding you can satisfy now with `df verify`. Pending is honest,
192
+ not a failure — fix it before declaring done.
193
+ - **`failed`** — evidence is negative. Fix the change, re-verify, re-prove.
194
+
195
+ ## Quick-reference
196
+
197
+ ```bash
198
+ # 1. Derive objectives from Cycle 23's exit criteria:
199
+ df objectives derive --cycle 23 --apply
200
+
201
+ # 2. Edit .darkfactory/objectives.yaml — fill attestedBy for each objective.
202
+
203
+ # 3. Verify the text-hash bindings match the cycle doc:
204
+ df objectives check
205
+
206
+ # 4. Commit objectives.yaml alongside the implementation.
207
+
208
+ # 5. At closeout — proven readout:
209
+ df prove
210
+ ```
211
+
212
+ ## Trust boundary
213
+
214
+ The `df prove` readout is *agent-attested, evidence-backed* — stronger than
215
+ free-text "done" (every status is derived, not asserted), but not yet
216
+ independent verification. The ratchet: v1 objectives default to
217
+ `enforced: false` (`df prove` exits 0 and surfaces pending/failed). Flip an
218
+ objective to `enforced: true`, or run `df prove --strict` (e.g. a
219
+ `.husky/pre-push` step), to turn unproven objectives into a hard block with
220
+ no code change.
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "../skill-schema.json",
3
+ "name": "objectives",
4
+ "version": "1.0.0",
5
+ "summary": "Author verifiable objectives at plan time — derive .darkfactory/objectives.yaml from cycle-doc exit criteria, bind attestedBy to real route/test evidence, agree the contract, and declare victory with df prove at closeout.",
6
+ "originatingRepo": "momentiq-ai/dark-factory",
7
+ "files": [
8
+ { "template": "SKILL.md.tmpl", "target": "SKILL.md" }
9
+ ],
10
+ "variables": {
11
+ "REPO_NAME": {
12
+ "description": "Display name of the consumer repo (e.g. 'Dark Factory Platform').",
13
+ "source": "darkfactory.yaml: repo.displayName",
14
+ "default": "this repo"
15
+ }
16
+ }
17
+ }