@kernloop/faculty-scrum 0.1.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/LICENSE +21 -0
- package/dist/decompose.d.ts +88 -0
- package/dist/decompose.d.ts.map +1 -0
- package/dist/decompose.js +188 -0
- package/dist/decompose.js.map +1 -0
- package/dist/errors.d.ts +66 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +87 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/labels.d.ts +30 -0
- package/dist/labels.d.ts.map +1 -0
- package/dist/labels.js +116 -0
- package/dist/labels.js.map +1 -0
- package/dist/manifest.d.ts +19 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +41 -0
- package/dist/manifest.js.map +1 -0
- package/package.json +35 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 William Zujkowski and Kernloop contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Program goal decomposition — the MECHANICAL half, ONE ALTITUDE UP from the
|
|
3
|
+
* PM's plan decomposition (spec §5.4; CLM-0096). Where faculty-workforce's
|
|
4
|
+
* `decomposePlan` splits a ratified plan into agent-assigned children, this
|
|
5
|
+
* splits a program GOAL into an epic/story TaskContract tree, tagging each
|
|
6
|
+
* child with its program altitude/track/sprint as constraint tags.
|
|
7
|
+
*
|
|
8
|
+
* No model is ever called here: a PM model WRITES the story specs upstream;
|
|
9
|
+
* this function takes them as plain input and enforces the contract — schema
|
|
10
|
+
* validity, id/parent/overlay derivation, ceiling clamping, the budget-sum
|
|
11
|
+
* invariant, and well-formed constraint tags. The invariant is therefore
|
|
12
|
+
* unit-testable without any model in the loop. This faculty imports only
|
|
13
|
+
* @kernloop/contracts and zod (constitutional rule 5).
|
|
14
|
+
*/
|
|
15
|
+
import { type TaskContract } from '@kernloop/contracts';
|
|
16
|
+
import { z } from 'zod';
|
|
17
|
+
/**
|
|
18
|
+
* One story (or sub-epic) as proposed by the PM. Identity, overlay, and
|
|
19
|
+
* authority are NOT inputs — they are derived from the parent here, so a PM
|
|
20
|
+
* cannot grant what the parent does not hold. `altitude` is the child's
|
|
21
|
+
* program rung (e.g. 'epic' or 'story'); optional `track`/`sprint` group it.
|
|
22
|
+
*/
|
|
23
|
+
export declare const StorySpecSchema: z.ZodObject<{
|
|
24
|
+
goal: z.ZodString;
|
|
25
|
+
constraints: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
26
|
+
budget: z.ZodObject<{
|
|
27
|
+
tokens: z.ZodNumber;
|
|
28
|
+
usd: z.ZodNumber;
|
|
29
|
+
wallClockMin: z.ZodNumber;
|
|
30
|
+
}, z.core.$strict>;
|
|
31
|
+
evidence: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
32
|
+
kind: z.ZodEnum<{
|
|
33
|
+
test: "test";
|
|
34
|
+
ci: "ci";
|
|
35
|
+
doc: "doc";
|
|
36
|
+
eval: "eval";
|
|
37
|
+
}>;
|
|
38
|
+
ref: z.ZodString;
|
|
39
|
+
}, z.core.$strict>>>;
|
|
40
|
+
definitionOfDone: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
41
|
+
name: z.ZodString;
|
|
42
|
+
command: z.ZodString;
|
|
43
|
+
}, z.core.$strict>>>;
|
|
44
|
+
assignTo: z.ZodEnum<{
|
|
45
|
+
pm: "pm";
|
|
46
|
+
coder: "coder";
|
|
47
|
+
reviewer: "reviewer";
|
|
48
|
+
documenter: "documenter";
|
|
49
|
+
researcher: "researcher";
|
|
50
|
+
}>;
|
|
51
|
+
altitude: z.ZodEnum<{
|
|
52
|
+
epic: "epic";
|
|
53
|
+
story: "story";
|
|
54
|
+
task: "task";
|
|
55
|
+
}>;
|
|
56
|
+
track: z.ZodOptional<z.ZodString>;
|
|
57
|
+
sprint: z.ZodOptional<z.ZodString>;
|
|
58
|
+
}, z.core.$strict>;
|
|
59
|
+
export type StorySpec = z.infer<typeof StorySpecSchema>;
|
|
60
|
+
/** Input to {@link decomposeGoal}. */
|
|
61
|
+
export interface DecomposeGoalInput {
|
|
62
|
+
parent: TaskContract;
|
|
63
|
+
subtasks: StorySpec[];
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Derive zod-valid child TaskContracts from a program parent plus PM-proposed
|
|
67
|
+
* story specs, ONE ALTITUDE UP from `decomposePlan` (CLM-0096). Enforces:
|
|
68
|
+
*
|
|
69
|
+
* - ALTITUDE DESCENT: when the parent carries an `altitude`, it decomposes
|
|
70
|
+
* exactly one rung down (epic→story, story→task) and a `task` parent is a
|
|
71
|
+
* leaf that cannot decompose — a violation throws {@link AltitudeDescentError}.
|
|
72
|
+
* A parent with no altitude (the program root) is the unconstrained entry.
|
|
73
|
+
* - BUDGET INVARIANT: child budgets sum within the parent's on each of tokens,
|
|
74
|
+
* usd, and wallClockMin independently; any breach throws
|
|
75
|
+
* {@link ScrumBudgetExceededError} naming the dimension and amounts. An exact
|
|
76
|
+
* sum is within budget. Zero/negative child slices are rejected.
|
|
77
|
+
* - Identity: `child.id = parent.id + '.<n>'` (1-based input order),
|
|
78
|
+
* `child.parent = parent.id`, `child.overlay = parent.overlay`.
|
|
79
|
+
* - Authority: `child.authorityCeiling = min(parent ceiling, 'suggest')` — a PM
|
|
80
|
+
* cannot grant authority the parent does not hold, and generative program
|
|
81
|
+
* work enters at `suggest` (spec §3.2).
|
|
82
|
+
* - Constraints: parent constraints bind children, then the story's own, then
|
|
83
|
+
* the program tags `altitude:<v>` (+ optional `track:`/`sprint:`), then the
|
|
84
|
+
* routing tag `assign:agent.<template>`. Emitted tags are validated via
|
|
85
|
+
* {@link parseConstraintTags} so an unsafe value cannot escape.
|
|
86
|
+
*/
|
|
87
|
+
export declare function decomposeGoal(input: DecomposeGoalInput): TaskContract[];
|
|
88
|
+
//# sourceMappingURL=decompose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decompose.d.ts","sourceRoot":"","sources":["../src/decompose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAOL,KAAK,YAAY,EAElB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA2CxB;;;;;GAKG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAc1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,sCAAsC;AACtC,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,SAAS,EAAE,CAAC;CACvB;AAsFD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,YAAY,EAAE,CAmBvE"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Program goal decomposition — the MECHANICAL half, ONE ALTITUDE UP from the
|
|
3
|
+
* PM's plan decomposition (spec §5.4; CLM-0096). Where faculty-workforce's
|
|
4
|
+
* `decomposePlan` splits a ratified plan into agent-assigned children, this
|
|
5
|
+
* splits a program GOAL into an epic/story TaskContract tree, tagging each
|
|
6
|
+
* child with its program altitude/track/sprint as constraint tags.
|
|
7
|
+
*
|
|
8
|
+
* No model is ever called here: a PM model WRITES the story specs upstream;
|
|
9
|
+
* this function takes them as plain input and enforces the contract — schema
|
|
10
|
+
* validity, id/parent/overlay derivation, ceiling clamping, the budget-sum
|
|
11
|
+
* invariant, and well-formed constraint tags. The invariant is therefore
|
|
12
|
+
* unit-testable without any model in the loop. This faculty imports only
|
|
13
|
+
* @kernloop/contracts and zod (constitutional rule 5).
|
|
14
|
+
*/
|
|
15
|
+
import { AltitudeSchema, TaskContractSchema, TierSchema, constraintTag, parseConstraintTags, } from '@kernloop/contracts';
|
|
16
|
+
import { z } from 'zod';
|
|
17
|
+
import { AltitudeDescentError, InvalidParentError, InvalidStorySpecError, ScrumBudgetExceededError, } from './errors.js';
|
|
18
|
+
/** The altitude exactly one rung below a decomposable parent (the descent
|
|
19
|
+
* ladder epic → story → task). A `task` is a leaf (no rung below). */
|
|
20
|
+
const CHILD_ALTITUDE = {
|
|
21
|
+
epic: 'story',
|
|
22
|
+
story: 'task',
|
|
23
|
+
task: undefined,
|
|
24
|
+
};
|
|
25
|
+
/** Authority ladder, lowest first (spec §3.2). */
|
|
26
|
+
const TIER_ORDER = TierSchema.options;
|
|
27
|
+
/** The lower of two tiers on the ladder. */
|
|
28
|
+
function minTier(a, b) {
|
|
29
|
+
return TIER_ORDER.indexOf(a) <= TIER_ORDER.indexOf(b) ? a : b;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The shipped agent-template names a story may be assigned to. Inlined rather
|
|
33
|
+
* than imported from @kernloop/faculty-workforce — a faculty→faculty import is
|
|
34
|
+
* forbidden (constitutional rule 5). Mirrors workforce's `SHIPPED_TEMPLATE_NAMES`;
|
|
35
|
+
* custom templates are a later increment (deferred: #177).
|
|
36
|
+
*/
|
|
37
|
+
const STORY_ASSIGNEES = ['pm', 'coder', 'reviewer', 'documenter', 'researcher'];
|
|
38
|
+
/**
|
|
39
|
+
* A child budget as proposed. Stricter than TaskContract's nonnegative budget:
|
|
40
|
+
* a zero or negative slice on any dimension is rejected — a child with nothing
|
|
41
|
+
* to spend is a stub, and stubs are forbidden.
|
|
42
|
+
*/
|
|
43
|
+
const StoryBudgetSchema = z.strictObject({
|
|
44
|
+
tokens: z.number().int().positive(),
|
|
45
|
+
usd: z.number().positive(),
|
|
46
|
+
wallClockMin: z.number().positive(),
|
|
47
|
+
});
|
|
48
|
+
/**
|
|
49
|
+
* One story (or sub-epic) as proposed by the PM. Identity, overlay, and
|
|
50
|
+
* authority are NOT inputs — they are derived from the parent here, so a PM
|
|
51
|
+
* cannot grant what the parent does not hold. `altitude` is the child's
|
|
52
|
+
* program rung (e.g. 'epic' or 'story'); optional `track`/`sprint` group it.
|
|
53
|
+
*/
|
|
54
|
+
export const StorySpecSchema = z.strictObject({
|
|
55
|
+
goal: z.string().min(1),
|
|
56
|
+
constraints: z.array(z.string().min(1)).optional(),
|
|
57
|
+
budget: StoryBudgetSchema,
|
|
58
|
+
evidence: TaskContractSchema.shape.evidence.optional(),
|
|
59
|
+
definitionOfDone: TaskContractSchema.shape.definitionOfDone.optional(),
|
|
60
|
+
/** Shipped template name this child is assigned to (custom templates: later). */
|
|
61
|
+
assignTo: z.enum(STORY_ASSIGNEES),
|
|
62
|
+
/** The child's program altitude — epic | story | task. */
|
|
63
|
+
altitude: AltitudeSchema,
|
|
64
|
+
/** Optional track grouping (safe label charset, enforced on emit). */
|
|
65
|
+
track: z.string().optional(),
|
|
66
|
+
/** Optional sprint grouping (safe label charset, enforced on emit). */
|
|
67
|
+
sprint: z.string().optional(),
|
|
68
|
+
});
|
|
69
|
+
/** Parse one story spec, wrapping any schema failure as a typed error. */
|
|
70
|
+
function parseStory(spec, index) {
|
|
71
|
+
const parsed = StorySpecSchema.safeParse(spec);
|
|
72
|
+
if (!parsed.success) {
|
|
73
|
+
throw new InvalidStorySpecError(index, z.prettifyError(parsed.error));
|
|
74
|
+
}
|
|
75
|
+
return parsed.data;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Enforce altitude descent (CLM-0096): when the parent carries an `altitude`
|
|
79
|
+
* tag, it must decompose exactly one rung down — `epic`→`story`, `story`→`task`
|
|
80
|
+
* — and a `task` parent is a leaf that cannot be decomposed at all. A parent
|
|
81
|
+
* with NO altitude is the program root (the unconstrained entry) and is not
|
|
82
|
+
* checked, so the model still chooses the entry granularity. A child whose
|
|
83
|
+
* altitude is not exactly the expected rung throws {@link AltitudeDescentError}.
|
|
84
|
+
*/
|
|
85
|
+
function checkAltitudeDescent(parentAltitude, stories) {
|
|
86
|
+
if (parentAltitude === undefined)
|
|
87
|
+
return; // root entry — unconstrained
|
|
88
|
+
const expected = CHILD_ALTITUDE[parentAltitude];
|
|
89
|
+
if (expected === undefined) {
|
|
90
|
+
throw new AltitudeDescentError(parentAltitude, -1); // a task is a leaf
|
|
91
|
+
}
|
|
92
|
+
stories.forEach((spec, index) => {
|
|
93
|
+
if (spec.altitude !== expected) {
|
|
94
|
+
throw new AltitudeDescentError(parentAltitude, index, expected, spec.altitude);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/** Enforce sum(child) ≤ parent independently per budget dimension. */
|
|
99
|
+
function checkBudgetInvariant(parent, stories) {
|
|
100
|
+
for (const dimension of ['tokens', 'usd', 'wallClockMin']) {
|
|
101
|
+
const childSum = stories.reduce((sum, s) => sum + s.budget[dimension], 0);
|
|
102
|
+
if (childSum > parent.budget[dimension]) {
|
|
103
|
+
throw new ScrumBudgetExceededError(dimension, parent.budget[dimension], childSum);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/** Build a child's constraint array: the parent's FREE-FORM constraints
|
|
108
|
+
* (`inherited`, its program tags stripped) + the story's own + the child's
|
|
109
|
+
* freshly-derived altitude/track/sprint + assignment. The parent's own program
|
|
110
|
+
* tags are NOT inherited — re-deriving them per child is what lets an
|
|
111
|
+
* altitude-bearing parent decompose without a duplicate `altitude:` tag. */
|
|
112
|
+
function childConstraints(inherited, spec) {
|
|
113
|
+
return [
|
|
114
|
+
...inherited,
|
|
115
|
+
...(spec.constraints ?? []),
|
|
116
|
+
constraintTag('altitude', spec.altitude),
|
|
117
|
+
...(spec.track !== undefined ? [constraintTag('track', spec.track)] : []),
|
|
118
|
+
...(spec.sprint !== undefined ? [constraintTag('sprint', spec.sprint)] : []),
|
|
119
|
+
constraintTag('assign', `agent.${spec.assignTo}`),
|
|
120
|
+
];
|
|
121
|
+
}
|
|
122
|
+
/** Map one validated story spec to a zod-valid child TaskContract. */
|
|
123
|
+
function toChild(parent, inherited, spec, index) {
|
|
124
|
+
const constraints = childConstraints(inherited, spec);
|
|
125
|
+
// Defense in depth: the emitted program tags must read back cleanly — an
|
|
126
|
+
// unsafe track/sprint or bad altitude surfaces here as a typed story error.
|
|
127
|
+
try {
|
|
128
|
+
parseConstraintTags(constraints);
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
throw new InvalidStorySpecError(index, error instanceof Error ? error.message : String(error));
|
|
132
|
+
}
|
|
133
|
+
return TaskContractSchema.parse({
|
|
134
|
+
id: `${parent.id}.${index + 1}`,
|
|
135
|
+
parent: parent.id,
|
|
136
|
+
goal: spec.goal,
|
|
137
|
+
constraints,
|
|
138
|
+
budget: spec.budget,
|
|
139
|
+
evidence: spec.evidence ?? [],
|
|
140
|
+
definitionOfDone: spec.definitionOfDone ?? [],
|
|
141
|
+
authorityCeiling: minTier(parent.authorityCeiling, 'suggest'),
|
|
142
|
+
overlay: parent.overlay,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Derive zod-valid child TaskContracts from a program parent plus PM-proposed
|
|
147
|
+
* story specs, ONE ALTITUDE UP from `decomposePlan` (CLM-0096). Enforces:
|
|
148
|
+
*
|
|
149
|
+
* - ALTITUDE DESCENT: when the parent carries an `altitude`, it decomposes
|
|
150
|
+
* exactly one rung down (epic→story, story→task) and a `task` parent is a
|
|
151
|
+
* leaf that cannot decompose — a violation throws {@link AltitudeDescentError}.
|
|
152
|
+
* A parent with no altitude (the program root) is the unconstrained entry.
|
|
153
|
+
* - BUDGET INVARIANT: child budgets sum within the parent's on each of tokens,
|
|
154
|
+
* usd, and wallClockMin independently; any breach throws
|
|
155
|
+
* {@link ScrumBudgetExceededError} naming the dimension and amounts. An exact
|
|
156
|
+
* sum is within budget. Zero/negative child slices are rejected.
|
|
157
|
+
* - Identity: `child.id = parent.id + '.<n>'` (1-based input order),
|
|
158
|
+
* `child.parent = parent.id`, `child.overlay = parent.overlay`.
|
|
159
|
+
* - Authority: `child.authorityCeiling = min(parent ceiling, 'suggest')` — a PM
|
|
160
|
+
* cannot grant authority the parent does not hold, and generative program
|
|
161
|
+
* work enters at `suggest` (spec §3.2).
|
|
162
|
+
* - Constraints: parent constraints bind children, then the story's own, then
|
|
163
|
+
* the program tags `altitude:<v>` (+ optional `track:`/`sprint:`), then the
|
|
164
|
+
* routing tag `assign:agent.<template>`. Emitted tags are validated via
|
|
165
|
+
* {@link parseConstraintTags} so an unsafe value cannot escape.
|
|
166
|
+
*/
|
|
167
|
+
export function decomposeGoal(input) {
|
|
168
|
+
const parentResult = TaskContractSchema.safeParse(input.parent);
|
|
169
|
+
if (!parentResult.success) {
|
|
170
|
+
throw new InvalidParentError(z.prettifyError(parentResult.error));
|
|
171
|
+
}
|
|
172
|
+
const parent = parentResult.data;
|
|
173
|
+
// Parse the parent's program tags ONCE: its altitude drives descent, and its
|
|
174
|
+
// free-form (non-tag) constraints are what children inherit. A malformed
|
|
175
|
+
// parent tag is a typed InvalidParentError, never a raw throw.
|
|
176
|
+
let parentTags;
|
|
177
|
+
try {
|
|
178
|
+
parentTags = parseConstraintTags(parent.constraints);
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
throw new InvalidParentError(error instanceof Error ? error.message : String(error));
|
|
182
|
+
}
|
|
183
|
+
const stories = input.subtasks.map((spec, i) => parseStory(spec, i));
|
|
184
|
+
checkAltitudeDescent(parentTags.altitude, stories);
|
|
185
|
+
checkBudgetInvariant(parent, stories);
|
|
186
|
+
return stories.map((spec, i) => toChild(parent, parentTags.other, spec, i));
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=decompose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decompose.js","sourceRoot":"","sources":["../src/decompose.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed errors thrown at the scrum faculty's boundaries. Callers discriminate
|
|
3
|
+
* on `name` or `instanceof` — never on message text. Mirrors the shapes of
|
|
4
|
+
* faculty-workforce's decomposition errors (spec §5.4).
|
|
5
|
+
*/
|
|
6
|
+
import type { Altitude, TaskContract } from '@kernloop/contracts';
|
|
7
|
+
/** The three independently-summed budget dimensions of a TaskContract. */
|
|
8
|
+
export type BudgetDimension = keyof TaskContract['budget'];
|
|
9
|
+
/**
|
|
10
|
+
* Thrown when the sum of child (story) budgets exceeds the parent budget on
|
|
11
|
+
* any dimension (spec §5.4: child TaskContract budgets "must sum within the
|
|
12
|
+
* parent's"; CLM-0096). Carries the offending dimension and both amounts so a
|
|
13
|
+
* caller can report — or replan — without parsing text.
|
|
14
|
+
*/
|
|
15
|
+
export declare class ScrumBudgetExceededError extends Error {
|
|
16
|
+
readonly dimension: BudgetDimension;
|
|
17
|
+
readonly parentAmount: number;
|
|
18
|
+
readonly childSum: number;
|
|
19
|
+
constructor(dimension: BudgetDimension, parentAmount: number, childSum: number);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Thrown when the parent contract handed to decomposeGoal fails
|
|
23
|
+
* TaskContractSchema validation (charter: zod-validate at every contract
|
|
24
|
+
* boundary).
|
|
25
|
+
*/
|
|
26
|
+
export declare class InvalidParentError extends Error {
|
|
27
|
+
constructor(detail: string);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Thrown when a story spec is malformed for a reason other than the budget-sum
|
|
31
|
+
* invariant: schema violation, zero/negative budget dimension, an `assignTo`
|
|
32
|
+
* naming no shipped template, or an `altitude` outside the enum.
|
|
33
|
+
*/
|
|
34
|
+
export declare class InvalidStorySpecError extends Error {
|
|
35
|
+
/** Zero-based index of the offending story in the input array. */
|
|
36
|
+
readonly index: number;
|
|
37
|
+
constructor(index: number, detail: string);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Thrown when a decomposition violates altitude descent (spec §5.4; CLM-0096):
|
|
41
|
+
* an altitude-bearing parent must decompose exactly ONE rung down (epic→story,
|
|
42
|
+
* story→task), and a `task`-altitude parent is a LEAF that cannot decompose at
|
|
43
|
+
* all. (A parent with no altitude — the program root — is the unconstrained
|
|
44
|
+
* entry and is not checked.) Carries the parent + expected/actual child
|
|
45
|
+
* altitudes so a caller can report or replan without parsing text. For a
|
|
46
|
+
* task-parent leaf violation, `expected`/`actual` are omitted.
|
|
47
|
+
*/
|
|
48
|
+
export declare class AltitudeDescentError extends Error {
|
|
49
|
+
readonly parentAltitude: Altitude;
|
|
50
|
+
readonly expected?: Altitude;
|
|
51
|
+
readonly actual?: Altitude;
|
|
52
|
+
/** Zero-based index of the offending child, or -1 for a task-leaf parent. */
|
|
53
|
+
readonly index: number;
|
|
54
|
+
constructor(parentAltitude: Altitude, index: number, expected?: Altitude, actual?: Altitude);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Thrown by {@link programLabels} when an emitted label would not satisfy the
|
|
58
|
+
* tracker's label charset. Unreachable from valid decomposed input (altitude is
|
|
59
|
+
* an enum; track/sprint/assign are charset-bound upstream) — it is a typed
|
|
60
|
+
* invariant guard so a FUTURE label source that slips an unsafe value surfaces
|
|
61
|
+
* as a clean, discriminable error rather than escaping as a raw throw.
|
|
62
|
+
*/
|
|
63
|
+
export declare class UnsafeLabelError extends Error {
|
|
64
|
+
constructor(label: string);
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAElE,0EAA0E;AAC1E,MAAM,MAAM,eAAe,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAC;AAE3D;;;;;GAKG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;IACjD,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,SAAS,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAU/E;AAED;;;;GAIG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,MAAM,EAAE,MAAM;CAI3B;AAED;;;;GAIG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAK1C;AAED;;;;;;;;GAQG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,cAAc,EAAE,QAAQ,CAAC;IAClC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC;IAC3B,6EAA6E;IAC7E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,cAAc,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,QAAQ;CAa5F;AAED;;;;;;GAMG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,KAAK,EAAE,MAAM;CAI1B"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown when the sum of child (story) budgets exceeds the parent budget on
|
|
3
|
+
* any dimension (spec §5.4: child TaskContract budgets "must sum within the
|
|
4
|
+
* parent's"; CLM-0096). Carries the offending dimension and both amounts so a
|
|
5
|
+
* caller can report — or replan — without parsing text.
|
|
6
|
+
*/
|
|
7
|
+
export class ScrumBudgetExceededError extends Error {
|
|
8
|
+
dimension;
|
|
9
|
+
parentAmount;
|
|
10
|
+
childSum;
|
|
11
|
+
constructor(dimension, parentAmount, childSum) {
|
|
12
|
+
super(`child budgets exceed parent on ${dimension}: ` +
|
|
13
|
+
`sum ${childSum} > parent ${parentAmount} (spec §5.4)`);
|
|
14
|
+
this.name = 'ScrumBudgetExceededError';
|
|
15
|
+
this.dimension = dimension;
|
|
16
|
+
this.parentAmount = parentAmount;
|
|
17
|
+
this.childSum = childSum;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Thrown when the parent contract handed to decomposeGoal fails
|
|
22
|
+
* TaskContractSchema validation (charter: zod-validate at every contract
|
|
23
|
+
* boundary).
|
|
24
|
+
*/
|
|
25
|
+
export class InvalidParentError extends Error {
|
|
26
|
+
constructor(detail) {
|
|
27
|
+
super(detail);
|
|
28
|
+
this.name = 'InvalidParentError';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Thrown when a story spec is malformed for a reason other than the budget-sum
|
|
33
|
+
* invariant: schema violation, zero/negative budget dimension, an `assignTo`
|
|
34
|
+
* naming no shipped template, or an `altitude` outside the enum.
|
|
35
|
+
*/
|
|
36
|
+
export class InvalidStorySpecError extends Error {
|
|
37
|
+
/** Zero-based index of the offending story in the input array. */
|
|
38
|
+
index;
|
|
39
|
+
constructor(index, detail) {
|
|
40
|
+
super(`story[${index}]: ${detail}`);
|
|
41
|
+
this.name = 'InvalidStorySpecError';
|
|
42
|
+
this.index = index;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Thrown when a decomposition violates altitude descent (spec §5.4; CLM-0096):
|
|
47
|
+
* an altitude-bearing parent must decompose exactly ONE rung down (epic→story,
|
|
48
|
+
* story→task), and a `task`-altitude parent is a LEAF that cannot decompose at
|
|
49
|
+
* all. (A parent with no altitude — the program root — is the unconstrained
|
|
50
|
+
* entry and is not checked.) Carries the parent + expected/actual child
|
|
51
|
+
* altitudes so a caller can report or replan without parsing text. For a
|
|
52
|
+
* task-parent leaf violation, `expected`/`actual` are omitted.
|
|
53
|
+
*/
|
|
54
|
+
export class AltitudeDescentError extends Error {
|
|
55
|
+
parentAltitude;
|
|
56
|
+
expected;
|
|
57
|
+
actual;
|
|
58
|
+
/** Zero-based index of the offending child, or -1 for a task-leaf parent. */
|
|
59
|
+
index;
|
|
60
|
+
constructor(parentAltitude, index, expected, actual) {
|
|
61
|
+
super(expected === undefined
|
|
62
|
+
? `a "${parentAltitude}" is a leaf and cannot be decomposed (spec §5.4)`
|
|
63
|
+
: `story[${index}]: altitude "${actual ?? '<missing>'}" violates descent — ` +
|
|
64
|
+
`a "${parentAltitude}" parent decomposes to "${expected}" children (spec §5.4)`);
|
|
65
|
+
this.name = 'AltitudeDescentError';
|
|
66
|
+
this.parentAltitude = parentAltitude;
|
|
67
|
+
this.index = index;
|
|
68
|
+
if (expected !== undefined)
|
|
69
|
+
this.expected = expected;
|
|
70
|
+
if (actual !== undefined)
|
|
71
|
+
this.actual = actual;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Thrown by {@link programLabels} when an emitted label would not satisfy the
|
|
76
|
+
* tracker's label charset. Unreachable from valid decomposed input (altitude is
|
|
77
|
+
* an enum; track/sprint/assign are charset-bound upstream) — it is a typed
|
|
78
|
+
* invariant guard so a FUTURE label source that slips an unsafe value surfaces
|
|
79
|
+
* as a clean, discriminable error rather than escaping as a raw throw.
|
|
80
|
+
*/
|
|
81
|
+
export class UnsafeLabelError extends Error {
|
|
82
|
+
constructor(label) {
|
|
83
|
+
super(`program label "${label}" is not tracker-label-safe`);
|
|
84
|
+
this.name = 'UnsafeLabelError';
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAUA;;;;;GAKG;AACH,MAAM,OAAO,wBAAyB,SAAQ,KAAK;IACxC,SAAS,CAAkB;IAC3B,YAAY,CAAS;IACrB,QAAQ,CAAS;IAE1B,YAAY,SAA0B,EAAE,YAAoB,EAAE,QAAgB;QAC5E,KAAK,CACH,kCAAkC,SAAS,IAAI;YAC7C,OAAO,QAAQ,aAAa,YAAY,cAAc,CACzD,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;QACvC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,MAAc;QACxB,KAAK,CAAC,MAAM,CAAC,CAAC;QACd,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9C,kEAAkE;IACzD,KAAK,CAAS;IAEvB,YAAY,KAAa,EAAE,MAAc;QACvC,KAAK,CAAC,SAAS,KAAK,MAAM,MAAM,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACpC,cAAc,CAAW;IACzB,QAAQ,CAAY;IACpB,MAAM,CAAY;IAC3B,6EAA6E;IACpE,KAAK,CAAS;IAEvB,YAAY,cAAwB,EAAE,KAAa,EAAE,QAAmB,EAAE,MAAiB;QACzF,KAAK,CACH,QAAQ,KAAK,SAAS;YACpB,CAAC,CAAC,MAAM,cAAc,kDAAkD;YACxE,CAAC,CAAC,SAAS,KAAK,gBAAgB,MAAM,IAAI,WAAW,uBAAuB;gBACxE,MAAM,cAAc,2BAA2B,QAAQ,wBAAwB,CACtF,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,QAAQ,KAAK,SAAS;YAAE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACrD,IAAI,MAAM,KAAK,SAAS;YAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACjD,CAAC;CACF;AAED;;;;;;GAMG;AACH,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC,YAAY,KAAa;QACvB,KAAK,CAAC,kBAAkB,KAAK,6BAA6B,CAAC,CAAC;QAC5D,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @kernloop/faculty-scrum — the scrum/program-decomposition faculty (spec §5.4).
|
|
3
|
+
*
|
|
4
|
+
* Decomposes a program goal into an epic/story TaskContract tree ONE ALTITUDE
|
|
5
|
+
* UP from the PM's plan decomposition: child budgets must sum within the
|
|
6
|
+
* parent's on every dimension (the budget-sum invariant), and each child
|
|
7
|
+
* carries its program altitude/track/sprint as constraint tags (CLM-0096).
|
|
8
|
+
* GitHub-free and model-free — generative work happens elsewhere; this package
|
|
9
|
+
* is pure mechanical enforcement, surfaced through the suggest-tier
|
|
10
|
+
* `kernloop program decompose` CLI. It imports only @kernloop/contracts and
|
|
11
|
+
* external dependencies (constitutional rule 5).
|
|
12
|
+
*/
|
|
13
|
+
export { decomposeGoal, StorySpecSchema } from './decompose.js';
|
|
14
|
+
export type { StorySpec, DecomposeGoalInput } from './decompose.js';
|
|
15
|
+
export { programLabels, programIssueBody } from './labels.js';
|
|
16
|
+
export { AltitudeDescentError, InvalidParentError, InvalidStorySpecError, ScrumBudgetExceededError, UnsafeLabelError, } from './errors.js';
|
|
17
|
+
export type { BudgetDimension } from './errors.js';
|
|
18
|
+
export { scrumManifest } from './manifest.js';
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAChE,YAAY,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,EACrB,wBAAwB,EACxB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @kernloop/faculty-scrum — the scrum/program-decomposition faculty (spec §5.4).
|
|
3
|
+
*
|
|
4
|
+
* Decomposes a program goal into an epic/story TaskContract tree ONE ALTITUDE
|
|
5
|
+
* UP from the PM's plan decomposition: child budgets must sum within the
|
|
6
|
+
* parent's on every dimension (the budget-sum invariant), and each child
|
|
7
|
+
* carries its program altitude/track/sprint as constraint tags (CLM-0096).
|
|
8
|
+
* GitHub-free and model-free — generative work happens elsewhere; this package
|
|
9
|
+
* is pure mechanical enforcement, surfaced through the suggest-tier
|
|
10
|
+
* `kernloop program decompose` CLI. It imports only @kernloop/contracts and
|
|
11
|
+
* external dependencies (constitutional rule 5).
|
|
12
|
+
*/
|
|
13
|
+
export { decomposeGoal, StorySpecSchema } from './decompose.js';
|
|
14
|
+
export { programLabels, programIssueBody } from './labels.js';
|
|
15
|
+
export { AltitudeDescentError, InvalidParentError, InvalidStorySpecError, ScrumBudgetExceededError, UnsafeLabelError, } from './errors.js';
|
|
16
|
+
export { scrumManifest } from './manifest.js';
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEhE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,EACrB,wBAAwB,EACxB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/labels.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The constraint-tag → GitHub-label map + issue-body rendering for program
|
|
3
|
+
* emission (spec §5.4; CLM-0097). The half of `kernloop program emit` that is
|
|
4
|
+
* PURE and GitHub-free: it turns a decomposed child TaskContract into the
|
|
5
|
+
* label set and issue body the CLI will hand to the hardened @kernloop/tracker.
|
|
6
|
+
*
|
|
7
|
+
* Faculty isolation (constitutional rule 5): this module imports ONLY
|
|
8
|
+
* @kernloop/contracts and zod — never the tracker and never the CLI. The label
|
|
9
|
+
* charset it must satisfy (the tracker's `LabelSchema`) is therefore asserted
|
|
10
|
+
* here with an inlined copy of the same regex, not by importing the tracker.
|
|
11
|
+
*/
|
|
12
|
+
import { type TaskContract } from '@kernloop/contracts';
|
|
13
|
+
/**
|
|
14
|
+
* Map a TaskContract's constraint tags to GitHub labels through the one
|
|
15
|
+
* `LABEL_MAP` table — so the GitHub view and future loop routing never
|
|
16
|
+
* diverge [CLM-0097]. Emits `altitude:<a>`, `track:<t>`, `sprint:<s>`, and
|
|
17
|
+
* `agent:<t>` (from `assign:agent.<t>`); free-form/unknown constraints (the
|
|
18
|
+
* `other` bucket) produce NO label. Output is deduped and every label is
|
|
19
|
+
* asserted tracker-label-safe ({@link assertLabelSafe}) before return.
|
|
20
|
+
*/
|
|
21
|
+
export declare function programLabels(constraints: readonly string[]): string[];
|
|
22
|
+
/**
|
|
23
|
+
* Render the GitHub issue body for a decomposed child node (CLM-0097): the
|
|
24
|
+
* node goal as prose, then the replayable task-shaped payload (id, parent,
|
|
25
|
+
* goal, constraints, budget) as a fenced JSON block a human or `kernloop run`
|
|
26
|
+
* can pick up. Pure — no secrets, no tracker, no model. Mirrors the spirit of
|
|
27
|
+
* faculty-observer's `issueBody`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function programIssueBody(node: TaskContract): string;
|
|
30
|
+
//# sourceMappingURL=labels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../src/labels.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAwD7E;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAatE;AAeD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAU3D"}
|
package/dist/labels.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The constraint-tag → GitHub-label map + issue-body rendering for program
|
|
3
|
+
* emission (spec §5.4; CLM-0097). The half of `kernloop program emit` that is
|
|
4
|
+
* PURE and GitHub-free: it turns a decomposed child TaskContract into the
|
|
5
|
+
* label set and issue body the CLI will hand to the hardened @kernloop/tracker.
|
|
6
|
+
*
|
|
7
|
+
* Faculty isolation (constitutional rule 5): this module imports ONLY
|
|
8
|
+
* @kernloop/contracts and zod — never the tracker and never the CLI. The label
|
|
9
|
+
* charset it must satisfy (the tracker's `LabelSchema`) is therefore asserted
|
|
10
|
+
* here with an inlined copy of the same regex, not by importing the tracker.
|
|
11
|
+
*/
|
|
12
|
+
import { parseConstraintTags } from '@kernloop/contracts';
|
|
13
|
+
import { z } from 'zod';
|
|
14
|
+
import { UnsafeLabelError } from './errors.js';
|
|
15
|
+
/**
|
|
16
|
+
* The tracker `LabelSchema` charset, INLINED (faculty-scrum must not import the
|
|
17
|
+
* tracker — constitutional rule 5). Kept byte-identical to
|
|
18
|
+
* `@kernloop/tracker`'s `LabelSchema` regex (leading alphanumeric, then the
|
|
19
|
+
* `[A-Za-z0-9 _.\-/:]` charset, ≤80, no leading `-`) so a label this module
|
|
20
|
+
* emits is provably accepted at the sink. {@link assertLabelSafe} applies it.
|
|
21
|
+
*/
|
|
22
|
+
const LABEL_SAFE = /^[A-Za-z0-9][A-Za-z0-9 _.\-/:]*$/;
|
|
23
|
+
/**
|
|
24
|
+
* Assert an emitted label satisfies the tracker's label charset (≤80, leading
|
|
25
|
+
* alphanumeric). Every value `programLabels` emits is already charset-bound
|
|
26
|
+
* upstream — altitude is the `epic|story|task` enum; track/sprint/assign are
|
|
27
|
+
* validated by `parseConstraintTags` against `[A-Za-z0-9._-]` — so this is
|
|
28
|
+
* defense in depth: a future tag source that slips an unsafe value cannot
|
|
29
|
+
* escape to `gh` as a flag-shaped label.
|
|
30
|
+
*/
|
|
31
|
+
function assertLabelSafe(label) {
|
|
32
|
+
if (label.length > 80 || !LABEL_SAFE.test(label)) {
|
|
33
|
+
throw new UnsafeLabelError(label);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* THE ONE MAP: how a single program constraint tag becomes a GitHub label.
|
|
38
|
+
* Keyed by the {@link parseConstraintTags} field, each entry renders the
|
|
39
|
+
* typed value to a label string. This is the single source of truth so the
|
|
40
|
+
* GitHub view and future loop routing can never diverge on the spelling.
|
|
41
|
+
*
|
|
42
|
+
* Note the `assign` transform: `assign:agent.<t>` (the constraint carrier) maps
|
|
43
|
+
* to the label `agent:<t>` — the key changes from `assign` to `agent` and the
|
|
44
|
+
* `agent.<t>` value's `.` becomes `:`. The other three keys pass through.
|
|
45
|
+
*
|
|
46
|
+
* INCREMENT 4 (#52) NOTE: the REVERSE direction (label → tag, for loop
|
|
47
|
+
* routing) is a trivial later addition over this same table, and when the
|
|
48
|
+
* kernel/router needs it the table moves to a shared home. For now
|
|
49
|
+
* faculty-scrum is the only consumer.
|
|
50
|
+
*/
|
|
51
|
+
const LABEL_MAP = {
|
|
52
|
+
altitude: (v) => `altitude:${v}`,
|
|
53
|
+
track: (v) => `track:${v}`,
|
|
54
|
+
sprint: (v) => `sprint:${v}`,
|
|
55
|
+
// `assign:agent.<t>` → `agent:<t>` (drop the `assign:` prefix, `.` → `:`).
|
|
56
|
+
// Anything not of the `agent.<t>` shape produces no label (skipped).
|
|
57
|
+
assign: (v) => (v.startsWith('agent.') ? `agent:${v.slice('agent.'.length)}` : undefined),
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Map a TaskContract's constraint tags to GitHub labels through the one
|
|
61
|
+
* `LABEL_MAP` table — so the GitHub view and future loop routing never
|
|
62
|
+
* diverge [CLM-0097]. Emits `altitude:<a>`, `track:<t>`, `sprint:<s>`, and
|
|
63
|
+
* `agent:<t>` (from `assign:agent.<t>`); free-form/unknown constraints (the
|
|
64
|
+
* `other` bucket) produce NO label. Output is deduped and every label is
|
|
65
|
+
* asserted tracker-label-safe ({@link assertLabelSafe}) before return.
|
|
66
|
+
*/
|
|
67
|
+
export function programLabels(constraints) {
|
|
68
|
+
const tags = parseConstraintTags(constraints);
|
|
69
|
+
const out = [];
|
|
70
|
+
if (tags.altitude !== undefined)
|
|
71
|
+
out.push(LABEL_MAP.altitude(tags.altitude));
|
|
72
|
+
if (tags.track !== undefined)
|
|
73
|
+
out.push(LABEL_MAP.track(tags.track));
|
|
74
|
+
if (tags.sprint !== undefined)
|
|
75
|
+
out.push(LABEL_MAP.sprint(tags.sprint));
|
|
76
|
+
if (tags.assign !== undefined) {
|
|
77
|
+
const label = LABEL_MAP.assign(tags.assign);
|
|
78
|
+
if (label !== undefined)
|
|
79
|
+
out.push(label);
|
|
80
|
+
}
|
|
81
|
+
const deduped = [...new Set(out)];
|
|
82
|
+
for (const label of deduped)
|
|
83
|
+
assertLabelSafe(label);
|
|
84
|
+
return deduped;
|
|
85
|
+
}
|
|
86
|
+
/** The replayable, task-shaped payload embedded in a program issue body. */
|
|
87
|
+
const PayloadSchema = z.strictObject({
|
|
88
|
+
id: z.string(),
|
|
89
|
+
parent: z.string().optional(),
|
|
90
|
+
goal: z.string(),
|
|
91
|
+
constraints: z.array(z.string()),
|
|
92
|
+
budget: z.object({
|
|
93
|
+
tokens: z.number(),
|
|
94
|
+
usd: z.number(),
|
|
95
|
+
wallClockMin: z.number(),
|
|
96
|
+
}),
|
|
97
|
+
});
|
|
98
|
+
/**
|
|
99
|
+
* Render the GitHub issue body for a decomposed child node (CLM-0097): the
|
|
100
|
+
* node goal as prose, then the replayable task-shaped payload (id, parent,
|
|
101
|
+
* goal, constraints, budget) as a fenced JSON block a human or `kernloop run`
|
|
102
|
+
* can pick up. Pure — no secrets, no tracker, no model. Mirrors the spirit of
|
|
103
|
+
* faculty-observer's `issueBody`.
|
|
104
|
+
*/
|
|
105
|
+
export function programIssueBody(node) {
|
|
106
|
+
const payload = PayloadSchema.parse({
|
|
107
|
+
id: node.id,
|
|
108
|
+
...(node.parent !== undefined ? { parent: node.parent } : {}),
|
|
109
|
+
goal: node.goal,
|
|
110
|
+
constraints: node.constraints,
|
|
111
|
+
budget: node.budget,
|
|
112
|
+
});
|
|
113
|
+
const json = JSON.stringify(payload, null, 2);
|
|
114
|
+
return `${node.goal}\n\n---\nTask-shaped payload — feed to \`kernloop run\` (no privileged path):\n\n\`\`\`json\n${json}\n\`\`\``;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=labels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.js","sourceRoot":"","sources":["../src/labels.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The scrum faculty's registration record (spec §4, §5.4). Parsed through
|
|
3
|
+
* `ManifestSchema` at module load so an invalid manifest fails fast, not at
|
|
4
|
+
* registry time.
|
|
5
|
+
*/
|
|
6
|
+
import { type Manifest } from '@kernloop/contracts';
|
|
7
|
+
/**
|
|
8
|
+
* The faculty-scrum registration manifest. Tier is `suggest` — program
|
|
9
|
+
* decomposition stands behind the PM, a generative role, and anything
|
|
10
|
+
* generative enters at `suggest` (spec §3.2); promotion needs evidence +
|
|
11
|
+
* ratification. Consumes TaskContract (the program parent) and emits
|
|
12
|
+
* TaskContract (the derived epic/story children). Cost is zero tokens/usd:
|
|
13
|
+
* decomposition enforcement is mechanical — the PM's generative work runs
|
|
14
|
+
* elsewhere, where the adapters meter it. The capability has no run-executor:
|
|
15
|
+
* it is surfaced through the `kernloop program decompose` CLI verb (CLM-0096),
|
|
16
|
+
* registered here for observability and its ladder tier.
|
|
17
|
+
*/
|
|
18
|
+
export declare const scrumManifest: Manifest;
|
|
19
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,EAAE,QAuB1B,CAAC"}
|
package/dist/manifest.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The scrum faculty's registration record (spec §4, §5.4). Parsed through
|
|
3
|
+
* `ManifestSchema` at module load so an invalid manifest fails fast, not at
|
|
4
|
+
* registry time.
|
|
5
|
+
*/
|
|
6
|
+
import { ManifestSchema } from '@kernloop/contracts';
|
|
7
|
+
/**
|
|
8
|
+
* The faculty-scrum registration manifest. Tier is `suggest` — program
|
|
9
|
+
* decomposition stands behind the PM, a generative role, and anything
|
|
10
|
+
* generative enters at `suggest` (spec §3.2); promotion needs evidence +
|
|
11
|
+
* ratification. Consumes TaskContract (the program parent) and emits
|
|
12
|
+
* TaskContract (the derived epic/story children). Cost is zero tokens/usd:
|
|
13
|
+
* decomposition enforcement is mechanical — the PM's generative work runs
|
|
14
|
+
* elsewhere, where the adapters meter it. The capability has no run-executor:
|
|
15
|
+
* it is surfaced through the `kernloop program decompose` CLI verb (CLM-0096),
|
|
16
|
+
* registered here for observability and its ladder tier.
|
|
17
|
+
*/
|
|
18
|
+
export const scrumManifest = ManifestSchema.parse({
|
|
19
|
+
name: '@kernloop/faculty-scrum',
|
|
20
|
+
version: '0.1.0',
|
|
21
|
+
kind: 'faculty',
|
|
22
|
+
capabilities: [
|
|
23
|
+
{
|
|
24
|
+
name: 'scrum.decompose-goal',
|
|
25
|
+
description: 'Decompose a program goal into an epic/story TaskContract tree under the budget-sum invariant with altitude/track/sprint tags (spec §5.4)',
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
contracts: {
|
|
29
|
+
consumes: ['TaskContract'],
|
|
30
|
+
emits: ['TaskContract'],
|
|
31
|
+
},
|
|
32
|
+
cost: {
|
|
33
|
+
tokens: 0,
|
|
34
|
+
usd: 0,
|
|
35
|
+
latencyMs: 10,
|
|
36
|
+
},
|
|
37
|
+
tier: 'suggest',
|
|
38
|
+
claims: ['CLM-0096'],
|
|
39
|
+
maturity: 'stable',
|
|
40
|
+
});
|
|
41
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,cAAc,EAAiB,MAAM,qBAAqB,CAAC;AAEpE;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,aAAa,GAAa,cAAc,CAAC,KAAK,CAAC;IAC1D,IAAI,EAAE,yBAAyB;IAC/B,OAAO,EAAE,OAAO;IAChB,IAAI,EAAE,SAAS;IACf,YAAY,EAAE;QACZ;YACE,IAAI,EAAE,sBAAsB;YAC5B,WAAW,EACT,0IAA0I;SAC7I;KACF;IACD,SAAS,EAAE;QACT,QAAQ,EAAE,CAAC,cAAc,CAAC;QAC1B,KAAK,EAAE,CAAC,cAAc,CAAC;KACxB;IACD,IAAI,EAAE;QACJ,MAAM,EAAE,CAAC;QACT,GAAG,EAAE,CAAC;QACN,SAAS,EAAE,EAAE;KACd;IACD,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,CAAC,UAAU,CAAC;IACpB,QAAQ,EAAE,QAAQ;CACnB,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kernloop/faculty-scrum",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Kernloop scrum/program-decomposition faculty (spec §5.4). Decomposes a goal into an epic/story TaskContract tree one altitude up from the PM's plan decomposition: child budgets must sum within the parent's on every dimension, and each child carries altitude/track/sprint constraint tags. GitHub-free and model-free — pure, mechanical decomposition surfaced through the suggest-tier `kernloop program decompose` CLI.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"zod": "^4.4.3",
|
|
20
|
+
"@kernloop/contracts": "0.1.0"
|
|
21
|
+
},
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/kernloop/kernloop.git",
|
|
28
|
+
"directory": "packages/faculty-scrum"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsc -p tsconfig.json",
|
|
32
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
33
|
+
"test": "vitest run --coverage"
|
|
34
|
+
}
|
|
35
|
+
}
|