@zhchxiao123/dsh-devflow 0.1.1 → 0.3.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/README.i18n.yaml +2 -2
- package/README.md +7 -5
- package/README.zh.md +7 -5
- package/lib/index.js +240 -19
- package/lib/types/index.d.ts +151 -9
- package/lib/types/index.js +46 -2
- package/lib/types/invariant.js +1 -1
- package/lib/types/journal.d.ts +23 -2
- package/lib/types/journal.js +80 -7
- package/lib/types/stages.d.ts +43 -7
- package/lib/types/stages.js +73 -12
- package/lib/types/types.d.ts +190 -11
- package/package.json +1 -1
package/lib/types/types.d.ts
CHANGED
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
import type { DevflowCardId } from './stages.ts';
|
|
8
8
|
export type { DevflowCardId } from './stages.ts';
|
|
9
9
|
declare module '@deepseek-ai/cordis' {
|
|
10
|
+
interface Context {
|
|
11
|
+
/** Optional dynamic artifact-contract inspection published by a policy provider. */
|
|
12
|
+
devflowArtifactContract: ArtifactContract;
|
|
13
|
+
}
|
|
10
14
|
interface Events {
|
|
11
15
|
/**
|
|
12
16
|
* Single-decision transition pipeline. The store dispatches this after the
|
|
@@ -43,6 +47,20 @@ declare module '@deepseek-ai/cordis' {
|
|
|
43
47
|
export type DevStage = 'draft' | 'designing' | 'ready' | 'developing' | 'reviewing' | 'testing' | 'done';
|
|
44
48
|
/** Where a card currently sits: a pipeline stage, or the `blocked` bypass. */
|
|
45
49
|
export type CardLocation = DevStage | 'blocked';
|
|
50
|
+
/**
|
|
51
|
+
* The closed set of service classes a card is created under, each selecting
|
|
52
|
+
* which edges of the pipeline that card may take. Every class is a superset of
|
|
53
|
+
* `standard`, so a class only ever adds a shortcut.
|
|
54
|
+
*
|
|
55
|
+
* - `standard` — the full pipeline; the class of a card that declares none.
|
|
56
|
+
* - `express` — reaches `developing` from `draft` and `done` from
|
|
57
|
+
* `reviewing`, skipping design, readiness, and independent verification.
|
|
58
|
+
* Peer review stays: it is the control worth keeping on cheap work.
|
|
59
|
+
* - `emergency` — reaches `developing` from `draft` and `done` from
|
|
60
|
+
* `developing`. It gives up review too, and the follow-up is an ordinary
|
|
61
|
+
* card rather than an obligation encoded in the state machine.
|
|
62
|
+
*/
|
|
63
|
+
export type ServiceClass = 'standard' | 'express' | 'emergency';
|
|
46
64
|
/** Who performed a journal action; `command` marks the human-command intervention plane. */
|
|
47
65
|
export type DevActor = {
|
|
48
66
|
kind: 'human';
|
|
@@ -62,6 +80,24 @@ export interface JournalCreated {
|
|
|
62
80
|
by: DevActor;
|
|
63
81
|
/** The card this one decomposes, fixed here at creation and never changed. */
|
|
64
82
|
parent?: DevflowCardId;
|
|
83
|
+
/**
|
|
84
|
+
* The card's service class, fixed here at creation and never changed.
|
|
85
|
+
* Omitted is `standard`, so a journal written before classes existed reads
|
|
86
|
+
* as one and a `standard` card's first entry keeps its original bytes.
|
|
87
|
+
*/
|
|
88
|
+
serviceClass?: ServiceClass;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* One recorded gate verdict on a committed transition: which actor allowed the
|
|
92
|
+
* move and, optionally, what the check covered. Only permitting verdicts
|
|
93
|
+
* exist — a refusal vetoes the transition instead of being recorded.
|
|
94
|
+
*/
|
|
95
|
+
export interface GateCheck {
|
|
96
|
+
/** The actor that allowed the move. */
|
|
97
|
+
by: DevActor;
|
|
98
|
+
verdict: 'allowed';
|
|
99
|
+
/** One-line account of what the check covered. */
|
|
100
|
+
summary?: string;
|
|
65
101
|
}
|
|
66
102
|
/**
|
|
67
103
|
* One stage move. A move to `blocked` remembers `from`; the matching recovery
|
|
@@ -75,9 +111,14 @@ export interface JournalTransition {
|
|
|
75
111
|
to: CardLocation;
|
|
76
112
|
by?: DevActor;
|
|
77
113
|
reason?: string;
|
|
78
|
-
/**
|
|
114
|
+
/**
|
|
115
|
+
* Gate facts attached by the transition waterfall: the human approval
|
|
116
|
+
* signature and/or the recorded gate verdicts. At least one is present —
|
|
117
|
+
* a move nothing gated carries no `gate` at all.
|
|
118
|
+
*/
|
|
79
119
|
gate?: {
|
|
80
|
-
approvedBy
|
|
120
|
+
approvedBy?: DevActor;
|
|
121
|
+
checks?: GateCheck[];
|
|
81
122
|
};
|
|
82
123
|
}
|
|
83
124
|
/** Registration of a stage deliverable produced under `artifacts/`. */
|
|
@@ -88,6 +129,28 @@ export interface JournalArtifact {
|
|
|
88
129
|
path: string;
|
|
89
130
|
stage: DevStage;
|
|
90
131
|
by?: DevActor;
|
|
132
|
+
/**
|
|
133
|
+
* Deliverable kind of a store-written artifact; absent for a path-only
|
|
134
|
+
* registration and for entries predating kinds.
|
|
135
|
+
*/
|
|
136
|
+
kind?: string;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* The decision to stop: this card will never be finished. Terminal — no entry
|
|
140
|
+
* may follow it — and the card leaves the active board rather than occupying
|
|
141
|
+
* a stage nobody is working in.
|
|
142
|
+
*/
|
|
143
|
+
export interface JournalAbandoned {
|
|
144
|
+
rev: number;
|
|
145
|
+
at: string;
|
|
146
|
+
type: 'abandoned';
|
|
147
|
+
by: DevActor;
|
|
148
|
+
/**
|
|
149
|
+
* Why the work stopped. Required, unlike a transition's reason: a transition
|
|
150
|
+
* leaves the card visible and explicable from where it sits, while this
|
|
151
|
+
* removes it from the board, so the reason is all that is left of it.
|
|
152
|
+
*/
|
|
153
|
+
reason: string;
|
|
91
154
|
}
|
|
92
155
|
/** Takeover of a stale lease: the previous holder's heartbeat lapsed. */
|
|
93
156
|
export interface JournalClaimExpired {
|
|
@@ -98,7 +161,22 @@ export interface JournalClaimExpired {
|
|
|
98
161
|
by: DevActor;
|
|
99
162
|
}
|
|
100
163
|
/** The journal entry union; the discriminant is `type`. */
|
|
101
|
-
export type DevflowJournalEntry = JournalCreated | JournalTransition | JournalArtifact | JournalClaimExpired;
|
|
164
|
+
export type DevflowJournalEntry = JournalCreated | JournalTransition | JournalArtifact | JournalAbandoned | JournalClaimExpired;
|
|
165
|
+
/**
|
|
166
|
+
* Read-side value of one artifact registration: the journal entry's facts
|
|
167
|
+
* without its envelope. Registrations are immutable — the newest record of one
|
|
168
|
+
* `kind` (the highest `rev`) is that kind's current content.
|
|
169
|
+
*/
|
|
170
|
+
export interface ArtifactRecord {
|
|
171
|
+
/** Artifact path relative to the card directory. */
|
|
172
|
+
path: string;
|
|
173
|
+
/** Deliverable kind; absent for a path-only registration. */
|
|
174
|
+
kind?: string;
|
|
175
|
+
/** Journal revision of the registration; orders records of one kind. */
|
|
176
|
+
rev: number;
|
|
177
|
+
/** The stage the deliverable was registered against. */
|
|
178
|
+
stage: DevStage;
|
|
179
|
+
}
|
|
102
180
|
/** Read-side value of one card, current state derived by journal replay. */
|
|
103
181
|
export interface DevCard {
|
|
104
182
|
id: DevflowCardId;
|
|
@@ -117,12 +195,50 @@ export interface DevCard {
|
|
|
117
195
|
* exists, so a card carrying `parent` is never itself a parent.
|
|
118
196
|
*/
|
|
119
197
|
parent?: DevflowCardId;
|
|
198
|
+
/**
|
|
199
|
+
* The card's service class, selecting which pipeline edges it may take.
|
|
200
|
+
* Always present: a card whose journal states none is `standard`.
|
|
201
|
+
*/
|
|
202
|
+
serviceClass: ServiceClass;
|
|
203
|
+
/**
|
|
204
|
+
* Set once the card was abandoned: the work stopped and will not resume.
|
|
205
|
+
* Such a card is off the active board, so `list` never reports one.
|
|
206
|
+
*/
|
|
207
|
+
abandoned?: true;
|
|
120
208
|
/** Markdown body of the card file below its frontmatter. */
|
|
121
209
|
body: string;
|
|
122
210
|
/** Display path of the card file. */
|
|
123
211
|
path: string;
|
|
124
|
-
/** Artifact paths registered in the journal, in registration order. */
|
|
212
|
+
/** Artifact paths registered in the journal, in registration order; the path projection of {@link artifactRecords}. */
|
|
125
213
|
artifacts: string[];
|
|
214
|
+
/** Artifact registrations in registration order, each carrying its journal revision, registering stage, and optional kind. */
|
|
215
|
+
artifactRecords: ArtifactRecord[];
|
|
216
|
+
}
|
|
217
|
+
/** Immutable normalized artifact shape published through the inspection seam. */
|
|
218
|
+
export interface PublishedArtifactKindSpec {
|
|
219
|
+
readonly frontmatter?: readonly string[];
|
|
220
|
+
readonly sections?: readonly string[];
|
|
221
|
+
}
|
|
222
|
+
/** Mechanical state of one required artifact at the inspected card revision. */
|
|
223
|
+
export type ArtifactRequirementStatus = 'missing' | 'malformed' | 'satisfied';
|
|
224
|
+
/** One required kind and the exact evidence the transition policy will judge. */
|
|
225
|
+
export interface ArtifactRequirementInspection {
|
|
226
|
+
readonly kind: string;
|
|
227
|
+
readonly status: ArtifactRequirementStatus;
|
|
228
|
+
readonly spec: PublishedArtifactKindSpec;
|
|
229
|
+
readonly artifact?: Readonly<ArtifactRecord>;
|
|
230
|
+
readonly defects: readonly string[];
|
|
231
|
+
}
|
|
232
|
+
/** Artifact requirements of one configured, currently legal outgoing edge. */
|
|
233
|
+
export interface ArtifactTransitionInspection {
|
|
234
|
+
readonly from: CardLocation;
|
|
235
|
+
readonly to: CardLocation;
|
|
236
|
+
readonly requirements: readonly ArtifactRequirementInspection[];
|
|
237
|
+
}
|
|
238
|
+
/** Optional read-only policy seam consumed by model-facing card tools. */
|
|
239
|
+
export interface ArtifactContract {
|
|
240
|
+
/** Inspect every configured legal edge leaving the card's current location. */
|
|
241
|
+
inspectOutgoing(card: DevCard): Promise<readonly ArtifactTransitionInspection[]>;
|
|
126
242
|
}
|
|
127
243
|
/** Read filter accepted by {@link import('./index.ts').DevflowStore.list}. */
|
|
128
244
|
export interface CardFilter {
|
|
@@ -146,6 +262,12 @@ export interface CreateRequest {
|
|
|
146
262
|
* must be an active top-level card of the same root — only one level exists.
|
|
147
263
|
*/
|
|
148
264
|
parent?: DevflowCardId;
|
|
265
|
+
/**
|
|
266
|
+
* Which pipeline edges the card may take, fixed here and never changed —
|
|
267
|
+
* escalating live work means a new card, not a mutated one. Omitted is
|
|
268
|
+
* `standard`, the full pipeline.
|
|
269
|
+
*/
|
|
270
|
+
serviceClass?: ServiceClass;
|
|
149
271
|
/** Devflow root receiving the card; omitted uses the implementation's default root. */
|
|
150
272
|
root?: string;
|
|
151
273
|
}
|
|
@@ -211,12 +333,19 @@ export type TransitionDecision = {
|
|
|
211
333
|
allowed: true;
|
|
212
334
|
/** The human signature a policy listener collected; recorded as the journal entry's `gate.approvedBy`. */
|
|
213
335
|
approvedBy?: DevActor;
|
|
336
|
+
/** Gate verdicts policy listeners collected; recorded as the journal entry's `gate.checks` when non-empty. */
|
|
337
|
+
checks?: GateCheck[];
|
|
214
338
|
} | {
|
|
215
339
|
allowed: false;
|
|
216
340
|
reason: string;
|
|
217
341
|
};
|
|
218
|
-
/**
|
|
219
|
-
|
|
342
|
+
/**
|
|
343
|
+
* Stable rejection codes of {@link TransitionResult}; the discriminant is
|
|
344
|
+
* `code`. `write-contended` is the only one a caller can retry unchanged: it
|
|
345
|
+
* says another process held the card's commit long enough that this one gave
|
|
346
|
+
* up, and that nothing was written.
|
|
347
|
+
*/
|
|
348
|
+
export type TransitionRejectionCode = 'revision-mismatch' | 'illegal-edge' | 'reason-required' | 'vetoed' | 'write-contended';
|
|
220
349
|
/**
|
|
221
350
|
* Transition outcome. Domain rejections resolve with `ok: false` and a stable
|
|
222
351
|
* code; only infrastructure failures (unwritable journal, unreadable card)
|
|
@@ -231,24 +360,74 @@ export type TransitionResult = {
|
|
|
231
360
|
code: TransitionRejectionCode;
|
|
232
361
|
message: string;
|
|
233
362
|
};
|
|
234
|
-
/** Caller view of one
|
|
235
|
-
export interface
|
|
363
|
+
/** Caller view of one abandonment: the decision that this card stops here. */
|
|
364
|
+
export interface AbandonRequest {
|
|
365
|
+
id: DevflowCardId;
|
|
366
|
+
/** Optimistic-concurrency token: the `stageRevision` the caller last observed. */
|
|
367
|
+
expectedRevision: number;
|
|
368
|
+
by: DevActor;
|
|
369
|
+
/** Why the work stopped; blank is rejected rather than recorded as nothing. */
|
|
370
|
+
reason: string;
|
|
371
|
+
/** Devflow root holding the card; omitted uses the implementation's default root. */
|
|
372
|
+
root?: string;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Stable rejection codes of {@link AbandonResult}. `already-done` names the one
|
|
376
|
+
* card that must not be abandoned: a delivered outcome is not a decision to
|
|
377
|
+
* stop, and `archiveDone` is what settles it.
|
|
378
|
+
*/
|
|
379
|
+
export type AbandonRejectionCode = 'empty-reason' | 'already-done' | 'revision-mismatch' | 'write-contended';
|
|
380
|
+
/**
|
|
381
|
+
* Outcome of one abandonment. Domain rejections resolve with a stable code;
|
|
382
|
+
* only infrastructure failures reject the promise.
|
|
383
|
+
*/
|
|
384
|
+
export type AbandonResult = {
|
|
385
|
+
ok: true;
|
|
386
|
+
card: DevCard;
|
|
387
|
+
} | {
|
|
388
|
+
ok: false;
|
|
389
|
+
code: AbandonRejectionCode;
|
|
390
|
+
message: string;
|
|
391
|
+
};
|
|
392
|
+
/** Fields shared by both {@link ArtifactRequest} forms. */
|
|
393
|
+
interface ArtifactRequestBase {
|
|
236
394
|
id: DevflowCardId;
|
|
237
|
-
/** Artifact path relative to the card directory, e.g. `artifacts/design.md`. */
|
|
238
|
-
path: string;
|
|
239
395
|
/** Optimistic-concurrency token: the `stageRevision` the caller last observed. */
|
|
240
396
|
expectedRevision: number;
|
|
241
397
|
by: DevActor;
|
|
242
398
|
/** Devflow root holding the card; omitted uses the implementation's default root. */
|
|
243
399
|
root?: string;
|
|
244
400
|
}
|
|
401
|
+
/** Reference form: the caller already wrote the file and registers its path. */
|
|
402
|
+
export interface ArtifactPathRequest extends ArtifactRequestBase {
|
|
403
|
+
/** Artifact path relative to the card directory, e.g. `artifacts/design.md`. */
|
|
404
|
+
path: string;
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Store-written form: the implementation writes `artifacts/<rev>-<kind>.md`
|
|
408
|
+
* itself, before the journal append, and registers that path.
|
|
409
|
+
*/
|
|
410
|
+
export interface ArtifactContentRequest extends ArtifactRequestBase {
|
|
411
|
+
/** Deliverable kind; the slug grammar, rejected `invalid-kind` otherwise. */
|
|
412
|
+
kind: string;
|
|
413
|
+
/** Complete Markdown content the implementation writes. */
|
|
414
|
+
content: string;
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Caller view of one artifact registration against the card's current stage:
|
|
418
|
+
* the reference form or the store-written form. The two are mutually
|
|
419
|
+
* exclusive — the model-facing tool rejects a call carrying both before the
|
|
420
|
+
* seam is reached.
|
|
421
|
+
*/
|
|
422
|
+
export type ArtifactRequest = ArtifactPathRequest | ArtifactContentRequest;
|
|
245
423
|
/** Artifact-registration outcome; domain rejections resolve like {@link TransitionResult}. */
|
|
246
424
|
export type ArtifactResult = {
|
|
247
425
|
ok: true;
|
|
248
426
|
card: DevCard;
|
|
427
|
+
record: ArtifactRecord;
|
|
249
428
|
} | {
|
|
250
429
|
ok: false;
|
|
251
|
-
code: 'revision-mismatch' | 'illegal-edge';
|
|
430
|
+
code: 'revision-mismatch' | 'illegal-edge' | 'invalid-kind' | 'write-contended';
|
|
252
431
|
message: string;
|
|
253
432
|
};
|
|
254
433
|
/** Current lease facts of one card, read from its claim record. */
|
package/package.json
CHANGED