@kaddo/cli 3.74.0 → 3.75.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/core.js
CHANGED
|
@@ -3686,9 +3686,6 @@ var RECOMMENDED_SKILLS = [...SKILL_GROUPS.delivery, ...SKILL_GROUPS.tech];
|
|
|
3686
3686
|
function skillInstallPath(id) {
|
|
3687
3687
|
return `knowledge/skills/${id}/skill.md`;
|
|
3688
3688
|
}
|
|
3689
|
-
function skillById(id) {
|
|
3690
|
-
return SKILLS.find((s) => s.id === id);
|
|
3691
|
-
}
|
|
3692
3689
|
|
|
3693
3690
|
// src/agents/responsibility.ts
|
|
3694
3691
|
var RESPONSIBILITY_MATRIX = {
|
|
@@ -7456,6 +7453,17 @@ function analyzeCrossRepoEvidence(input) {
|
|
|
7456
7453
|
|
|
7457
7454
|
// src/core/work-items.ts
|
|
7458
7455
|
import matter6 from "gray-matter";
|
|
7456
|
+
function computeRefinementStatus(wi) {
|
|
7457
|
+
const aspects = {
|
|
7458
|
+
outcome: Boolean(wi.currentBehavior?.trim() || wi.targetBehavior?.trim()),
|
|
7459
|
+
journey: Boolean(wi.entryPoints?.trim() || wi.endToEndFlow?.trim()),
|
|
7460
|
+
modules: wi.affectedModules.length > 0 || wi.moduleCoverage.length > 0,
|
|
7461
|
+
impact: wi.impactAnalysis.length > 0,
|
|
7462
|
+
acceptance: wi.acceptanceCriteria.length > 0
|
|
7463
|
+
};
|
|
7464
|
+
const refined = aspects.outcome && aspects.modules && aspects.acceptance;
|
|
7465
|
+
return { status: refined ? "refined" : "needs-refinement", aspects };
|
|
7466
|
+
}
|
|
7459
7467
|
var WorkItemNotFoundError = class extends Error {
|
|
7460
7468
|
constructor(workItemId) {
|
|
7461
7469
|
super(`Work Item "${workItemId}" was not found.`);
|
|
@@ -7531,8 +7539,9 @@ function getWorkItem(dir, workItemId) {
|
|
|
7531
7539
|
const fm = match.rawFrontmatter;
|
|
7532
7540
|
const knowledge = discoverKnowledge(dir).filter((a) => !a.isWorkItem);
|
|
7533
7541
|
const knowledgeById = new Map(knowledge.filter((k) => k.id).map((k) => [k.id, k]));
|
|
7534
|
-
|
|
7542
|
+
const detail = {
|
|
7535
7543
|
...base,
|
|
7544
|
+
summary: match.summary?.trim() || null,
|
|
7536
7545
|
actor: sectionText(sections, ["actor"]),
|
|
7537
7546
|
outcome: sectionText(sections, ["actor and outcome", "outcome", "expected result"]),
|
|
7538
7547
|
currentBehavior: sectionText(sections, ["current behavior", "current behaviour"]),
|
|
@@ -7552,6 +7561,7 @@ function getWorkItem(dir, workItemId) {
|
|
|
7552
7561
|
source: parseWorkItemSource(fm),
|
|
7553
7562
|
path: match.relPath
|
|
7554
7563
|
};
|
|
7564
|
+
return { ...detail, refinement: computeRefinementStatus(detail) };
|
|
7555
7565
|
}
|
|
7556
7566
|
function readBody(filePath) {
|
|
7557
7567
|
try {
|
|
@@ -7724,6 +7734,194 @@ import fs2 from "fs";
|
|
|
7724
7734
|
import path2 from "path";
|
|
7725
7735
|
import crypto from "crypto";
|
|
7726
7736
|
import matter7 from "gray-matter";
|
|
7737
|
+
|
|
7738
|
+
// src/core/knowledge-levels.ts
|
|
7739
|
+
var WORK_ITEM_TYPES2 = ["feature", "bugfix", "hotfix", "spike", "chore"];
|
|
7740
|
+
var TYPE_ALIASES = {
|
|
7741
|
+
setup: "chore",
|
|
7742
|
+
maintenance: "chore",
|
|
7743
|
+
tooling: "chore",
|
|
7744
|
+
infrastructure: "chore",
|
|
7745
|
+
infra: "chore",
|
|
7746
|
+
config: "chore",
|
|
7747
|
+
configuration: "chore",
|
|
7748
|
+
refactor: "chore"
|
|
7749
|
+
};
|
|
7750
|
+
var LEVELS = {
|
|
7751
|
+
K0: {
|
|
7752
|
+
level: "K0",
|
|
7753
|
+
description: "Trivial change. No formal knowledge required.",
|
|
7754
|
+
questions: [],
|
|
7755
|
+
qualityGate: []
|
|
7756
|
+
},
|
|
7757
|
+
K1: {
|
|
7758
|
+
level: "K1",
|
|
7759
|
+
description: "Simple fix or hotfix.",
|
|
7760
|
+
questions: [
|
|
7761
|
+
{
|
|
7762
|
+
id: "problem",
|
|
7763
|
+
prompt: "What problem does this fix?",
|
|
7764
|
+
placeholder: "e.g. Button is not clickable on mobile",
|
|
7765
|
+
frontMatterField: "problem",
|
|
7766
|
+
required: true
|
|
7767
|
+
},
|
|
7768
|
+
{
|
|
7769
|
+
id: "expected_result",
|
|
7770
|
+
prompt: "What is the expected result after the fix?",
|
|
7771
|
+
placeholder: "e.g. Button works correctly on all screen sizes",
|
|
7772
|
+
frontMatterField: "expected_result",
|
|
7773
|
+
required: true
|
|
7774
|
+
}
|
|
7775
|
+
],
|
|
7776
|
+
qualityGate: ["Problem is clear.", "Expected result is defined."]
|
|
7777
|
+
},
|
|
7778
|
+
K2: {
|
|
7779
|
+
level: "K2",
|
|
7780
|
+
description: "Feature or bugfix with functional impact.",
|
|
7781
|
+
questions: [
|
|
7782
|
+
{
|
|
7783
|
+
id: "problem",
|
|
7784
|
+
prompt: "What problem does this solve?",
|
|
7785
|
+
placeholder: "e.g. Users cannot complete checkout without email verification",
|
|
7786
|
+
frontMatterField: "problem",
|
|
7787
|
+
required: true
|
|
7788
|
+
},
|
|
7789
|
+
{
|
|
7790
|
+
id: "expected_result",
|
|
7791
|
+
prompt: "What is the expected result?",
|
|
7792
|
+
placeholder: "e.g. Users can verify email inline during checkout",
|
|
7793
|
+
frontMatterField: "expected_result",
|
|
7794
|
+
required: true
|
|
7795
|
+
},
|
|
7796
|
+
{
|
|
7797
|
+
id: "impact",
|
|
7798
|
+
prompt: "What is the impact if this is not done?",
|
|
7799
|
+
placeholder: "e.g. ~30% of users drop off at checkout",
|
|
7800
|
+
frontMatterField: "impact",
|
|
7801
|
+
required: true
|
|
7802
|
+
},
|
|
7803
|
+
{
|
|
7804
|
+
id: "acceptance_criteria",
|
|
7805
|
+
prompt: "What are the acceptance criteria? (one per line, press Enter twice to finish)",
|
|
7806
|
+
placeholder: "e.g. Email is verified before payment step",
|
|
7807
|
+
frontMatterField: "acceptance_criteria",
|
|
7808
|
+
required: true
|
|
7809
|
+
}
|
|
7810
|
+
],
|
|
7811
|
+
qualityGate: [
|
|
7812
|
+
"Problem is clear.",
|
|
7813
|
+
"Expected result is defined.",
|
|
7814
|
+
"Impact of not doing it is stated.",
|
|
7815
|
+
"Acceptance criteria are verifiable."
|
|
7816
|
+
]
|
|
7817
|
+
},
|
|
7818
|
+
K3: {
|
|
7819
|
+
level: "K3",
|
|
7820
|
+
description: "Capability, integration, or significant functional change.",
|
|
7821
|
+
questions: [
|
|
7822
|
+
{
|
|
7823
|
+
id: "problem",
|
|
7824
|
+
prompt: "What problem does this solve?",
|
|
7825
|
+
placeholder: "e.g. Payments need to support multiple providers",
|
|
7826
|
+
frontMatterField: "problem",
|
|
7827
|
+
required: true
|
|
7828
|
+
},
|
|
7829
|
+
{
|
|
7830
|
+
id: "impact",
|
|
7831
|
+
prompt: "What is the impact if this is not done?",
|
|
7832
|
+
placeholder: "e.g. We are locked into a single provider with no fallback",
|
|
7833
|
+
frontMatterField: "impact",
|
|
7834
|
+
required: true
|
|
7835
|
+
},
|
|
7836
|
+
{
|
|
7837
|
+
id: "acceptance_criteria",
|
|
7838
|
+
prompt: "What are the acceptance criteria?",
|
|
7839
|
+
placeholder: "e.g. System routes to provider B when provider A fails",
|
|
7840
|
+
frontMatterField: "acceptance_criteria",
|
|
7841
|
+
required: true
|
|
7842
|
+
},
|
|
7843
|
+
{
|
|
7844
|
+
id: "design",
|
|
7845
|
+
prompt: "What is the proposed design or approach?",
|
|
7846
|
+
placeholder: "e.g. Abstract provider interface + strategy pattern",
|
|
7847
|
+
frontMatterField: "design",
|
|
7848
|
+
required: true
|
|
7849
|
+
}
|
|
7850
|
+
],
|
|
7851
|
+
qualityGate: [
|
|
7852
|
+
"Problem is clear.",
|
|
7853
|
+
"Impact is stated.",
|
|
7854
|
+
"Acceptance criteria are verifiable.",
|
|
7855
|
+
"Design is sufficient to start."
|
|
7856
|
+
]
|
|
7857
|
+
},
|
|
7858
|
+
K4: {
|
|
7859
|
+
level: "K4",
|
|
7860
|
+
description: "Architecture change, migration, or high-risk decision.",
|
|
7861
|
+
questions: [
|
|
7862
|
+
{
|
|
7863
|
+
id: "problem",
|
|
7864
|
+
prompt: "What problem does this solve?",
|
|
7865
|
+
placeholder: "e.g. Current auth system does not support SSO",
|
|
7866
|
+
frontMatterField: "problem",
|
|
7867
|
+
required: true
|
|
7868
|
+
},
|
|
7869
|
+
{
|
|
7870
|
+
id: "impact",
|
|
7871
|
+
prompt: "What is the impact if this is not done?",
|
|
7872
|
+
placeholder: "e.g. Enterprise clients cannot onboard",
|
|
7873
|
+
frontMatterField: "impact",
|
|
7874
|
+
required: true
|
|
7875
|
+
},
|
|
7876
|
+
{
|
|
7877
|
+
id: "design",
|
|
7878
|
+
prompt: "What is the proposed design or approach?",
|
|
7879
|
+
placeholder: "e.g. Replace JWT-only auth with OIDC + JWT hybrid",
|
|
7880
|
+
frontMatterField: "design",
|
|
7881
|
+
required: true
|
|
7882
|
+
},
|
|
7883
|
+
{
|
|
7884
|
+
id: "risks",
|
|
7885
|
+
prompt: "What are the main risks?",
|
|
7886
|
+
placeholder: "e.g. Existing sessions may be invalidated during migration",
|
|
7887
|
+
frontMatterField: "risks",
|
|
7888
|
+
required: true
|
|
7889
|
+
}
|
|
7890
|
+
],
|
|
7891
|
+
qualityGate: [
|
|
7892
|
+
"Problem is clear.",
|
|
7893
|
+
"Impact is stated.",
|
|
7894
|
+
"Design is documented.",
|
|
7895
|
+
"Risks are identified.",
|
|
7896
|
+
"ADR is created or linked if applicable."
|
|
7897
|
+
]
|
|
7898
|
+
}
|
|
7899
|
+
};
|
|
7900
|
+
var TYPE_TO_LEVEL = {
|
|
7901
|
+
hotfix: "K1",
|
|
7902
|
+
bugfix: "K2",
|
|
7903
|
+
feature: "K2",
|
|
7904
|
+
spike: "K3",
|
|
7905
|
+
// Chores are maintenance/config/tooling work — low ceremony (problem + expected result).
|
|
7906
|
+
chore: "K1"
|
|
7907
|
+
};
|
|
7908
|
+
function getLevel(level) {
|
|
7909
|
+
return LEVELS[level];
|
|
7910
|
+
}
|
|
7911
|
+
function getLevelForType(type) {
|
|
7912
|
+
return TYPE_TO_LEVEL[type];
|
|
7913
|
+
}
|
|
7914
|
+
function isValidType(type) {
|
|
7915
|
+
return WORK_ITEM_TYPES2.includes(type);
|
|
7916
|
+
}
|
|
7917
|
+
function normalizeType(raw) {
|
|
7918
|
+
if (!raw) return null;
|
|
7919
|
+
const t = raw.trim().toLowerCase();
|
|
7920
|
+
if (isValidType(t)) return t;
|
|
7921
|
+
return TYPE_ALIASES[t] ?? null;
|
|
7922
|
+
}
|
|
7923
|
+
|
|
7924
|
+
// src/core/work-item-write.ts
|
|
7727
7925
|
var WORK_ITEMS_DIR = "knowledge/delivery/work-items";
|
|
7728
7926
|
var WorkItemWriteError = class extends Error {
|
|
7729
7927
|
constructor(code, message) {
|
|
@@ -8032,8 +8230,8 @@ function captureBody(title, type, answers) {
|
|
|
8032
8230
|
function createWorkItem(dir, opts) {
|
|
8033
8231
|
const intent = opts.intent.trim();
|
|
8034
8232
|
if (!intent) throw new WorkItemWriteError("INVALID_INPUT", "An intent or summary is required.");
|
|
8035
|
-
const type = opts.type.trim()
|
|
8036
|
-
if (!
|
|
8233
|
+
const type = normalizeType(opts.type.trim()) ?? "";
|
|
8234
|
+
if (!type) throw new WorkItemWriteError("INVALID_INPUT", `Unknown Work Item type "${opts.type}".`);
|
|
8037
8235
|
const id = nextWorkItemId(dir);
|
|
8038
8236
|
const title = intent.split(/\r?\n/)[0].trim().slice(0, 120);
|
|
8039
8237
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -8073,7 +8271,7 @@ function createWorkItem(dir, opts) {
|
|
|
8073
8271
|
}
|
|
8074
8272
|
function validateInput(input) {
|
|
8075
8273
|
if (!input.title.trim()) throw new WorkItemWriteError("INVALID_INPUT", "Title is required.");
|
|
8076
|
-
if (!
|
|
8274
|
+
if (!isValidType(input.type)) throw new WorkItemWriteError("INVALID_INPUT", `Unknown Work Item type "${input.type}".`);
|
|
8077
8275
|
}
|
|
8078
8276
|
function updateWorkItem(dir, id, input, expectedRevision) {
|
|
8079
8277
|
validateInput(input);
|
|
@@ -8152,173 +8350,6 @@ function transitionWorkItem(dir, id, to, expectedRevision) {
|
|
|
8152
8350
|
return { revision: revisionOf(nextRaw), status: to, path: targetRel };
|
|
8153
8351
|
}
|
|
8154
8352
|
|
|
8155
|
-
// src/core/knowledge-levels.ts
|
|
8156
|
-
var WORK_ITEM_TYPES2 = ["feature", "bugfix", "hotfix", "spike", "chore"];
|
|
8157
|
-
var LEVELS = {
|
|
8158
|
-
K0: {
|
|
8159
|
-
level: "K0",
|
|
8160
|
-
description: "Trivial change. No formal knowledge required.",
|
|
8161
|
-
questions: [],
|
|
8162
|
-
qualityGate: []
|
|
8163
|
-
},
|
|
8164
|
-
K1: {
|
|
8165
|
-
level: "K1",
|
|
8166
|
-
description: "Simple fix or hotfix.",
|
|
8167
|
-
questions: [
|
|
8168
|
-
{
|
|
8169
|
-
id: "problem",
|
|
8170
|
-
prompt: "What problem does this fix?",
|
|
8171
|
-
placeholder: "e.g. Button is not clickable on mobile",
|
|
8172
|
-
frontMatterField: "problem",
|
|
8173
|
-
required: true
|
|
8174
|
-
},
|
|
8175
|
-
{
|
|
8176
|
-
id: "expected_result",
|
|
8177
|
-
prompt: "What is the expected result after the fix?",
|
|
8178
|
-
placeholder: "e.g. Button works correctly on all screen sizes",
|
|
8179
|
-
frontMatterField: "expected_result",
|
|
8180
|
-
required: true
|
|
8181
|
-
}
|
|
8182
|
-
],
|
|
8183
|
-
qualityGate: ["Problem is clear.", "Expected result is defined."]
|
|
8184
|
-
},
|
|
8185
|
-
K2: {
|
|
8186
|
-
level: "K2",
|
|
8187
|
-
description: "Feature or bugfix with functional impact.",
|
|
8188
|
-
questions: [
|
|
8189
|
-
{
|
|
8190
|
-
id: "problem",
|
|
8191
|
-
prompt: "What problem does this solve?",
|
|
8192
|
-
placeholder: "e.g. Users cannot complete checkout without email verification",
|
|
8193
|
-
frontMatterField: "problem",
|
|
8194
|
-
required: true
|
|
8195
|
-
},
|
|
8196
|
-
{
|
|
8197
|
-
id: "expected_result",
|
|
8198
|
-
prompt: "What is the expected result?",
|
|
8199
|
-
placeholder: "e.g. Users can verify email inline during checkout",
|
|
8200
|
-
frontMatterField: "expected_result",
|
|
8201
|
-
required: true
|
|
8202
|
-
},
|
|
8203
|
-
{
|
|
8204
|
-
id: "impact",
|
|
8205
|
-
prompt: "What is the impact if this is not done?",
|
|
8206
|
-
placeholder: "e.g. ~30% of users drop off at checkout",
|
|
8207
|
-
frontMatterField: "impact",
|
|
8208
|
-
required: true
|
|
8209
|
-
},
|
|
8210
|
-
{
|
|
8211
|
-
id: "acceptance_criteria",
|
|
8212
|
-
prompt: "What are the acceptance criteria? (one per line, press Enter twice to finish)",
|
|
8213
|
-
placeholder: "e.g. Email is verified before payment step",
|
|
8214
|
-
frontMatterField: "acceptance_criteria",
|
|
8215
|
-
required: true
|
|
8216
|
-
}
|
|
8217
|
-
],
|
|
8218
|
-
qualityGate: [
|
|
8219
|
-
"Problem is clear.",
|
|
8220
|
-
"Expected result is defined.",
|
|
8221
|
-
"Impact of not doing it is stated.",
|
|
8222
|
-
"Acceptance criteria are verifiable."
|
|
8223
|
-
]
|
|
8224
|
-
},
|
|
8225
|
-
K3: {
|
|
8226
|
-
level: "K3",
|
|
8227
|
-
description: "Capability, integration, or significant functional change.",
|
|
8228
|
-
questions: [
|
|
8229
|
-
{
|
|
8230
|
-
id: "problem",
|
|
8231
|
-
prompt: "What problem does this solve?",
|
|
8232
|
-
placeholder: "e.g. Payments need to support multiple providers",
|
|
8233
|
-
frontMatterField: "problem",
|
|
8234
|
-
required: true
|
|
8235
|
-
},
|
|
8236
|
-
{
|
|
8237
|
-
id: "impact",
|
|
8238
|
-
prompt: "What is the impact if this is not done?",
|
|
8239
|
-
placeholder: "e.g. We are locked into a single provider with no fallback",
|
|
8240
|
-
frontMatterField: "impact",
|
|
8241
|
-
required: true
|
|
8242
|
-
},
|
|
8243
|
-
{
|
|
8244
|
-
id: "acceptance_criteria",
|
|
8245
|
-
prompt: "What are the acceptance criteria?",
|
|
8246
|
-
placeholder: "e.g. System routes to provider B when provider A fails",
|
|
8247
|
-
frontMatterField: "acceptance_criteria",
|
|
8248
|
-
required: true
|
|
8249
|
-
},
|
|
8250
|
-
{
|
|
8251
|
-
id: "design",
|
|
8252
|
-
prompt: "What is the proposed design or approach?",
|
|
8253
|
-
placeholder: "e.g. Abstract provider interface + strategy pattern",
|
|
8254
|
-
frontMatterField: "design",
|
|
8255
|
-
required: true
|
|
8256
|
-
}
|
|
8257
|
-
],
|
|
8258
|
-
qualityGate: [
|
|
8259
|
-
"Problem is clear.",
|
|
8260
|
-
"Impact is stated.",
|
|
8261
|
-
"Acceptance criteria are verifiable.",
|
|
8262
|
-
"Design is sufficient to start."
|
|
8263
|
-
]
|
|
8264
|
-
},
|
|
8265
|
-
K4: {
|
|
8266
|
-
level: "K4",
|
|
8267
|
-
description: "Architecture change, migration, or high-risk decision.",
|
|
8268
|
-
questions: [
|
|
8269
|
-
{
|
|
8270
|
-
id: "problem",
|
|
8271
|
-
prompt: "What problem does this solve?",
|
|
8272
|
-
placeholder: "e.g. Current auth system does not support SSO",
|
|
8273
|
-
frontMatterField: "problem",
|
|
8274
|
-
required: true
|
|
8275
|
-
},
|
|
8276
|
-
{
|
|
8277
|
-
id: "impact",
|
|
8278
|
-
prompt: "What is the impact if this is not done?",
|
|
8279
|
-
placeholder: "e.g. Enterprise clients cannot onboard",
|
|
8280
|
-
frontMatterField: "impact",
|
|
8281
|
-
required: true
|
|
8282
|
-
},
|
|
8283
|
-
{
|
|
8284
|
-
id: "design",
|
|
8285
|
-
prompt: "What is the proposed design or approach?",
|
|
8286
|
-
placeholder: "e.g. Replace JWT-only auth with OIDC + JWT hybrid",
|
|
8287
|
-
frontMatterField: "design",
|
|
8288
|
-
required: true
|
|
8289
|
-
},
|
|
8290
|
-
{
|
|
8291
|
-
id: "risks",
|
|
8292
|
-
prompt: "What are the main risks?",
|
|
8293
|
-
placeholder: "e.g. Existing sessions may be invalidated during migration",
|
|
8294
|
-
frontMatterField: "risks",
|
|
8295
|
-
required: true
|
|
8296
|
-
}
|
|
8297
|
-
],
|
|
8298
|
-
qualityGate: [
|
|
8299
|
-
"Problem is clear.",
|
|
8300
|
-
"Impact is stated.",
|
|
8301
|
-
"Design is documented.",
|
|
8302
|
-
"Risks are identified.",
|
|
8303
|
-
"ADR is created or linked if applicable."
|
|
8304
|
-
]
|
|
8305
|
-
}
|
|
8306
|
-
};
|
|
8307
|
-
var TYPE_TO_LEVEL = {
|
|
8308
|
-
hotfix: "K1",
|
|
8309
|
-
bugfix: "K2",
|
|
8310
|
-
feature: "K2",
|
|
8311
|
-
spike: "K3",
|
|
8312
|
-
// Chores are maintenance/config/tooling work — low ceremony (problem + expected result).
|
|
8313
|
-
chore: "K1"
|
|
8314
|
-
};
|
|
8315
|
-
function getLevel(level) {
|
|
8316
|
-
return LEVELS[level];
|
|
8317
|
-
}
|
|
8318
|
-
function getLevelForType(type) {
|
|
8319
|
-
return TYPE_TO_LEVEL[type];
|
|
8320
|
-
}
|
|
8321
|
-
|
|
8322
8353
|
// src/core/work-item-refinement.ts
|
|
8323
8354
|
function toCapture(q) {
|
|
8324
8355
|
return { id: q.id, prompt: q.prompt, placeholder: q.placeholder, field: q.frontMatterField, required: q.required };
|
|
@@ -8333,140 +8364,70 @@ function getWorkItemCaptureDefinition() {
|
|
|
8333
8364
|
questions
|
|
8334
8365
|
};
|
|
8335
8366
|
}
|
|
8336
|
-
|
|
8337
|
-
|
|
8338
|
-
|
|
8339
|
-
|
|
8340
|
-
}
|
|
8341
|
-
function assembleRefinementContext(dir, workItemId) {
|
|
8342
|
-
const edit = getWorkItemForEdit(dir, workItemId);
|
|
8367
|
+
var RECOMMENDED_AGENT = "work-item-agent";
|
|
8368
|
+
var RECOMMENDED_SKILL = "work-item-refinement";
|
|
8369
|
+
function buildRefinementHandoff(dir, workItemId) {
|
|
8370
|
+
const wi = getWorkItem(dir, workItemId);
|
|
8343
8371
|
const config = loadConfig(dir);
|
|
8344
|
-
const
|
|
8345
|
-
|
|
8372
|
+
const projectName = config?.project.name ?? "this project";
|
|
8373
|
+
const mappedModules = loadMappedModules(dir).map((m) => m.id);
|
|
8374
|
+
const multirepo = mappedModules.length > 0;
|
|
8375
|
+
const lines = [
|
|
8376
|
+
`Refine Work Item ${wi.id} \u2014 "${wi.title}" \u2014 in project "${projectName}" using Kaddo.`,
|
|
8377
|
+
"",
|
|
8378
|
+
"Use a Kaddo-enabled agent with access to this repository. Drive the refinement with the",
|
|
8379
|
+
`canonical ${RECOMMENDED_AGENT} and the ${RECOMMENDED_SKILL} skill (via Kaddo MCP or skills).`,
|
|
8380
|
+
"",
|
|
8381
|
+
"Inspect the actual implementation before defining scope \u2014 do not guess affected modules from",
|
|
8382
|
+
"the Work Item title. Read the current behavior in the code first, then classify."
|
|
8383
|
+
];
|
|
8384
|
+
if (multirepo) {
|
|
8385
|
+
lines.push(
|
|
8386
|
+
"",
|
|
8387
|
+
`This is a multirepo project. Evaluate the scope across all relevant mapped modules (${mappedModules.join(", ")})`,
|
|
8388
|
+
"before finalizing affected_modules and module_coverage."
|
|
8389
|
+
);
|
|
8390
|
+
}
|
|
8391
|
+
lines.push(
|
|
8392
|
+
"",
|
|
8393
|
+
`Update the canonical Work Item ${wi.id} with:`,
|
|
8394
|
+
"- current and target behavior;",
|
|
8395
|
+
"- the end-to-end flow (journey);",
|
|
8396
|
+
"- affected modules;",
|
|
8397
|
+
"- module coverage;",
|
|
8398
|
+
"- impact analysis across the relevant surfaces;",
|
|
8399
|
+
"- scope confidence and open unknowns;",
|
|
8400
|
+
"- acceptance criteria;",
|
|
8401
|
+
"- relevant Knowledge / ADR relationships.",
|
|
8402
|
+
"",
|
|
8403
|
+
"Do not implement the Work Item. Do not run mutating Git operations."
|
|
8346
8404
|
);
|
|
8347
|
-
const decisions = knowledgeArtifacts.filter((a) => a.type === "adr" || /^adr-/i.test(a.id)).map((a) => ({ id: a.id, title: a.title || a.id }));
|
|
8348
|
-
const knowledge = knowledgeArtifacts.filter((a) => !(a.type === "adr" || /^adr-/i.test(a.id))).map((a) => ({ id: a.id || a.relPath, title: a.title || a.id, layer: a.layer, type: a.type || void 0, summary: a.summary || void 0 }));
|
|
8349
|
-
const modules = ["core", ...loadMappedModules(dir).map((m) => m.id)].filter((v, i, arr) => arr.indexOf(v) === i);
|
|
8350
8405
|
return {
|
|
8351
|
-
|
|
8352
|
-
|
|
8353
|
-
|
|
8354
|
-
|
|
8355
|
-
|
|
8356
|
-
|
|
8406
|
+
workItemId: wi.id,
|
|
8407
|
+
title: wi.title,
|
|
8408
|
+
projectName,
|
|
8409
|
+
refinement: wi.refinement,
|
|
8410
|
+
recommendedAgent: RECOMMENDED_AGENT,
|
|
8411
|
+
recommendedSkill: RECOMMENDED_SKILL,
|
|
8412
|
+
text: lines.join("\n")
|
|
8357
8413
|
};
|
|
8358
8414
|
}
|
|
8359
|
-
function stripEdit(edit) {
|
|
8360
|
-
const { id: _i, status: _s, revision: _r, path: _p, editable: _e, editableReason: _er, ...input } = edit;
|
|
8361
|
-
return input;
|
|
8362
|
-
}
|
|
8363
|
-
var VALID_COVERAGE2 = /* @__PURE__ */ new Set(["affected", "reviewed-not-affected", "unknown", "not-applicable"]);
|
|
8364
|
-
var VALID_CONFIDENCE2 = /* @__PURE__ */ new Set(["high", "medium", "low"]);
|
|
8365
|
-
function str(v) {
|
|
8366
|
-
return typeof v === "string" && v.trim() ? v.trim() : void 0;
|
|
8367
|
-
}
|
|
8368
|
-
function strList(v) {
|
|
8369
|
-
return Array.isArray(v) ? v.map((x) => typeof x === "string" ? x.trim() : "").filter(Boolean) : [];
|
|
8370
|
-
}
|
|
8371
|
-
function normalizeAndValidateProposal(dir, workItemId, proposal) {
|
|
8372
|
-
const ctx = assembleRefinementContext(dir, workItemId);
|
|
8373
|
-
const knownModules = new Set(ctx.modules);
|
|
8374
|
-
const knownDecisions = new Set(ctx.decisions.map((d) => d.id));
|
|
8375
|
-
const knownKnowledge = new Set(ctx.knowledge.map((k) => k.id));
|
|
8376
|
-
const extraFindings = [];
|
|
8377
|
-
const input = { ...ctx.workItem.current };
|
|
8378
|
-
if (str(proposal.title)) input.title = str(proposal.title);
|
|
8379
|
-
const o = proposal.outcome ?? {};
|
|
8380
|
-
if (str(o.actor) !== void 0) input.actor = str(o.actor);
|
|
8381
|
-
if (str(o.observableOutcome) !== void 0) input.outcome = str(o.observableOutcome);
|
|
8382
|
-
if (str(o.currentBehavior) !== void 0) input.currentBehavior = str(o.currentBehavior);
|
|
8383
|
-
if (str(o.targetBehavior) !== void 0) input.targetBehavior = str(o.targetBehavior);
|
|
8384
|
-
const j = proposal.journey ?? {};
|
|
8385
|
-
if (j.entryPoints) input.entryPoints = strList(j.entryPoints).join("\n");
|
|
8386
|
-
if (j.flow) input.endToEndFlow = strList(j.flow).map((s) => `- ${s}`).join("\n");
|
|
8387
|
-
if (proposal.moduleCoverage) {
|
|
8388
|
-
input.moduleCoverage = proposal.moduleCoverage.filter((c) => {
|
|
8389
|
-
if (!knownModules.has(c.id)) {
|
|
8390
|
-
extraFindings.push({ level: "warning", message: `Proposed module "${c.id}" is not registered and was not included.` });
|
|
8391
|
-
return false;
|
|
8392
|
-
}
|
|
8393
|
-
return VALID_COVERAGE2.has(c.status);
|
|
8394
|
-
}).map((c) => ({ id: c.id, status: c.status, ...str(c.reason) ? { reason: str(c.reason) } : {} }));
|
|
8395
|
-
}
|
|
8396
|
-
const affected = /* @__PURE__ */ new Set();
|
|
8397
|
-
for (const m of proposal.affectedModules ?? []) if (knownModules.has(m)) affected.add(m);
|
|
8398
|
-
for (const c of input.moduleCoverage) if (c.status === "affected") affected.add(c.id);
|
|
8399
|
-
if (proposal.affectedModules || proposal.moduleCoverage) input.affectedModules = [...affected];
|
|
8400
|
-
if (proposal.impactAnalysis) {
|
|
8401
|
-
input.impactAnalysis = proposal.impactAnalysis.filter((s) => VALID_COVERAGE2.has(s.status) && str(s.surface)).map((s) => ({ surface: str(s.surface), status: s.status, ...str(s.reason) ? { reason: str(s.reason) } : {}, ...str(s.question) ? { question: str(s.question) } : {} }));
|
|
8402
|
-
}
|
|
8403
|
-
if (proposal.scopeConfidence && VALID_CONFIDENCE2.has(proposal.scopeConfidence.level)) {
|
|
8404
|
-
input.scopeConfidence = { level: proposal.scopeConfidence.level, reasons: strList(proposal.scopeConfidence.reasons) };
|
|
8405
|
-
}
|
|
8406
|
-
if (proposal.scopeUnknowns) input.scopeUnknowns = strList(proposal.scopeUnknowns);
|
|
8407
|
-
if (proposal.acceptanceCriteria) input.acceptanceCriteria = strList(proposal.acceptanceCriteria).map((t) => ({ text: t, checked: null }));
|
|
8408
|
-
if (proposal.linkedDecisions) {
|
|
8409
|
-
input.decisions = proposal.linkedDecisions.filter((id) => {
|
|
8410
|
-
if (!knownDecisions.has(id)) {
|
|
8411
|
-
extraFindings.push({ level: "warning", message: `Proposed decision "${id}" does not exist and was not linked.` });
|
|
8412
|
-
return false;
|
|
8413
|
-
}
|
|
8414
|
-
return true;
|
|
8415
|
-
});
|
|
8416
|
-
}
|
|
8417
|
-
if (proposal.relatedKnowledge) {
|
|
8418
|
-
input.relatedKnowledge = proposal.relatedKnowledge.filter((id) => {
|
|
8419
|
-
if (!knownKnowledge.has(id)) {
|
|
8420
|
-
extraFindings.push({ level: "warning", message: `Proposed knowledge "${id}" could not be resolved and was not linked.` });
|
|
8421
|
-
return false;
|
|
8422
|
-
}
|
|
8423
|
-
return true;
|
|
8424
|
-
});
|
|
8425
|
-
}
|
|
8426
|
-
const findings = [...extraFindings, ...evaluate(input, knownModules)];
|
|
8427
|
-
const blocking = findings.filter((f) => f.level === "blocking").length;
|
|
8428
|
-
const warning = findings.filter((f) => f.level === "warning").length;
|
|
8429
|
-
const fyi = findings.filter((f) => f.level === "fyi").length;
|
|
8430
|
-
return { input, validation: { findings, blocking, warning, fyi, canApply: true } };
|
|
8431
|
-
}
|
|
8432
|
-
function evaluate(input, knownModules) {
|
|
8433
|
-
const findings = [];
|
|
8434
|
-
for (const c of input.moduleCoverage) {
|
|
8435
|
-
if (c.status === "affected" && !input.affectedModules.includes(c.id)) {
|
|
8436
|
-
findings.push({ level: "blocking", message: `${c.id} is marked affected in module coverage but is missing from affected_modules.` });
|
|
8437
|
-
}
|
|
8438
|
-
}
|
|
8439
|
-
for (const m of input.affectedModules) {
|
|
8440
|
-
if (!knownModules.has(m)) findings.push({ level: "blocking", message: `Module "${m}" is not registered in this project.` });
|
|
8441
|
-
}
|
|
8442
|
-
if (!input.targetBehavior?.trim()) findings.push({ level: "warning", message: "Target behavior is not defined." });
|
|
8443
|
-
if (input.acceptanceCriteria.length === 0) findings.push({ level: "warning", message: "No acceptance criteria have been defined." });
|
|
8444
|
-
if (input.scopeConfidence?.level === "low") findings.push({ level: "warning", message: "Scope confidence is Low." });
|
|
8445
|
-
if (!input.scopeConfidence) findings.push({ level: "warning", message: "Scope confidence has not been assessed." });
|
|
8446
|
-
for (const s of input.impactAnalysis) if (s.status === "unknown") findings.push({ level: "fyi", message: `Impact on ${s.surface} is unknown.` });
|
|
8447
|
-
return findings;
|
|
8448
|
-
}
|
|
8449
|
-
function applyRefinement(dir, workItemId, proposal, expectedRevision) {
|
|
8450
|
-
const { input } = normalizeAndValidateProposal(dir, workItemId, proposal);
|
|
8451
|
-
return updateWorkItem(dir, workItemId, input, expectedRevision);
|
|
8452
|
-
}
|
|
8453
8415
|
export {
|
|
8454
8416
|
WorkItemNotFoundError,
|
|
8455
8417
|
WorkItemWriteError,
|
|
8456
8418
|
analyzeCrossRepoEvidence,
|
|
8457
8419
|
analyzeScopeCoverage,
|
|
8458
|
-
applyRefinement,
|
|
8459
|
-
assembleRefinementContext,
|
|
8460
8420
|
buildProjectExplanation,
|
|
8461
8421
|
buildProjectRoute,
|
|
8462
8422
|
buildReadinessReport,
|
|
8423
|
+
buildRefinementHandoff,
|
|
8424
|
+
computeRefinementStatus,
|
|
8463
8425
|
createWorkItem,
|
|
8464
8426
|
cwd,
|
|
8465
8427
|
discoverKnowledge,
|
|
8466
8428
|
discoverWorkItems,
|
|
8467
8429
|
exists,
|
|
8468
8430
|
getWorkItem,
|
|
8469
|
-
getWorkItemAgentAssets,
|
|
8470
8431
|
getWorkItemCaptureDefinition,
|
|
8471
8432
|
getWorkItemForEdit,
|
|
8472
8433
|
getWorkItems,
|
|
@@ -8479,7 +8440,6 @@ export {
|
|
|
8479
8440
|
lifecycleStateOf,
|
|
8480
8441
|
loadConfig,
|
|
8481
8442
|
loadMappedModules,
|
|
8482
|
-
normalizeAndValidateProposal,
|
|
8483
8443
|
readFile,
|
|
8484
8444
|
transitionWorkItem,
|
|
8485
8445
|
updateWorkItem,
|