@godv61/dsh-task-engine 0.23.9 → 0.25.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/.acceptance.mjs +151 -0
- package/.assessment-batch1.mjs +423 -0
- package/.e2e-presets.mjs +230 -0
- package/.enforce-test.mjs +139 -0
- package/.evidence-test.mjs +119 -0
- package/.filter-test.mjs +93 -0
- package/.freeze-test.mjs +199 -0
- package/.hook-consistency.mjs +60 -0
- package/.hook-test.mjs +8 -3
- package/.p0-test.mjs +141 -50
- package/.revision-test.mjs +114 -0
- package/.roundtrip-test.mjs +63 -0
- package/.workflow-test.mjs +94 -65
- package/README.md +4 -2
- package/defaults/eng.json +45 -6
- package/docs/BRIEF-FOR-REVIEW.md +163 -0
- package/docs/CHANGELOG.md +96 -0
- package/docs/configuration.md +31 -6
- package/hooks/commit-msg +162 -65
- package/lib/client.js +638 -431
- package/lib/client.js.map +3 -3
- package/lib/controller.d.ts +18 -1
- package/lib/controller.js +64 -5
- package/lib/controller.js.map +1 -1
- package/lib/dev-task.js +363 -47
- package/lib/dev-task.js.map +1 -1
- package/lib/engine.d.ts +368 -6
- package/lib/engine.js +328 -13
- package/lib/engine.js.map +1 -1
- package/lib/hook.js +14 -4
- package/lib/hook.js.map +1 -1
- package/lib/skill-audit.d.ts +14 -3
- package/lib/skill-audit.js +71 -4
- package/lib/skill-audit.js.map +1 -1
- package/lib/workflows.d.ts +75 -12
- package/lib/workflows.js +213 -77
- package/lib/workflows.js.map +1 -1
- package/package.json +14 -4
- package/scripts/verify-package.mjs +1 -1
package/lib/engine.d.ts
CHANGED
|
@@ -42,13 +42,107 @@ export interface CommitRule {
|
|
|
42
42
|
/** When true (default), a commit may only touch files listed in the task's `files`. */
|
|
43
43
|
file_scope: boolean;
|
|
44
44
|
}
|
|
45
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* A resource reference that names where the resource lives.
|
|
47
|
+
*
|
|
48
|
+
* A bare name is ambiguous once project and user directories can both hold one:
|
|
49
|
+
* `coding-conventions` in a project and `coding-conventions` in the user home are
|
|
50
|
+
* different resources that happen to share a name, and a binding written as a
|
|
51
|
+
* plain string cannot say which was meant. Every stored reference therefore
|
|
52
|
+
* carries its source layer, and a legacy bare name is resolved by the documented
|
|
53
|
+
* precedence and recorded as the layer it resolved to.
|
|
54
|
+
*/
|
|
55
|
+
export interface ResourceRef {
|
|
56
|
+
/** Source layer the resource belongs to. */
|
|
57
|
+
source: ResourceSource;
|
|
58
|
+
/** Resource name within that layer. */
|
|
59
|
+
name: string;
|
|
60
|
+
}
|
|
61
|
+
/** Where a skill or rule came from. `bundled` ships with the plugin. */
|
|
62
|
+
export type ResourceSource = 'bundled' | 'project' | 'user';
|
|
63
|
+
/** Render a reference as `source:name`, the form used in config and status output. */
|
|
64
|
+
export declare function formatResourceRef(ref: ResourceRef): string;
|
|
65
|
+
/**
|
|
66
|
+
* Parse a `source:name` reference. Returns undefined for a bare name, which is
|
|
67
|
+
* the legacy shape and must go through precedence resolution instead.
|
|
68
|
+
* @param text - the stored reference text.
|
|
69
|
+
* @returns the parsed reference, or undefined when it carries no source.
|
|
70
|
+
*/
|
|
71
|
+
export declare function parseResourceRef(text: string): ResourceRef | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* One skill bound to a stage, with the complete list of rules that apply to it.
|
|
74
|
+
*
|
|
75
|
+
* Rules belong to the SKILL, not to the stage. A skill has exactly one rule list:
|
|
76
|
+
* wherever that skill is bound, the same rules come with it. There is no
|
|
77
|
+
* per-stage rule list, no inheritance from a stage or a preset, and no override
|
|
78
|
+
* layer, because a stage-level list forced every reader to compute a merge before
|
|
79
|
+
* knowing what actually applied, and made "which rules is this skill running
|
|
80
|
+
* under?" unanswerable without inspecting the whole composition.
|
|
81
|
+
*
|
|
82
|
+
* To use one skill under two different rule sets, copy it into a distinct skill
|
|
83
|
+
* and configure that one separately. Explicit duplication is easier to reason
|
|
84
|
+
* about than an implicit inheritance chain, and it keeps the answer to the
|
|
85
|
+
* question above local to the skill.
|
|
86
|
+
*/
|
|
87
|
+
export interface SkillBinding {
|
|
88
|
+
/** The skill, named with its source layer. */
|
|
89
|
+
skill: ResourceRef;
|
|
90
|
+
/** Rules this skill follows, each named with its source layer. */
|
|
91
|
+
rules: ResourceRef[];
|
|
92
|
+
/**
|
|
93
|
+
* What kind of evidence proves this skill was actually executed.
|
|
94
|
+
*
|
|
95
|
+
* A shell command is one kind of proof, not the only one: a requirement or design
|
|
96
|
+
* skill produces a document, and demanding a "real validation command" from it
|
|
97
|
+
* forced an irrelevant command in order to satisfy a gate. Absent means the
|
|
98
|
+
* historical default (`command`), so existing configs and frozen snapshots keep
|
|
99
|
+
* behaving exactly as they did.
|
|
100
|
+
*/
|
|
101
|
+
evidence?: EvidenceKind;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* How a bound skill proves it ran.
|
|
105
|
+
*
|
|
106
|
+
* - `command`: a shell command with a captured receipt (the default).
|
|
107
|
+
* - `artifact`: a recorded artifact body, for skills whose output is a document.
|
|
108
|
+
* - `review`: a recorded review verdict, for skills that judge rather than build.
|
|
109
|
+
* - `manual`: an explicit human statement, for work no machine can verify.
|
|
110
|
+
* - `none`: the skill is advisory and needs no separate proof.
|
|
111
|
+
*
|
|
112
|
+
* Naming them lets a flow say what it actually wants, instead of encoding one kind
|
|
113
|
+
* of evidence as though it were the only kind.
|
|
114
|
+
*/
|
|
115
|
+
export type EvidenceKind = 'command' | 'artifact' | 'review' | 'manual' | 'none';
|
|
116
|
+
/**
|
|
117
|
+
* What a stage binds for progressive disclosure when the task enters it.
|
|
118
|
+
*
|
|
119
|
+
* A stage selects skills only. Its rules are whatever those skills carry.
|
|
120
|
+
*/
|
|
46
121
|
export interface StageBinding {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
122
|
+
skills?: SkillBinding[];
|
|
123
|
+
/**
|
|
124
|
+
* Stage-level rule names from a pre-migration config, preserved verbatim.
|
|
125
|
+
*
|
|
126
|
+
* Rules used to belong to the stage, so a stage with several skills gave no
|
|
127
|
+
* indication which skill a rule was meant for. Assigning them silently would
|
|
128
|
+
* invent an answer the config never contained, and dropping them would remove a
|
|
129
|
+
* constraint the user configured. They are therefore carried here unchanged:
|
|
130
|
+
* still disclosed, still enforced — so nothing is lost — while the status output
|
|
131
|
+
* names them as unassigned so a human can decide which skill each belongs to, or
|
|
132
|
+
* split the skill if the answer differs per stage.
|
|
133
|
+
*/
|
|
134
|
+
legacy_rules?: string[];
|
|
51
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* How thoroughly a flow audits each implementation item.
|
|
138
|
+
*
|
|
139
|
+
* `two-stage` requires both a specification-conformance and a quality verdict per
|
|
140
|
+
* item, which suits a full-development flow. `single` requires one combined
|
|
141
|
+
* verdict, which is what a fast-change flow needs: the work still has to be
|
|
142
|
+
* checked before it counts as done, but the same change is not re-reviewed twice
|
|
143
|
+
* under two headings that a short change rarely distinguishes.
|
|
144
|
+
*/
|
|
145
|
+
export type ReviewDepth = 'two-stage' | 'single';
|
|
52
146
|
export interface WorkflowConfig {
|
|
53
147
|
stages: string[];
|
|
54
148
|
start_stage: string;
|
|
@@ -60,6 +154,55 @@ export interface WorkflowConfig {
|
|
|
60
154
|
high_risk_requires_verification: boolean;
|
|
61
155
|
/** Per-stage skill/rule bindings disclosed when the task enters the stage. */
|
|
62
156
|
stage_bindings?: Record<string, StageBinding>;
|
|
157
|
+
/**
|
|
158
|
+
* How much per-item review this flow demands before `todos_done` passes.
|
|
159
|
+
*
|
|
160
|
+
* The three presets differ in task complexity, not in how seriously they take
|
|
161
|
+
* safety, so a lighter flow must be able to ask for a lighter audit rather than
|
|
162
|
+
* inheriting the heaviest one. Omitting the field keeps the historical
|
|
163
|
+
* behaviour (`two-stage`), so configs and frozen snapshots written before this
|
|
164
|
+
* field existed read exactly as they did.
|
|
165
|
+
*/
|
|
166
|
+
review_depth?: ReviewDepth;
|
|
167
|
+
/**
|
|
168
|
+
* Whether finishing the task must include a recorded Git commit.
|
|
169
|
+
*
|
|
170
|
+
* A Git commit is one delivery mode, not a universal completion condition: a
|
|
171
|
+
* non-code task or a project outside version control has nothing to commit.
|
|
172
|
+
* Omitting the field keeps the historical behaviour (`true`), so existing
|
|
173
|
+
* configs and frozen snapshots are unaffected.
|
|
174
|
+
*/
|
|
175
|
+
commit_required?: boolean;
|
|
176
|
+
/**
|
|
177
|
+
* Guards a flow requires to hold at COMPLETION, for stages that have no way out.
|
|
178
|
+
*
|
|
179
|
+
* A guard normally rides an edge: `代码审核 → 完成` requiring `review_passed` is how
|
|
180
|
+
* the standard flow states that the review must pass before the end. But a flow
|
|
181
|
+
* whose final stage is where the work happens has no such edge — the agile flow's
|
|
182
|
+
* `审查` IS the review, and it is terminal. Hanging a review guard on `交付 → 审查`
|
|
183
|
+
* would be circular (demanding the verdict before the stage that produces it) and
|
|
184
|
+
* would also block the commit at `交付`, because a commit requires its stage's
|
|
185
|
+
* outgoing guards.
|
|
186
|
+
*
|
|
187
|
+
* Declaring the requirement here lets completion check it directly and keeps the
|
|
188
|
+
* statement next to the stage it describes, rather than hidden in edge order.
|
|
189
|
+
*/
|
|
190
|
+
completion_guards?: GuardName[];
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* A frozen copy of one resource's body, taken when the task was created.
|
|
194
|
+
*
|
|
195
|
+
* Names alone cannot keep an in-flight task stable: editing a skill or rule that
|
|
196
|
+
* a running task uses would silently change what that task is doing. The body is
|
|
197
|
+
* copied, and identical bodies are stored once and shared by content hash, so two
|
|
198
|
+
* tasks using the same rule do not duplicate several kilobytes each.
|
|
199
|
+
*/
|
|
200
|
+
export interface FrozenResource {
|
|
201
|
+
ref: ResourceRef;
|
|
202
|
+
/** SHA-256 of the body, which is also the key under which it is stored. */
|
|
203
|
+
hash: string;
|
|
204
|
+
/** The body itself, so a deleted or edited source cannot change a running task. */
|
|
205
|
+
content: string;
|
|
63
206
|
}
|
|
64
207
|
/**
|
|
65
208
|
* A task's frozen workflow: the preset id, its version, and the complete
|
|
@@ -74,6 +217,12 @@ export interface FlowSnapshot {
|
|
|
74
217
|
config: WorkflowConfig;
|
|
75
218
|
/** SHA-256 of the canonical JSON of `config`; a mismatch proves the snapshot was edited after creation. Absent on pre-0.22 records. */
|
|
76
219
|
hash?: string;
|
|
220
|
+
/**
|
|
221
|
+
* The skill and rule bodies this task actually resolved, captured at creation.
|
|
222
|
+
* Absent on records written before resource freezing; those fall back to live
|
|
223
|
+
* resolution.
|
|
224
|
+
*/
|
|
225
|
+
resources?: FrozenResource[];
|
|
77
226
|
}
|
|
78
227
|
/** One delegated implementation unit: a subagent fetch plus its two-stage review. */
|
|
79
228
|
export interface ItemDispatch {
|
|
@@ -82,6 +231,55 @@ export interface ItemDispatch {
|
|
|
82
231
|
/** ISO-8601 timestamp when the subagent was dispatched. */
|
|
83
232
|
at: string;
|
|
84
233
|
}
|
|
234
|
+
/**
|
|
235
|
+
* Explicit task completion, recorded once every configured condition holds.
|
|
236
|
+
*
|
|
237
|
+
* Reaching the last configured stage is not the same fact as finishing the work,
|
|
238
|
+
* and conflating them let a flow whose final stage is also its commit checkpoint
|
|
239
|
+
* arrive at that stage with no delivery record at all: the "commit before leaving
|
|
240
|
+
* a checkpoint" rule fires on the way OUT of a stage, and a terminal stage has no
|
|
241
|
+
* way out. Completion is therefore its own recorded event, checked by the engine,
|
|
242
|
+
* so every preset ends through the same lifecycle regardless of how few working
|
|
243
|
+
* stages it has.
|
|
244
|
+
*/
|
|
245
|
+
export interface TaskCompletion {
|
|
246
|
+
/** ISO-8601 timestamp of the completion call. */
|
|
247
|
+
at: string;
|
|
248
|
+
/** The commit recorded at completion, when the flow's delivery mode requires one. */
|
|
249
|
+
commit_hash?: string;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* A recorded rework: why the task went back, and exactly what that invalidated.
|
|
253
|
+
*
|
|
254
|
+
* The graph only has forward edges, but the work does not: a requirement can
|
|
255
|
+
* change after implementation started, and a defect can be found during review.
|
|
256
|
+
* Before this existed, the only way back was a hand-edited record, which left
|
|
257
|
+
* every downstream conclusion nominally intact — a confirmation, verification
|
|
258
|
+
* receipt or review verdict that described a superseded tree would still read as
|
|
259
|
+
* passing.
|
|
260
|
+
*
|
|
261
|
+
* The invalidated set is computed from the DECLARED kind rather than from a
|
|
262
|
+
* blanket rule, because the two cases differ: a changed requirement invalidates
|
|
263
|
+
* the requirement confirmation and everything downstream of it, while fixing a
|
|
264
|
+
* defect found in review invalidates the verification and review of that work but
|
|
265
|
+
* leaves the agreed requirement standing. Invalidating everything on every
|
|
266
|
+
* rework would be simpler and would also throw away conclusions that are still
|
|
267
|
+
* true, forcing work to be redone for no reason.
|
|
268
|
+
*/
|
|
269
|
+
export interface TaskRevision {
|
|
270
|
+
/** What kind of change this was; decides the invalidation scope. */
|
|
271
|
+
kind: 'requirement' | 'solution' | 'defect';
|
|
272
|
+
/** Why the task went back, in the author's words. */
|
|
273
|
+
reason: string;
|
|
274
|
+
/** The stage the task returned to. */
|
|
275
|
+
to: string;
|
|
276
|
+
/** The stage it was at when the rework was recorded. */
|
|
277
|
+
from: string;
|
|
278
|
+
/** ISO-8601 timestamp. */
|
|
279
|
+
at: string;
|
|
280
|
+
/** Conclusion names this rework invalidated, for audit. */
|
|
281
|
+
invalidated: string[];
|
|
282
|
+
}
|
|
85
283
|
/** Verdict of one review stage over a completed item. */
|
|
86
284
|
export interface ItemReviewStage {
|
|
87
285
|
outcome: 'pass' | 'fail';
|
|
@@ -186,6 +384,10 @@ export interface TaskState {
|
|
|
186
384
|
evidence: string[];
|
|
187
385
|
receipt?: VerificationReceipt;
|
|
188
386
|
}>>;
|
|
387
|
+
/** Set by the `complete` operation once every configured condition holds. Absent while the task is still open. */
|
|
388
|
+
completed?: TaskCompletion;
|
|
389
|
+
/** Rework history, newest last. Absent when the task never went back. */
|
|
390
|
+
revisions?: TaskRevision[];
|
|
189
391
|
}
|
|
190
392
|
export interface Result {
|
|
191
393
|
ok: boolean;
|
|
@@ -216,7 +418,7 @@ export declare function findTransition(from: string, to: string, config: Workflo
|
|
|
216
418
|
* two-stage review whose both stages passed, so the implementation and its
|
|
217
419
|
* audit trail are completed together.
|
|
218
420
|
*/
|
|
219
|
-
export declare function todosBlockers(state: TaskState): string[];
|
|
421
|
+
export declare function todosBlockers(state: TaskState, config?: WorkflowConfig): string[];
|
|
220
422
|
/**
|
|
221
423
|
* Validate an advance from `state.stage` to `targetStage`.
|
|
222
424
|
*
|
|
@@ -248,6 +450,44 @@ export interface CommitCheckpoint {
|
|
|
248
450
|
label?: string;
|
|
249
451
|
reason?: string;
|
|
250
452
|
}
|
|
453
|
+
/**
|
|
454
|
+
* Whether this task's flow ever demands a passing verification.
|
|
455
|
+
*
|
|
456
|
+
* A preset that never guards an edge on `verified` is telling the engine that
|
|
457
|
+
* verification is not one of its completion conditions, so a downstream stage
|
|
458
|
+
* must not invent the requirement.
|
|
459
|
+
* @param config - the frozen workflow config.
|
|
460
|
+
* @returns true when any configured transition requires `verified`.
|
|
461
|
+
*/
|
|
462
|
+
export declare function flowRequiresVerification(config: WorkflowConfig): boolean;
|
|
463
|
+
/**
|
|
464
|
+
* Stages where a passing verification must still HOLD, derived from the graph.
|
|
465
|
+
*
|
|
466
|
+
* `verified` guards the edge INTO a stage, so the requirement follows the task
|
|
467
|
+
* past that edge rather than applying from the start: a task sitting at 需求评审
|
|
468
|
+
* has produced nothing to verify. Once a task has crossed a `verified` edge,
|
|
469
|
+
* though, the requirement stays with it — that is the case the old code missed,
|
|
470
|
+
* where re-verifying and failing let the task continue and commit.
|
|
471
|
+
*
|
|
472
|
+
* Computed by walking forward from every `verified` edge's target, so it is a
|
|
473
|
+
* property of the configured graph rather than a hardcoded stage name.
|
|
474
|
+
* @param config - the frozen workflow config.
|
|
475
|
+
* @returns the set of stages at or after a verification gate.
|
|
476
|
+
*/
|
|
477
|
+
export declare function verificationHeldStages(config: WorkflowConfig): Set<string>;
|
|
478
|
+
/**
|
|
479
|
+
* Why the current state fails the flow's verification requirement, if it does.
|
|
480
|
+
*
|
|
481
|
+
* Applies only once the task has reached a stage that sits at or after a
|
|
482
|
+
* verification gate, so it never fires on a task that has not yet had anything
|
|
483
|
+
* to verify. Completion and commit share this rule, which is what stops a failed
|
|
484
|
+
* re-verification from being outrun by advancing to a stage whose own outgoing
|
|
485
|
+
* edge happens not to repeat the guard.
|
|
486
|
+
* @param state - the task state.
|
|
487
|
+
* @param config - the frozen workflow config.
|
|
488
|
+
* @returns human-readable blockers; empty when the requirement does not apply or holds.
|
|
489
|
+
*/
|
|
490
|
+
export declare function verificationBlockers(state: TaskState, config: WorkflowConfig): string[];
|
|
251
491
|
/**
|
|
252
492
|
* Decide whether the current task state permits a commit and with what label.
|
|
253
493
|
*
|
|
@@ -257,6 +497,128 @@ export interface CommitCheckpoint {
|
|
|
257
497
|
* hold, so the engine cannot be asked to commit before its own state is valid.
|
|
258
498
|
*/
|
|
259
499
|
export declare function commitCheckpoint(state: TaskState, config: WorkflowConfig): CommitCheckpoint;
|
|
500
|
+
/**
|
|
501
|
+
* Whether a stage is terminal in the configured graph (no outgoing transition).
|
|
502
|
+
* @param stage - the stage to test.
|
|
503
|
+
* @param config - the frozen workflow config.
|
|
504
|
+
* @returns true when nothing follows this stage.
|
|
505
|
+
*/
|
|
506
|
+
export declare function isTerminalStage(stage: string, config: WorkflowConfig): boolean;
|
|
507
|
+
/**
|
|
508
|
+
* Whether the delivery mode requires a recorded commit before completion.
|
|
509
|
+
* @param config - the frozen workflow config.
|
|
510
|
+
* @returns true when a commit must be recorded (the historical default).
|
|
511
|
+
*/
|
|
512
|
+
export declare function commitRequired(config: WorkflowConfig): boolean;
|
|
513
|
+
/**
|
|
514
|
+
* Every reason the task may not be marked complete.
|
|
515
|
+
*
|
|
516
|
+
* Completion is its own fact, checked here rather than inferred from standing on
|
|
517
|
+
* the last stage. Three things can hold it back: the task has not reached a
|
|
518
|
+
* terminal stage, the flow's own `todos_done` conditions are unmet, or the
|
|
519
|
+
* delivery mode wants a commit that is not recorded. Deliberately NOT included:
|
|
520
|
+
* a blanket demand for a commit on every flow, because a commit is one delivery
|
|
521
|
+
* mode rather than a universal finish line.
|
|
522
|
+
* @param state - the task state.
|
|
523
|
+
* @param config - the frozen workflow config.
|
|
524
|
+
* @returns human-readable blockers; empty when the task may complete.
|
|
525
|
+
*/
|
|
526
|
+
/**
|
|
527
|
+
* Configurations a stage needs but that cannot be resolved.
|
|
528
|
+
*
|
|
529
|
+
* Disclosure is not enforcement. `missing_rules` was reported in status and never
|
|
530
|
+
* blocked anything, so deleting a rule a stage was bound to still let the task
|
|
531
|
+
* advance — leaving a stage running without the constraints it was configured
|
|
532
|
+
* with, while the record looked fine.
|
|
533
|
+
*
|
|
534
|
+
* This is a pure decision over names, so the tool and the hook reach the same
|
|
535
|
+
* verdict from the same inputs. It takes the unresolved names rather than reading
|
|
536
|
+
* anything, because resolution needs a filesystem and this must stay callable from
|
|
537
|
+
* both planes.
|
|
538
|
+
* @param unresolved - references that resolved nowhere, as `source:name` or a bare legacy name.
|
|
539
|
+
* @param stage - the stage whose configuration is being checked.
|
|
540
|
+
* @returns one blocker per unresolved resource, empty when the stage is complete.
|
|
541
|
+
*/
|
|
542
|
+
export declare function resourceBlockers(unresolved: readonly string[], stage: string): string[];
|
|
543
|
+
/**
|
|
544
|
+
* The outcomes a flow's FINAL stage is required to have, derived from its guards.
|
|
545
|
+
*
|
|
546
|
+
* Completion used to check only standing-on-a-final-stage, unfinished items and
|
|
547
|
+
* whether a commit existed. A flow that declares `review_passed` or `verified` on
|
|
548
|
+
* its way into the terminal stage was therefore satisfiable by ARRIVING there: the
|
|
549
|
+
* agile flow's review verdict and the standard flow's verification could both be
|
|
550
|
+
* failing while `complete` succeeded.
|
|
551
|
+
*
|
|
552
|
+
* Derived rather than hardcoded, because a flow that declares no verification gate
|
|
553
|
+
* must not be made to demand one — the requirement is whatever the flow said.
|
|
554
|
+
* @param config - the effective workflow.
|
|
555
|
+
* @returns the guard names the final stage's incoming edges require.
|
|
556
|
+
*/
|
|
557
|
+
export declare function terminalRequirements(config: WorkflowConfig): GuardName[];
|
|
558
|
+
export declare function completionBlockers(state: TaskState, config: WorkflowConfig): string[];
|
|
559
|
+
/**
|
|
560
|
+
* Which recorded conclusions a rework of the given kind invalidates.
|
|
561
|
+
*
|
|
562
|
+
* Derived from what each kind of change actually supersedes:
|
|
563
|
+
*
|
|
564
|
+
* - `requirement`: the agreed requirement changed, so its confirmation no longer
|
|
565
|
+
* speaks for the work, and neither does the solution built on it. Verification,
|
|
566
|
+
* review and item audits all judged a tree derived from the old requirement.
|
|
567
|
+
* - `solution`: the requirement stands, but the approach changed. Its confirmation
|
|
568
|
+
* falls, along with everything that judged the implementation of the old one.
|
|
569
|
+
* - `defect`: a defect in the work as specified. The requirement and solution stay
|
|
570
|
+
* agreed; what falls is the evidence that the OLD implementation was correct —
|
|
571
|
+
* verification, review, and the per-item audits.
|
|
572
|
+
*
|
|
573
|
+
* A confirmation is always re-askable rather than silently assumed, because the
|
|
574
|
+
* human who approved it approved a different thing.
|
|
575
|
+
* @param kind - the kind of change being recorded.
|
|
576
|
+
* @returns the conclusion names to clear.
|
|
577
|
+
*/
|
|
578
|
+
export declare function invalidatedBy(kind: TaskRevision['kind']): string[];
|
|
579
|
+
/**
|
|
580
|
+
* The result of applying one rework to a task record.
|
|
581
|
+
*
|
|
582
|
+
* Kept separate from the mutation so the caller can report what changed, and so
|
|
583
|
+
* the clearing rules above are asserted directly in tests.
|
|
584
|
+
*/
|
|
585
|
+
export interface RevisionOutcome {
|
|
586
|
+
/** The stage the task now sits at. */
|
|
587
|
+
stage: string;
|
|
588
|
+
/** The conclusions that were cleared. */
|
|
589
|
+
invalidated: string[];
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* Apply a rework to a task record, clearing exactly the superseded conclusions.
|
|
593
|
+
*
|
|
594
|
+
* Confirmation flags are reset rather than deleted because the engine reads them
|
|
595
|
+
* as booleans; the other conclusions are cleared by removing the record that
|
|
596
|
+
* carried them, so `status` reports them as absent instead of stale.
|
|
597
|
+
* @param state - the task state, mutated in place.
|
|
598
|
+
* @param revision - the rework to apply.
|
|
599
|
+
* @returns the stage reached and the conclusions cleared.
|
|
600
|
+
*/
|
|
601
|
+
export declare function applyRevision(state: TaskState, revision: TaskRevision): RevisionOutcome;
|
|
602
|
+
/**
|
|
603
|
+
* A project's `.dsh/eng.json` as read off disk.
|
|
604
|
+
*
|
|
605
|
+
* This describes what a file MAY contain so the resolver can narrow it; declaring
|
|
606
|
+
* only the fields a valid file is allowed would make an invalid one look valid to
|
|
607
|
+
* the parser and hide the error until much later.
|
|
608
|
+
*/
|
|
609
|
+
export interface ParsedProjectConfig {
|
|
610
|
+
flow?: string;
|
|
611
|
+
/** The project's own stage bindings, taken verbatim. */
|
|
612
|
+
stage_bindings?: Record<string, StageBinding>;
|
|
613
|
+
/** The project's own commit policy, replacing any preset default. */
|
|
614
|
+
commit?: CommitRule;
|
|
615
|
+
/** The project's own artifact declarations. */
|
|
616
|
+
artifacts?: ArtifactDef[];
|
|
617
|
+
/** The project's own per-item review depth. */
|
|
618
|
+
review_depth?: ReviewDepth;
|
|
619
|
+
/** Whether a recorded commit is required before completion. */
|
|
620
|
+
commit_required?: boolean;
|
|
621
|
+
}
|
|
260
622
|
export interface FileScopeResult {
|
|
261
623
|
ok: boolean;
|
|
262
624
|
/** Paths outside the declared scope (present only when the scope is set but violated). */
|