@cat-factory/orchestration 0.60.3 → 0.61.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/dist/container.d.ts +15 -1
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +17 -0
- package/dist/container.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/modules/board/BoardService.d.ts +11 -2
- package/dist/modules/board/BoardService.d.ts.map +1 -1
- package/dist/modules/board/BoardService.js +27 -1
- package/dist/modules/board/BoardService.js.map +1 -1
- package/dist/modules/board/board.logic.d.ts.map +1 -1
- package/dist/modules/board/board.logic.js +5 -0
- package/dist/modules/board/board.logic.js.map +1 -1
- package/dist/modules/execution/ExecutionService.d.ts +10 -1
- package/dist/modules/execution/ExecutionService.d.ts.map +1 -1
- package/dist/modules/execution/ExecutionService.js +7 -1
- package/dist/modules/execution/ExecutionService.js.map +1 -1
- package/dist/modules/execution/RunDispatcher.d.ts +15 -0
- package/dist/modules/execution/RunDispatcher.d.ts.map +1 -1
- package/dist/modules/execution/RunDispatcher.js +105 -2
- package/dist/modules/execution/RunDispatcher.js.map +1 -1
- package/dist/modules/execution/RunStateMachine.d.ts.map +1 -1
- package/dist/modules/execution/RunStateMachine.js +11 -1
- package/dist/modules/execution/RunStateMachine.js.map +1 -1
- package/dist/modules/initiative/InitiativeService.d.ts +60 -0
- package/dist/modules/initiative/InitiativeService.d.ts.map +1 -0
- package/dist/modules/initiative/InitiativeService.js +158 -0
- package/dist/modules/initiative/InitiativeService.js.map +1 -0
- package/dist/modules/initiative/initiative.logic.d.ts +47 -0
- package/dist/modules/initiative/initiative.logic.d.ts.map +1 -0
- package/dist/modules/initiative/initiative.logic.js +202 -0
- package/dist/modules/initiative/initiative.logic.js.map +1 -0
- package/dist/modules/requirements/RequirementReviewService.d.ts +21 -12
- package/dist/modules/requirements/RequirementReviewService.d.ts.map +1 -1
- package/dist/modules/requirements/RequirementReviewService.js +107 -56
- package/dist/modules/requirements/RequirementReviewService.js.map +1 -1
- package/dist/modules/requirements/requirements.logic.d.ts +14 -0
- package/dist/modules/requirements/requirements.logic.d.ts.map +1 -1
- package/dist/modules/requirements/requirements.logic.js +45 -0
- package/dist/modules/requirements/requirements.logic.js.map +1 -1
- package/package.json +10 -10
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { ConflictError, ValidationError, assertFound, requireWorkspace } from '@cat-factory/kernel';
|
|
2
|
+
import { parseInitiativePlanDraft } from '@cat-factory/contracts';
|
|
3
|
+
import { initiativeContentView } from '@cat-factory/agents';
|
|
4
|
+
import { gridSlot } from '../board/board.logic.js';
|
|
5
|
+
import { applyPlanDraft, initiativeSlug, validatePlanDraft } from './initiative.logic.js';
|
|
6
|
+
/** How many times a CAS write is retried against a concurrent writer before giving up. */
|
|
7
|
+
const CAS_ATTEMPTS = 3;
|
|
8
|
+
/**
|
|
9
|
+
* The initiative entity's owner: creation (the board block + the entity in one
|
|
10
|
+
* step), reads for the snapshot/controller, and the plan-ingest writes the
|
|
11
|
+
* execution engine drives from the planning pipeline. Every write after the
|
|
12
|
+
* insert goes through the repository's rev-guarded `compareAndSwap`, so the
|
|
13
|
+
* entity has a single logical writer even across concurrent tickers.
|
|
14
|
+
*/
|
|
15
|
+
export class InitiativeService {
|
|
16
|
+
deps;
|
|
17
|
+
constructor(deps) {
|
|
18
|
+
this.deps = deps;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create an initiative under a service frame: the `initiative`-level board
|
|
22
|
+
* block (a structural frame child, like a module) plus its empty entity
|
|
23
|
+
* (`status: 'planning'`, rev 0), returned together so the client patches both
|
|
24
|
+
* caches. The planning pipeline is then started against the block.
|
|
25
|
+
*/
|
|
26
|
+
async create(workspaceId, input) {
|
|
27
|
+
await requireWorkspace(this.deps.workspaceRepository, workspaceId);
|
|
28
|
+
const frame = assertFound(await this.deps.blockRepository.get(workspaceId, input.frameId), 'Block', input.frameId);
|
|
29
|
+
if (frame.level !== 'frame') {
|
|
30
|
+
throw new ValidationError('An initiative can only be created under a service frame');
|
|
31
|
+
}
|
|
32
|
+
const blocks = await this.deps.blockRepository.listByWorkspace(workspaceId);
|
|
33
|
+
const siblings = blocks.filter((b) => b.parentId === frame.id && b.level === 'initiative').length;
|
|
34
|
+
// A stable, unique tracker-folder slug: suffix on collision with the
|
|
35
|
+
// workspace's existing initiatives (two initiatives may share a title).
|
|
36
|
+
const existing = await this.deps.initiativeRepository.list(workspaceId);
|
|
37
|
+
const taken = new Set(existing.map((i) => i.slug));
|
|
38
|
+
const base = initiativeSlug(input.title);
|
|
39
|
+
let slug = base;
|
|
40
|
+
for (let n = 2; taken.has(slug); n++)
|
|
41
|
+
slug = `${base}-${n}`;
|
|
42
|
+
const now = this.deps.clock.now();
|
|
43
|
+
const block = {
|
|
44
|
+
id: this.deps.idGenerator.next('init'),
|
|
45
|
+
title: input.title.trim(),
|
|
46
|
+
type: frame.type,
|
|
47
|
+
description: input.description?.trim() ?? '',
|
|
48
|
+
position: gridSlot(siblings, 2, 280, 220, 16, 320),
|
|
49
|
+
status: 'planned',
|
|
50
|
+
progress: 0,
|
|
51
|
+
dependsOn: [],
|
|
52
|
+
executionId: null,
|
|
53
|
+
level: 'initiative',
|
|
54
|
+
parentId: frame.id,
|
|
55
|
+
};
|
|
56
|
+
const initiative = {
|
|
57
|
+
id: this.deps.idGenerator.next('initv'),
|
|
58
|
+
blockId: block.id,
|
|
59
|
+
slug,
|
|
60
|
+
title: input.title.trim(),
|
|
61
|
+
goal: input.description?.trim() ?? '',
|
|
62
|
+
constraints: [],
|
|
63
|
+
nonGoals: [],
|
|
64
|
+
qa: [],
|
|
65
|
+
analysisSummary: '',
|
|
66
|
+
phases: [],
|
|
67
|
+
items: [],
|
|
68
|
+
policy: null,
|
|
69
|
+
decisions: [],
|
|
70
|
+
deviations: [],
|
|
71
|
+
followUps: [],
|
|
72
|
+
caveats: [],
|
|
73
|
+
status: 'planning',
|
|
74
|
+
rev: 0,
|
|
75
|
+
createdAt: now,
|
|
76
|
+
updatedAt: now,
|
|
77
|
+
};
|
|
78
|
+
// Insert the initiative FIRST: its `(workspace_id, slug)` unique index is the
|
|
79
|
+
// backstop for the read-then-insert slug race, so a losing concurrent create throws
|
|
80
|
+
// here BEFORE a dangling initiative-block is written (rather than orphaning one).
|
|
81
|
+
await this.deps.initiativeRepository.insert(workspaceId, initiative);
|
|
82
|
+
await this.deps.blockRepository.insert(workspaceId, block);
|
|
83
|
+
await this.deps.events.boardChanged(workspaceId, 'initiative-added', block.id);
|
|
84
|
+
await this.deps.events.initiativeChanged?.(workspaceId, initiative);
|
|
85
|
+
return { initiative, block };
|
|
86
|
+
}
|
|
87
|
+
list(workspaceId) {
|
|
88
|
+
return this.deps.initiativeRepository.list(workspaceId);
|
|
89
|
+
}
|
|
90
|
+
async get(workspaceId, id) {
|
|
91
|
+
return assertFound(await this.deps.initiativeRepository.get(workspaceId, id), 'Initiative', id);
|
|
92
|
+
}
|
|
93
|
+
getByBlock(workspaceId, blockId) {
|
|
94
|
+
return this.deps.initiativeRepository.getByBlock(workspaceId, blockId);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Ingest an `initiative-planner` step's plan draft into the block's entity:
|
|
98
|
+
* strict-parse (the trust boundary — a malformed draft is rejected, never
|
|
99
|
+
* half-applied), validate the reference graph, fold it in preserving runtime
|
|
100
|
+
* state, and CAS-write. IDEMPOTENT: re-ingesting a draft that produces
|
|
101
|
+
* byte-identical content (a durable-driver replay) is a no-op, so the ingest
|
|
102
|
+
* is replay-safe. Returns the updated entity, or null when the block has no
|
|
103
|
+
* initiative (nothing to ingest into).
|
|
104
|
+
*/
|
|
105
|
+
async ingestPlan(workspaceId, blockId, rawDraft) {
|
|
106
|
+
const draft = parseInitiativePlanDraft(rawDraft);
|
|
107
|
+
validatePlanDraft(draft);
|
|
108
|
+
return this.mutate(workspaceId, blockId, (current) => applyPlanDraft(current, draft, this.deps.clock.now()));
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Flip an initiative to `executing` (the committer step ran: the plan is
|
|
112
|
+
* approved and the tracker mirror committed), stamping the repo-doc
|
|
113
|
+
* bookkeeping when a commit landed. Idempotent on replay (same status + doc
|
|
114
|
+
* ⇒ content-unchanged ⇒ no write).
|
|
115
|
+
*/
|
|
116
|
+
async markExecuting(workspaceId, blockId, doc) {
|
|
117
|
+
return this.mutate(workspaceId, blockId, (current) => ({
|
|
118
|
+
...current,
|
|
119
|
+
status: current.status === 'planning' || current.status === 'awaiting_approval'
|
|
120
|
+
? 'executing'
|
|
121
|
+
: current.status,
|
|
122
|
+
...(doc ? { doc: { ...doc, committedAt: this.deps.clock.now() } } : {}),
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* The shared read → transform → CAS-write loop. A content-identical transform
|
|
127
|
+
* result short-circuits to no write (replay/idempotency); a lost CAS reloads
|
|
128
|
+
* and retries a bounded number of times before conflicting loudly.
|
|
129
|
+
*/
|
|
130
|
+
async mutate(workspaceId, blockId, transform) {
|
|
131
|
+
for (let attempt = 0; attempt < CAS_ATTEMPTS; attempt++) {
|
|
132
|
+
const current = await this.deps.initiativeRepository.getByBlock(workspaceId, blockId);
|
|
133
|
+
if (!current)
|
|
134
|
+
return null;
|
|
135
|
+
const next = transform(current);
|
|
136
|
+
if (sameContent(current, next))
|
|
137
|
+
return current;
|
|
138
|
+
const persisted = {
|
|
139
|
+
...next,
|
|
140
|
+
rev: current.rev + 1,
|
|
141
|
+
updatedAt: this.deps.clock.now(),
|
|
142
|
+
};
|
|
143
|
+
if (await this.deps.initiativeRepository.compareAndSwap(workspaceId, persisted, current.rev)) {
|
|
144
|
+
await this.deps.events.initiativeChanged?.(workspaceId, persisted);
|
|
145
|
+
return persisted;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
throw new ConflictError('Initiative was modified concurrently; retry the operation');
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/** Whether two entities carry identical plan content (bookkeeping excluded). */
|
|
152
|
+
function sameContent(a, b) {
|
|
153
|
+
// `doc` is bookkeeping but IS written by mutations (markExecuting), so compare
|
|
154
|
+
// it alongside the content view — only `rev`/`updatedAt` are noise.
|
|
155
|
+
return (JSON.stringify({ ...initiativeContentView(a), doc: a.doc ?? null }) ===
|
|
156
|
+
JSON.stringify({ ...initiativeContentView(b), doc: b.doc ?? null }));
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=InitiativeService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InitiativeService.js","sourceRoot":"","sources":["../../../src/modules/initiative/InitiativeService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Block, Initiative, InitiativePhase, InitiativePlanDraft } from '@cat-factory/kernel';
|
|
2
|
+
/** Turn a title into a stable, filesystem/URL-safe slug (the tracker folder name). */
|
|
3
|
+
export declare function initiativeSlug(title: string): string;
|
|
4
|
+
/**
|
|
5
|
+
* The bidirectional pipeline ⇔ block-level guard for initiative planning: a chain
|
|
6
|
+
* carrying an initiative kind may ONLY run on an `initiative`-level block, and an
|
|
7
|
+
* initiative block accepts ONLY such a chain. Called from the engine's shared
|
|
8
|
+
* `assertRunnable` (start + retry + restart), so the restriction can't drift
|
|
9
|
+
* between entry points.
|
|
10
|
+
*/
|
|
11
|
+
export declare function assertInitiativeShapeAllowed(block: Block, agentKinds: readonly string[]): void;
|
|
12
|
+
/**
|
|
13
|
+
* Validate a plan draft's internal references: unique phase/item ids, every item
|
|
14
|
+
* pointing at a declared phase, dependencies pointing at declared items, and an
|
|
15
|
+
* acyclic dependency graph. Throws {@link ValidationError} on the first violation.
|
|
16
|
+
* The lenient coercion (`coerceInitiativePlan`) already produces a well-formed
|
|
17
|
+
* draft; this re-checks at the trust boundary so a hand-supplied draft can't
|
|
18
|
+
* smuggle a broken graph into the loop.
|
|
19
|
+
*/
|
|
20
|
+
export declare function validatePlanDraft(draft: InitiativePlanDraft): void;
|
|
21
|
+
/**
|
|
22
|
+
* Fold an approved plan draft into the persisted entity, PRESERVING runtime state:
|
|
23
|
+
* an item whose id already exists keeps its `status`/`blockId`/`pr`/`note` (so a
|
|
24
|
+
* durable-driver replay of the ingest — or a later re-plan — never resets settled
|
|
25
|
+
* work), while its plan content (title/description/estimate/deps/phase) follows
|
|
26
|
+
* the draft. An item OMITTED from the draft is dropped ONLY when it is still
|
|
27
|
+
* un-materialised (`pending`, no spawned block); a re-plan that omits an item the
|
|
28
|
+
* loop already spawned or settled carries it over untouched, so a mid-flight
|
|
29
|
+
* re-plan never orphans a spawned task or erases completed work. New items start
|
|
30
|
+
* `pending`. Draft phases/items missing an id get a deterministic slug-derived one, and
|
|
31
|
+
* decisions merge by slug id keeping their original timestamps — so re-applying
|
|
32
|
+
* the same draft is byte-identical (the ingest idempotency check relies on it).
|
|
33
|
+
* Does NOT bump `rev`/`updatedAt` — the CAS writer owns those.
|
|
34
|
+
*/
|
|
35
|
+
export declare function applyPlanDraft(initiative: Initiative, draft: InitiativePlanDraft, now: number): Initiative;
|
|
36
|
+
/**
|
|
37
|
+
* The DERIVED current phase: the first phase (in declared order) still holding a
|
|
38
|
+
* non-terminal item. Null when every item is settled (the initiative is done).
|
|
39
|
+
* Deliberately never stored — deriving it means there is no cursor to corrupt.
|
|
40
|
+
*/
|
|
41
|
+
export declare function deriveCurrentPhase(initiative: Initiative): InitiativePhase | null;
|
|
42
|
+
/** Completion progress across all items (settled / total), for board rendering. */
|
|
43
|
+
export declare function initiativeProgress(initiative: Initiative): {
|
|
44
|
+
done: number;
|
|
45
|
+
total: number;
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=initiative.logic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"initiative.logic.d.ts","sourceRoot":"","sources":["../../../src/modules/initiative/initiative.logic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,UAAU,EAEV,eAAe,EACf,mBAAmB,EACpB,MAAM,qBAAqB,CAAA;AAO5B,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOpD;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAY9F;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAwClE;AAYD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,mBAAmB,EAC1B,GAAG,EAAE,MAAM,GACV,UAAU,CAkFZ;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,UAAU,GAAG,eAAe,GAAG,IAAI,CASjF;AAED,mFAAmF;AACnF,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAM1F"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { ConflictError, ValidationError, hasInitiativeKinds } from '@cat-factory/kernel';
|
|
2
|
+
import { INITIATIVE_ITEM_TERMINAL_STATUSES } from '@cat-factory/contracts';
|
|
3
|
+
// Pure initiative computations — no IO, no ports — reused by the InitiativeService,
|
|
4
|
+
// the execution engine's runnable guard, and (later slices) the execution loop.
|
|
5
|
+
/** Turn a title into a stable, filesystem/URL-safe slug (the tracker folder name). */
|
|
6
|
+
export function initiativeSlug(title) {
|
|
7
|
+
const slug = title
|
|
8
|
+
.toLowerCase()
|
|
9
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
10
|
+
.replace(/^-+|-+$/g, '')
|
|
11
|
+
.slice(0, 60);
|
|
12
|
+
return slug || 'initiative';
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The bidirectional pipeline ⇔ block-level guard for initiative planning: a chain
|
|
16
|
+
* carrying an initiative kind may ONLY run on an `initiative`-level block, and an
|
|
17
|
+
* initiative block accepts ONLY such a chain. Called from the engine's shared
|
|
18
|
+
* `assertRunnable` (start + retry + restart), so the restriction can't drift
|
|
19
|
+
* between entry points.
|
|
20
|
+
*/
|
|
21
|
+
export function assertInitiativeShapeAllowed(block, agentKinds) {
|
|
22
|
+
const initiativeShape = hasInitiativeKinds(agentKinds);
|
|
23
|
+
if (initiativeShape && block.level !== 'initiative') {
|
|
24
|
+
throw new ConflictError('The Initiative Planning pipeline can only be started on an initiative block');
|
|
25
|
+
}
|
|
26
|
+
if (!initiativeShape && block.level === 'initiative') {
|
|
27
|
+
throw new ConflictError('An initiative block only accepts the Initiative Planning pipeline (pl_initiative)');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Validate a plan draft's internal references: unique phase/item ids, every item
|
|
32
|
+
* pointing at a declared phase, dependencies pointing at declared items, and an
|
|
33
|
+
* acyclic dependency graph. Throws {@link ValidationError} on the first violation.
|
|
34
|
+
* The lenient coercion (`coerceInitiativePlan`) already produces a well-formed
|
|
35
|
+
* draft; this re-checks at the trust boundary so a hand-supplied draft can't
|
|
36
|
+
* smuggle a broken graph into the loop.
|
|
37
|
+
*/
|
|
38
|
+
export function validatePlanDraft(draft) {
|
|
39
|
+
const phaseIds = new Set();
|
|
40
|
+
for (const phase of draft.phases) {
|
|
41
|
+
if (!phase.id)
|
|
42
|
+
continue;
|
|
43
|
+
if (phaseIds.has(phase.id))
|
|
44
|
+
throw new ValidationError(`Duplicate phase id '${phase.id}'`);
|
|
45
|
+
phaseIds.add(phase.id);
|
|
46
|
+
}
|
|
47
|
+
const itemIds = new Set();
|
|
48
|
+
for (const item of draft.items) {
|
|
49
|
+
if (!item.id)
|
|
50
|
+
continue;
|
|
51
|
+
if (itemIds.has(item.id))
|
|
52
|
+
throw new ValidationError(`Duplicate item id '${item.id}'`);
|
|
53
|
+
itemIds.add(item.id);
|
|
54
|
+
}
|
|
55
|
+
for (const item of draft.items) {
|
|
56
|
+
if (item.phaseId && phaseIds.size > 0 && !phaseIds.has(item.phaseId)) {
|
|
57
|
+
throw new ValidationError(`Item '${item.id ?? item.title}' references unknown phase '${item.phaseId}'`);
|
|
58
|
+
}
|
|
59
|
+
for (const dep of item.dependsOn ?? []) {
|
|
60
|
+
if (!itemIds.has(dep)) {
|
|
61
|
+
throw new ValidationError(`Item '${item.id ?? item.title}' depends on unknown item '${dep}'`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Cycle check over the dependency edges (DFS with a visiting set).
|
|
66
|
+
const deps = new Map(draft.items.map((i) => [i.id ?? '', i.dependsOn ?? []]));
|
|
67
|
+
const done = new Set();
|
|
68
|
+
const visiting = new Set();
|
|
69
|
+
const visit = (id) => {
|
|
70
|
+
if (done.has(id))
|
|
71
|
+
return;
|
|
72
|
+
if (visiting.has(id))
|
|
73
|
+
throw new ValidationError(`Dependency cycle through item '${id}'`);
|
|
74
|
+
visiting.add(id);
|
|
75
|
+
for (const dep of deps.get(id) ?? [])
|
|
76
|
+
visit(dep);
|
|
77
|
+
visiting.delete(id);
|
|
78
|
+
done.add(id);
|
|
79
|
+
};
|
|
80
|
+
for (const id of deps.keys())
|
|
81
|
+
if (id)
|
|
82
|
+
visit(id);
|
|
83
|
+
}
|
|
84
|
+
/** Assign a unique slug-derived id, suffixing `-2`, `-3`, … on collision. */
|
|
85
|
+
function uniqueSlugId(base, taken) {
|
|
86
|
+
const slug = initiativeSlug(base);
|
|
87
|
+
let candidate = slug;
|
|
88
|
+
let n = 2;
|
|
89
|
+
while (taken.has(candidate))
|
|
90
|
+
candidate = `${slug}-${n++}`;
|
|
91
|
+
taken.add(candidate);
|
|
92
|
+
return candidate;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Fold an approved plan draft into the persisted entity, PRESERVING runtime state:
|
|
96
|
+
* an item whose id already exists keeps its `status`/`blockId`/`pr`/`note` (so a
|
|
97
|
+
* durable-driver replay of the ingest — or a later re-plan — never resets settled
|
|
98
|
+
* work), while its plan content (title/description/estimate/deps/phase) follows
|
|
99
|
+
* the draft. An item OMITTED from the draft is dropped ONLY when it is still
|
|
100
|
+
* un-materialised (`pending`, no spawned block); a re-plan that omits an item the
|
|
101
|
+
* loop already spawned or settled carries it over untouched, so a mid-flight
|
|
102
|
+
* re-plan never orphans a spawned task or erases completed work. New items start
|
|
103
|
+
* `pending`. Draft phases/items missing an id get a deterministic slug-derived one, and
|
|
104
|
+
* decisions merge by slug id keeping their original timestamps — so re-applying
|
|
105
|
+
* the same draft is byte-identical (the ingest idempotency check relies on it).
|
|
106
|
+
* Does NOT bump `rev`/`updatedAt` — the CAS writer owns those.
|
|
107
|
+
*/
|
|
108
|
+
export function applyPlanDraft(initiative, draft, now) {
|
|
109
|
+
// Seed the taken-set with every EXPLICIT id up front, so an id-less phase whose
|
|
110
|
+
// title slugifies to an id used by a LATER explicit phase can't silently collide
|
|
111
|
+
// (a hand-supplied / re-plan draft mixing explicit and omitted ids).
|
|
112
|
+
const phaseIds = new Set(draft.phases.map((p) => p.id).filter((id) => id !== undefined));
|
|
113
|
+
const phases = draft.phases.map((p) => ({
|
|
114
|
+
id: p.id ?? uniqueSlugId(p.title, phaseIds),
|
|
115
|
+
title: p.title,
|
|
116
|
+
goal: p.goal ?? '',
|
|
117
|
+
...(p.maxConcurrent !== undefined ? { maxConcurrent: p.maxConcurrent } : {}),
|
|
118
|
+
}));
|
|
119
|
+
const existingItems = new Map((initiative.items ?? []).map((i) => [i.id, i]));
|
|
120
|
+
const itemIds = new Set(draft.items.map((d) => d.id).filter((id) => id !== undefined));
|
|
121
|
+
const items = draft.items.map((d) => {
|
|
122
|
+
const id = d.id ?? uniqueSlugId(d.title, itemIds);
|
|
123
|
+
itemIds.add(id);
|
|
124
|
+
const prior = existingItems.get(id);
|
|
125
|
+
return {
|
|
126
|
+
id,
|
|
127
|
+
phaseId: d.phaseId,
|
|
128
|
+
title: d.title,
|
|
129
|
+
description: d.description ?? '',
|
|
130
|
+
dependsOn: d.dependsOn ?? [],
|
|
131
|
+
...(d.estimate ? { estimate: d.estimate } : {}),
|
|
132
|
+
...(d.pipelineId ? { pipelineId: d.pipelineId } : {}),
|
|
133
|
+
status: prior?.status ?? 'pending',
|
|
134
|
+
...(prior?.blockId != null ? { blockId: prior.blockId } : {}),
|
|
135
|
+
...(prior?.pr ? { pr: prior.pr } : {}),
|
|
136
|
+
...(prior?.note ? { note: prior.note } : {}),
|
|
137
|
+
};
|
|
138
|
+
});
|
|
139
|
+
// A re-plan that OMITS a previously-MATERIALISED item (the loop already spawned a task
|
|
140
|
+
// for it, or it already settled) must not silently drop it: that would orphan the spawned
|
|
141
|
+
// block — which still carries this initiative's `initiativeId` — and erase completed work
|
|
142
|
+
// from the tracker + progress rollup. Carry those items over unchanged; a still-`pending`,
|
|
143
|
+
// unspawned item omitted from the re-plan is genuinely removed. On a REPLAY of the SAME
|
|
144
|
+
// draft every prior item reappears by id, so `preserved` is empty and the ingest stays
|
|
145
|
+
// byte-identical (the idempotency check relies on it).
|
|
146
|
+
const draftItemIds = new Set(items.map((i) => i.id));
|
|
147
|
+
const preserved = (initiative.items ?? []).filter((i) => !draftItemIds.has(i.id) && (i.blockId != null || i.status !== 'pending'));
|
|
148
|
+
const existingDecisions = new Map((initiative.decisions ?? []).map((d) => [d.id, d]));
|
|
149
|
+
const decisionIds = new Set();
|
|
150
|
+
const decisions = (draft.decisions ?? []).map((d) => {
|
|
151
|
+
const id = uniqueSlugId(d.title, decisionIds);
|
|
152
|
+
const prior = existingDecisions.get(id);
|
|
153
|
+
return {
|
|
154
|
+
id,
|
|
155
|
+
at: prior?.at ?? now,
|
|
156
|
+
title: d.title,
|
|
157
|
+
detail: d.detail ?? '',
|
|
158
|
+
source: prior?.source ?? 'planning',
|
|
159
|
+
};
|
|
160
|
+
});
|
|
161
|
+
return {
|
|
162
|
+
...initiative,
|
|
163
|
+
goal: draft.goal ?? '',
|
|
164
|
+
constraints: draft.constraints ?? [],
|
|
165
|
+
nonGoals: draft.nonGoals ?? [],
|
|
166
|
+
analysisSummary: draft.analysisSummary ?? '',
|
|
167
|
+
phases,
|
|
168
|
+
items: [...items, ...preserved],
|
|
169
|
+
policy: draft.policy,
|
|
170
|
+
decisions,
|
|
171
|
+
caveats: draft.caveats ?? [],
|
|
172
|
+
// A fresh/re-run planning pass parks the run at the human gate next, so the
|
|
173
|
+
// entity reflects "plan drafted, awaiting approval". An already-executing
|
|
174
|
+
// initiative keeps its status (a mid-flight re-plan revises content only).
|
|
175
|
+
status: initiative.status === 'planning' || initiative.status === 'awaiting_approval'
|
|
176
|
+
? 'awaiting_approval'
|
|
177
|
+
: initiative.status,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* The DERIVED current phase: the first phase (in declared order) still holding a
|
|
182
|
+
* non-terminal item. Null when every item is settled (the initiative is done).
|
|
183
|
+
* Deliberately never stored — deriving it means there is no cursor to corrupt.
|
|
184
|
+
*/
|
|
185
|
+
export function deriveCurrentPhase(initiative) {
|
|
186
|
+
const items = initiative.items ?? [];
|
|
187
|
+
for (const phase of initiative.phases ?? []) {
|
|
188
|
+
const open = items.some((i) => i.phaseId === phase.id && !INITIATIVE_ITEM_TERMINAL_STATUSES.has(i.status));
|
|
189
|
+
if (open)
|
|
190
|
+
return phase;
|
|
191
|
+
}
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
/** Completion progress across all items (settled / total), for board rendering. */
|
|
195
|
+
export function initiativeProgress(initiative) {
|
|
196
|
+
const items = initiative.items ?? [];
|
|
197
|
+
return {
|
|
198
|
+
done: items.filter((i) => INITIATIVE_ITEM_TERMINAL_STATUSES.has(i.status)).length,
|
|
199
|
+
total: items.length,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=initiative.logic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"initiative.logic.js","sourceRoot":"","sources":["../../../src/modules/initiative/initiative.logic.ts"],"names":[],"mappings":"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"}
|
|
@@ -83,16 +83,18 @@ export declare class RequirementReviewService extends IterativeReviewService<Req
|
|
|
83
83
|
*/
|
|
84
84
|
prepareRecommendations(workspaceId: string, reviewId: string, itemIds: string[], note?: string): Promise<RequirementReview>;
|
|
85
85
|
/**
|
|
86
|
-
* Fill every `pending` recommendation on a review by running the Requirement Writer
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
* that
|
|
95
|
-
*
|
|
86
|
+
* Fill every `pending` recommendation on a review by running the Requirement Writer over
|
|
87
|
+
* CHUNKS of findings (up to {@link RECOMMENDATION_CHUNK_SIZE} per call), so a batch of N
|
|
88
|
+
* findings costs ceil(N / size) LLM calls instead of N. Grounding shared across findings (the
|
|
89
|
+
* block's best-practice fragments, the in-repo `spec/`/`tech-spec/` excerpts, and a single web
|
|
90
|
+
* search over the batch's titles) is gathered ONCE and reused across every chunk. Each chunk's
|
|
91
|
+
* results are persisted and `onProgress` is invoked with the fresh review, so an open window
|
|
92
|
+
* tracks the count live (`ready / total` advancing a chunk at a time) and the board's
|
|
93
|
+
* "Recommending…" badge clears the moment the last placeholder settles. A per-chunk Writer
|
|
94
|
+
* failure drops that chunk's placeholders and reopens their findings (so the human can answer
|
|
95
|
+
* manually) rather than wedging the whole batch. Best-effort and re-entrant: a replay that
|
|
96
|
+
* re-runs it simply finds no `pending` placeholders and produces nothing. Returns the number of
|
|
97
|
+
* recommendations produced (for the completion notification).
|
|
96
98
|
*/
|
|
97
99
|
fillPendingRecommendations(workspaceId: string, reviewId: string, opts?: {
|
|
98
100
|
onProgress?: (review: RequirementReview) => Promise<void>;
|
|
@@ -126,8 +128,15 @@ export declare class RequirementReviewService extends IterativeReviewService<Req
|
|
|
126
128
|
* marked would strand the finding with no way to settle it.
|
|
127
129
|
*/
|
|
128
130
|
rejectRecommendation(workspaceId: string, reviewId: string, recId: string): Promise<RequirementReview>;
|
|
129
|
-
/**
|
|
130
|
-
|
|
131
|
+
/**
|
|
132
|
+
* Run the Writer once for a CHUNK of live findings; returns a map of finding id → suggestion
|
|
133
|
+
* (empty when the call fails or yields nothing — the caller then drops+reopens those findings).
|
|
134
|
+
* A single-finding chunk uses the tolerant single-item coercion (a lone-finding prompt often
|
|
135
|
+
* omits the echoed itemId); a multi-finding chunk routes each suggestion back to its finding by
|
|
136
|
+
* the echoed itemId, falling back to prompt order for any the ids didn't cover (so a response
|
|
137
|
+
* that drops the ids isn't discarded wholesale — see {@link coerceChunkRecommendations}).
|
|
138
|
+
*/
|
|
139
|
+
private runWriterForChunk;
|
|
131
140
|
private mutateRecommendation;
|
|
132
141
|
/**
|
|
133
142
|
* Read the in-repo `spec/`/`tech-spec/` overviews (via RepoFiles when wired) the Writer
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RequirementReviewService.d.ts","sourceRoot":"","sources":["../../../src/modules/requirements/RequirementReviewService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EAIL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACtB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAC7E,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAA;AAUtE,OAAO,EACL,KAAK,mBAAmB,EACxB,sBAAsB,EACtB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACtB,MAAM,qCAAqC,CAAA;AAC5C,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EAEvB,KAAK,mBAAmB,
|
|
1
|
+
{"version":3,"file":"RequirementReviewService.d.ts","sourceRoot":"","sources":["../../../src/modules/requirements/RequirementReviewService.ts"],"names":[],"mappings":"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"}
|