@harness-engineering/cli 4.0.0 → 4.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/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +9 -8
- package/dist/agents/skills/claude-code/pre-merge-brief/SKILL.md +86 -0
- package/dist/agents/skills/claude-code/pre-merge-brief/skill.yaml +67 -0
- package/dist/agents/skills/claude-code/product-advisor/SKILL.md +202 -0
- package/dist/agents/skills/claude-code/product-advisor/skill.yaml +74 -0
- package/dist/agents/skills/codex/harness-autopilot/SKILL.md +9 -8
- package/dist/agents/skills/codex/pre-merge-brief/SKILL.md +86 -0
- package/dist/agents/skills/codex/pre-merge-brief/skill.yaml +67 -0
- package/dist/agents/skills/codex/product-advisor/SKILL.md +202 -0
- package/dist/agents/skills/codex/product-advisor/skill.yaml +74 -0
- package/dist/agents/skills/cursor/harness-autopilot/SKILL.md +9 -8
- package/dist/agents/skills/cursor/pre-merge-brief/SKILL.md +86 -0
- package/dist/agents/skills/cursor/pre-merge-brief/skill.yaml +67 -0
- package/dist/agents/skills/cursor/product-advisor/SKILL.md +202 -0
- package/dist/agents/skills/cursor/product-advisor/skill.yaml +74 -0
- package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +9 -8
- package/dist/agents/skills/gemini-cli/pre-merge-brief/SKILL.md +86 -0
- package/dist/agents/skills/gemini-cli/pre-merge-brief/skill.yaml +67 -0
- package/dist/agents/skills/gemini-cli/product-advisor/SKILL.md +202 -0
- package/dist/agents/skills/gemini-cli/product-advisor/skill.yaml +74 -0
- package/dist/{agents-md-7OSNWU52.js → agents-md-7L4PKKOM.js} +4 -4
- package/dist/analyzer-XRCV63KC-HLTEIKAJ.js +26 -0
- package/dist/{architecture-2XYGJGT3.js → architecture-RCHFDI7E.js} +5 -5
- package/dist/{assess-project-3KPP2D6M.js → assess-project-YUDPNRS6.js} +5 -3
- package/dist/bin/harness-mcp.js +16 -16
- package/dist/bin/harness.js +27 -27
- package/dist/{check-phase-gate-46U5AAXE.js → check-phase-gate-56GS3A72.js} +5 -5
- package/dist/{chunk-MSBJ445U.js → chunk-4SKWGVYD.js} +5 -5
- package/dist/{chunk-CLI4K2CH.js → chunk-4U5LDFCY.js} +1 -1
- package/dist/{chunk-6YXCZV33.js → chunk-ABRYIEWJ.js} +1090 -714
- package/dist/{chunk-AK67S3O4.js → chunk-AU4YPEIE.js} +3 -3
- package/dist/{chunk-BV45354Q.js → chunk-DGVT4DBI.js} +9 -9
- package/dist/{chunk-363V6GPR.js → chunk-GLHLXTKC.js} +9 -9
- package/dist/{chunk-VTUINXWR.js → chunk-GSYBGOY3.js} +1 -1
- package/dist/{chunk-FZ4Q73HA.js → chunk-IGWJRAJT.js} +1 -1
- package/dist/{chunk-S2RQPPL6.js → chunk-N4AI2WFH.js} +1 -1
- package/dist/{chunk-HXMAIVV2.js → chunk-NCMJXBEO.js} +1 -1
- package/dist/{chunk-ZEYAOYJL.js → chunk-OZSKLJQW.js} +1 -1
- package/dist/{chunk-VTU3QOJT.js → chunk-P4NA5OQX.js} +1 -1
- package/dist/{chunk-WL3O2PKJ.js → chunk-RY2U77OY.js} +8 -8
- package/dist/{chunk-TTWNGOBT.js → chunk-RZQZXWEL.js} +32 -7
- package/dist/{chunk-KLPX55TI.js → chunk-UACYZCW4.js} +239 -146
- package/dist/{chunk-IYWT3JJW.js → chunk-VG4G3R2V.js} +1 -1
- package/dist/{chunk-PP6ZRL5T.js → chunk-WZJR6SOI.js} +536 -422
- package/dist/{chunk-PHX45JYN.js → chunk-XW5XVVMI.js} +2 -2
- package/dist/{chunk-MYVTYFQD.js → chunk-XZNCONFG.js} +1 -1
- package/dist/{chunk-GXCPDAS5.js → chunk-Y33P35U3.js} +26 -8
- package/dist/{chunk-XFHZ7GCI.js → chunk-Y5HPJMTM.js} +19 -3
- package/dist/{chunk-N55WOGN3.js → chunk-YJYUJSWK.js} +59 -21
- package/dist/{chunk-SPE7P4GL.js → chunk-YWRPQZL7.js} +1 -1
- package/dist/{chunk-6NCREWWM.js → chunk-YXOPQEFZ.js} +3 -3
- package/dist/{chunk-2N4OENGE.js → chunk-YYFSFSB3.js} +1 -1
- package/dist/{chunk-ERILXQBP.js → chunk-Z4XWWNYX.js} +615 -433
- package/dist/{chunk-HMW3C5DP.js → chunk-ZU6T7W3U.js} +2 -2
- package/dist/{ci-workflow-XJN4UO3Q.js → ci-workflow-TFAA5BK7.js} +4 -4
- package/dist/{dist-OWHMNL4W.js → dist-DWBTZXR5.js} +1 -1
- package/dist/{dist-IPVFYGY2.js → dist-MCTEX5QH.js} +5 -3
- package/dist/{docs-RSFZTNPG.js → docs-BBMAN3CY.js} +5 -5
- package/dist/{engine-DJIHY4JT.js → engine-R2YH74AL.js} +4 -4
- package/dist/{entropy-EAEKJKRM.js → entropy-5UP5N6AF.js} +7 -4
- package/dist/{feedback-JT5X3DBC.js → feedback-6MDCCFZL.js} +1 -1
- package/dist/{generate-agent-definitions-CC6KED3E.js → generate-agent-definitions-KKAN5DB5.js} +5 -5
- package/dist/{glob-helper-GLZAURJC.js → glob-helper-VR6UCZZB.js} +1 -1
- package/dist/{graph-loader-HHXN5FLP.js → graph-loader-STFGYKZH.js} +1 -1
- package/dist/hooks/sentinel-pre.js +15 -138
- package/dist/index.d.ts +61 -0
- package/dist/index.js +27 -27
- package/dist/{loader-UWNVTYBY.js → loader-2WT2ZE2T.js} +4 -4
- package/dist/{mcp-TCLNK7HG.js → mcp-5V4LPMB3.js} +16 -16
- package/dist/{performance-R6O3N3UB.js → performance-2N3CFXLR.js} +5 -5
- package/dist/{review-pipeline-MOOWXWSQ.js → review-pipeline-XZIGBU3Q.js} +4 -4
- package/dist/{runtime-RIWQUKBQ.js → runtime-POME3GTR.js} +4 -4
- package/dist/{scan-P7YFKB77.js → scan-IYSVRPD2.js} +1 -1
- package/dist/{security-U76C54W6.js → security-QLJLMSIW.js} +1 -1
- package/dist/{state-events-F44CUUZG.js → state-events-YY5KBZTC.js} +4 -4
- package/dist/{validate-IUAV7MOU.js → validate-VZORVK43.js} +5 -5
- package/dist/{validate-cross-check-M2ZM6RFY.js → validate-cross-check-OYKEDCST.js} +4 -4
- package/package.json +5 -4
- package/dist/analyzer-V633GUHY-MBCQWKDU.js +0 -26
|
@@ -22,8 +22,8 @@ import {
|
|
|
22
22
|
getDefaultRegistry,
|
|
23
23
|
getOutline,
|
|
24
24
|
getParser,
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
init_chunk_IHRT6II2,
|
|
26
|
+
init_chunk_JZ7UO3OF,
|
|
27
27
|
parseFile,
|
|
28
28
|
parseSize,
|
|
29
29
|
readFileContent,
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
resetParserCache,
|
|
32
32
|
resolveFileToLayer,
|
|
33
33
|
validateDependencies
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-YJYUJSWK.js";
|
|
35
35
|
import {
|
|
36
36
|
AuthAuditEntrySchema,
|
|
37
37
|
AuthTokenPublicSchema,
|
|
@@ -87,7 +87,7 @@ import {
|
|
|
87
87
|
init_dist as init_dist2,
|
|
88
88
|
queryTraceability,
|
|
89
89
|
skipDirGlobs
|
|
90
|
-
} from "./chunk-
|
|
90
|
+
} from "./chunk-WZJR6SOI.js";
|
|
91
91
|
import {
|
|
92
92
|
ArchBaselineSchema,
|
|
93
93
|
ArchConfigSchema,
|
|
@@ -123,7 +123,7 @@ import {
|
|
|
123
123
|
__export
|
|
124
124
|
} from "./chunk-KFQGP6VL.js";
|
|
125
125
|
|
|
126
|
-
// ../core/dist/chunk-
|
|
126
|
+
// ../core/dist/chunk-OFA2AAZK.mjs
|
|
127
127
|
import { createHash } from "crypto";
|
|
128
128
|
import { readFileSync, writeFileSync, renameSync, mkdirSync, existsSync } from "fs";
|
|
129
129
|
import { randomBytes } from "crypto";
|
|
@@ -759,10 +759,10 @@ async function toHaveMaxDepDepth(received, maxDepth) {
|
|
|
759
759
|
};
|
|
760
760
|
}
|
|
761
761
|
var CircularDepsCollector, LayerViolationCollector, ArchBaselineManager, ComplexityCollector, CouplingCollector, ForbiddenImportCollector, ModuleSizeCollector, DepDepthCollector, defaultCollectors, archMatchers;
|
|
762
|
-
var
|
|
763
|
-
"../core/dist/chunk-
|
|
762
|
+
var init_chunk_OFA2AAZK = __esm({
|
|
763
|
+
"../core/dist/chunk-OFA2AAZK.mjs"() {
|
|
764
764
|
"use strict";
|
|
765
|
-
|
|
765
|
+
init_chunk_JZ7UO3OF();
|
|
766
766
|
init_chunk_IIEDD47I();
|
|
767
767
|
init_dist2();
|
|
768
768
|
init_dist2();
|
|
@@ -1718,6 +1718,7 @@ __export(dist_exports, {
|
|
|
1718
1718
|
parseManifest: () => parseManifest,
|
|
1719
1719
|
parseMeta: () => parseMeta,
|
|
1720
1720
|
parseProtectedRegions: () => parseProtectedRegions,
|
|
1721
|
+
parseReferencedIssues: () => parseReferencedIssues,
|
|
1721
1722
|
parseRoadmap: () => parseRoadmap,
|
|
1722
1723
|
parseSections: () => parseSections,
|
|
1723
1724
|
parseSecurityConfig: () => parseSecurityConfig,
|
|
@@ -5965,16 +5966,7 @@ function quoteYamlScalar(value) {
|
|
|
5965
5966
|
const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
5966
5967
|
return `"${escaped}"`;
|
|
5967
5968
|
}
|
|
5968
|
-
function
|
|
5969
|
-
let data;
|
|
5970
|
-
let content;
|
|
5971
|
-
try {
|
|
5972
|
-
const parsed = matter3(md);
|
|
5973
|
-
data = parsed.data;
|
|
5974
|
-
content = parsed.content;
|
|
5975
|
-
} catch (err) {
|
|
5976
|
-
return Err(new Error(`Shard frontmatter is not valid YAML: ${err.message}`));
|
|
5977
|
-
}
|
|
5969
|
+
function parseShardFrontmatter(data) {
|
|
5978
5970
|
const slug = data.slug;
|
|
5979
5971
|
if (typeof slug !== "string" || slug.length === 0) {
|
|
5980
5972
|
return Err(new Error("Shard frontmatter missing required field: slug"));
|
|
@@ -5990,6 +5982,21 @@ function parseShard(md) {
|
|
|
5990
5982
|
new Error(`Shard "${slug}" has invalid order: "${String(rawOrder)}" (must be a number)`)
|
|
5991
5983
|
);
|
|
5992
5984
|
}
|
|
5985
|
+
return Ok({ slug, milestone, order });
|
|
5986
|
+
}
|
|
5987
|
+
function parseShard(md) {
|
|
5988
|
+
let data;
|
|
5989
|
+
let content;
|
|
5990
|
+
try {
|
|
5991
|
+
const parsed = matter3(md);
|
|
5992
|
+
data = parsed.data;
|
|
5993
|
+
content = parsed.content;
|
|
5994
|
+
} catch (err) {
|
|
5995
|
+
return Err(new Error(`Shard frontmatter is not valid YAML: ${err.message}`));
|
|
5996
|
+
}
|
|
5997
|
+
const frontmatterResult = parseShardFrontmatter(data);
|
|
5998
|
+
if (!frontmatterResult.ok) return frontmatterResult;
|
|
5999
|
+
const { slug, milestone, order } = frontmatterResult.value;
|
|
5993
6000
|
const nameMatch = content.match(H3_NAME);
|
|
5994
6001
|
if (!nameMatch) {
|
|
5995
6002
|
return Err(new Error(`Shard "${slug}" is missing its "### <name>" heading`));
|
|
@@ -6011,6 +6018,17 @@ function serializeShard(shard) {
|
|
|
6011
6018
|
return [...frontmatter, ...serializeFeature(shard.feature)].join("\n") + "\n";
|
|
6012
6019
|
}
|
|
6013
6020
|
function parseMeta(md) {
|
|
6021
|
+
const block = parseFrontmatterBlock(md);
|
|
6022
|
+
if (!block.ok) return Err(block.error);
|
|
6023
|
+
const { data, body } = block.value;
|
|
6024
|
+
const frontmatter = buildFrontmatter(data);
|
|
6025
|
+
if (!frontmatter.ok) return Err(frontmatter.error);
|
|
6026
|
+
const milestones = parseMilestones2(data);
|
|
6027
|
+
if (!milestones.ok) return Err(milestones.error);
|
|
6028
|
+
const meta = { frontmatter: frontmatter.value, milestones: milestones.value };
|
|
6029
|
+
return attachAssignmentHistory(meta, body);
|
|
6030
|
+
}
|
|
6031
|
+
function parseFrontmatterBlock(md) {
|
|
6014
6032
|
const match = md.match(FRONTMATTER);
|
|
6015
6033
|
if (!match) {
|
|
6016
6034
|
return Err(new Error("_meta.md is missing or has malformed YAML frontmatter"));
|
|
@@ -6022,6 +6040,9 @@ function parseMeta(md) {
|
|
|
6022
6040
|
} catch (err) {
|
|
6023
6041
|
return Err(new Error(`_meta.md frontmatter is not valid YAML: ${err.message}`));
|
|
6024
6042
|
}
|
|
6043
|
+
return Ok({ data, body: match[2] ?? "" });
|
|
6044
|
+
}
|
|
6045
|
+
function buildFrontmatter(data) {
|
|
6025
6046
|
const project = data.project;
|
|
6026
6047
|
const rawVersion = data.version;
|
|
6027
6048
|
const lastSynced = data.last_synced;
|
|
@@ -6040,12 +6061,16 @@ function parseMeta(md) {
|
|
|
6040
6061
|
const frontmatter = { project, version, lastSynced, lastManualEdit };
|
|
6041
6062
|
if (typeof data.created === "string") frontmatter.created = data.created;
|
|
6042
6063
|
if (typeof data.updated === "string") frontmatter.updated = data.updated;
|
|
6064
|
+
return Ok(frontmatter);
|
|
6065
|
+
}
|
|
6066
|
+
function parseMilestones2(data) {
|
|
6043
6067
|
const rawMilestones = data.milestones;
|
|
6044
6068
|
if (!Array.isArray(rawMilestones) || !rawMilestones.every((m) => typeof m === "string")) {
|
|
6045
6069
|
return Err(new Error("_meta.md frontmatter `milestones` must be a list of strings"));
|
|
6046
6070
|
}
|
|
6047
|
-
|
|
6048
|
-
|
|
6071
|
+
return Ok(rawMilestones);
|
|
6072
|
+
}
|
|
6073
|
+
function attachAssignmentHistory(meta, body) {
|
|
6049
6074
|
if (body.includes("## Assignment History")) {
|
|
6050
6075
|
const history = parseAssignmentHistory(body);
|
|
6051
6076
|
if (!history.ok) return Err(history.error);
|
|
@@ -6078,43 +6103,49 @@ function isRegression(from, to) {
|
|
|
6078
6103
|
return STATUS_RANK[to] < STATUS_RANK[from];
|
|
6079
6104
|
}
|
|
6080
6105
|
function assembleRoadmap(shards, meta) {
|
|
6106
|
+
const byMilestone = groupShardsByMilestone(shards);
|
|
6107
|
+
const ordered = orderMilestoneNames(meta, byMilestone);
|
|
6108
|
+
const milestones = ordered.map((name) => buildMilestone(name, byMilestone));
|
|
6109
|
+
return {
|
|
6110
|
+
frontmatter: meta.frontmatter,
|
|
6111
|
+
milestones,
|
|
6112
|
+
assignmentHistory: meta.assignmentHistory ?? []
|
|
6113
|
+
};
|
|
6114
|
+
}
|
|
6115
|
+
function groupShardsByMilestone(shards) {
|
|
6081
6116
|
const byMilestone = /* @__PURE__ */ new Map();
|
|
6082
6117
|
for (const shard of shards) {
|
|
6083
6118
|
const bucket = byMilestone.get(shard.milestone);
|
|
6084
6119
|
if (bucket) bucket.push(shard);
|
|
6085
6120
|
else byMilestone.set(shard.milestone, [shard]);
|
|
6086
6121
|
}
|
|
6122
|
+
return byMilestone;
|
|
6123
|
+
}
|
|
6124
|
+
function orderMilestoneNames(meta, byMilestone) {
|
|
6087
6125
|
const ordered = [];
|
|
6088
6126
|
const seen = /* @__PURE__ */ new Set();
|
|
6089
|
-
|
|
6090
|
-
if (!seen.has(name)) {
|
|
6091
|
-
ordered.push(name);
|
|
6092
|
-
seen.add(name);
|
|
6093
|
-
}
|
|
6094
|
-
}
|
|
6095
|
-
for (const name of byMilestone.keys()) {
|
|
6127
|
+
const append = (name) => {
|
|
6096
6128
|
if (!seen.has(name)) {
|
|
6097
6129
|
ordered.push(name);
|
|
6098
6130
|
seen.add(name);
|
|
6099
6131
|
}
|
|
6100
|
-
}
|
|
6101
|
-
const
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
|
|
6105
|
-
|
|
6106
|
-
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
});
|
|
6132
|
+
};
|
|
6133
|
+
for (const name of meta.milestones) append(name);
|
|
6134
|
+
for (const name of byMilestone.keys()) append(name);
|
|
6135
|
+
return ordered;
|
|
6136
|
+
}
|
|
6137
|
+
function compareShards(a, b) {
|
|
6138
|
+
return a.order - b.order || STATUS_RANK[b.feature.status] - STATUS_RANK[a.feature.status] || // Deterministic code-unit comparison (NOT localeCompare, whose ICU/locale
|
|
6139
|
+
// collation is environment-dependent and threatens byte-stable regen).
|
|
6140
|
+
(a.slug < b.slug ? -1 : a.slug > b.slug ? 1 : 0);
|
|
6141
|
+
}
|
|
6142
|
+
function buildMilestone(name, byMilestone) {
|
|
6143
|
+
const bucket = [...byMilestone.get(name) ?? []];
|
|
6144
|
+
bucket.sort(compareShards);
|
|
6114
6145
|
return {
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6146
|
+
name,
|
|
6147
|
+
isBacklog: name === "Backlog",
|
|
6148
|
+
features: bucket.map((s) => s.feature)
|
|
6118
6149
|
};
|
|
6119
6150
|
}
|
|
6120
6151
|
function joinPath(dir, name) {
|
|
@@ -8940,10 +8971,12 @@ async function runEntropyCheck(projectRoot, config) {
|
|
|
8940
8971
|
const entropyConfig = config.entropy || {};
|
|
8941
8972
|
const perfConfig = config.performance || {};
|
|
8942
8973
|
const entryPoints = entropyConfig.entryPoints ?? perfConfig.entryPoints;
|
|
8974
|
+
const driftConfig = entropyConfig.drift;
|
|
8943
8975
|
const analyzer = new EntropyAnalyzer({
|
|
8944
8976
|
rootDir: projectRoot,
|
|
8945
8977
|
...entryPoints ? { entryPoints } : {},
|
|
8946
|
-
|
|
8978
|
+
...driftConfig?.docPaths ? { docPaths: driftConfig.docPaths } : {},
|
|
8979
|
+
analyze: { drift: driftConfig ?? true, deadCode: true, patterns: false }
|
|
8947
8980
|
});
|
|
8948
8981
|
const result = await analyzer.analyze();
|
|
8949
8982
|
if (!result.ok) {
|
|
@@ -12692,6 +12725,20 @@ async function fetchWithRetry(fetchFn, input, init, opts = RETRY_DEFAULTS) {
|
|
|
12692
12725
|
}
|
|
12693
12726
|
return lastResponse;
|
|
12694
12727
|
}
|
|
12728
|
+
function parseReferencedIssues(text) {
|
|
12729
|
+
if (!text) return [];
|
|
12730
|
+
const re = /(?:[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+)?#(\d+)/g;
|
|
12731
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12732
|
+
const out = [];
|
|
12733
|
+
for (const m of text.matchAll(re)) {
|
|
12734
|
+
const n = Number.parseInt(m[1], 10);
|
|
12735
|
+
if (Number.isInteger(n) && n > 0 && !seen.has(n)) {
|
|
12736
|
+
seen.add(n);
|
|
12737
|
+
out.push(n);
|
|
12738
|
+
}
|
|
12739
|
+
}
|
|
12740
|
+
return out;
|
|
12741
|
+
}
|
|
12695
12742
|
function isValidTrackerShape(tracker) {
|
|
12696
12743
|
if (!tracker || typeof tracker !== "object") return false;
|
|
12697
12744
|
const t = tracker;
|
|
@@ -13270,6 +13317,21 @@ function linearFromPriority(p) {
|
|
|
13270
13317
|
return 0;
|
|
13271
13318
|
}
|
|
13272
13319
|
}
|
|
13320
|
+
function metaDerivedFields(meta, issue) {
|
|
13321
|
+
return {
|
|
13322
|
+
spec: meta.spec ?? null,
|
|
13323
|
+
plans: meta.plan ? [meta.plan] : [],
|
|
13324
|
+
blockedBy: meta.blocked_by ?? [],
|
|
13325
|
+
assignee: assigneeDisplayName(issue.assignee),
|
|
13326
|
+
priority: meta.priority ?? priorityFromLinear(issue.priority),
|
|
13327
|
+
milestone: meta.milestone ?? null,
|
|
13328
|
+
createdAt: issue.createdAt ?? (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
13329
|
+
updatedAt: issue.updatedAt ?? null
|
|
13330
|
+
};
|
|
13331
|
+
}
|
|
13332
|
+
function assigneeDisplayName(assignee) {
|
|
13333
|
+
return assignee?.displayName ?? assignee?.name ?? null;
|
|
13334
|
+
}
|
|
13273
13335
|
function metaFrom(feature) {
|
|
13274
13336
|
const meta = {};
|
|
13275
13337
|
if (feature.spec != null) meta.spec = feature.spec;
|
|
@@ -13279,6 +13341,25 @@ function metaFrom(feature) {
|
|
|
13279
13341
|
if (feature.milestone != null) meta.milestone = feature.milestone;
|
|
13280
13342
|
return meta;
|
|
13281
13343
|
}
|
|
13344
|
+
function collectHistoryEvents(nodes) {
|
|
13345
|
+
const events = [];
|
|
13346
|
+
for (const c of nodes ?? []) {
|
|
13347
|
+
const parsed = parseHistoryComment(c.body);
|
|
13348
|
+
if (parsed) events.push(parsed);
|
|
13349
|
+
}
|
|
13350
|
+
return events;
|
|
13351
|
+
}
|
|
13352
|
+
function parseHistoryComment(body) {
|
|
13353
|
+
if (!body || !body.includes(HISTORY_MARKER)) return null;
|
|
13354
|
+
const m = /```json\s*([\s\S]*?)\s*```/.exec(body);
|
|
13355
|
+
if (!m?.[1]) return null;
|
|
13356
|
+
try {
|
|
13357
|
+
const parsed = JSON.parse(m[1]);
|
|
13358
|
+
if (parsed && typeof parsed.type === "string") return parsed;
|
|
13359
|
+
} catch {
|
|
13360
|
+
}
|
|
13361
|
+
return null;
|
|
13362
|
+
}
|
|
13282
13363
|
function createTrackerClient(config) {
|
|
13283
13364
|
if (config.kind === "github-issues") {
|
|
13284
13365
|
const token = config.token ?? process.env.GITHUB_TOKEN;
|
|
@@ -13725,6 +13806,50 @@ function checkRoadmapHealth(roadmap, options) {
|
|
|
13725
13806
|
}
|
|
13726
13807
|
return findings;
|
|
13727
13808
|
}
|
|
13809
|
+
function demoteUnactionablePlanned(feature, milestoneName, changes) {
|
|
13810
|
+
if (!isUnactionablePlanned(feature)) return;
|
|
13811
|
+
feature.status = "backlog";
|
|
13812
|
+
changes.push({
|
|
13813
|
+
kind: "demoted",
|
|
13814
|
+
feature: feature.name,
|
|
13815
|
+
from: milestoneName,
|
|
13816
|
+
to: "backlog"
|
|
13817
|
+
});
|
|
13818
|
+
}
|
|
13819
|
+
function restoreAssigneeInvariant(feature, milestoneName, changes) {
|
|
13820
|
+
if (feature.status !== "in-progress" && feature.assignee !== null) {
|
|
13821
|
+
changes.push({
|
|
13822
|
+
kind: "unassigned",
|
|
13823
|
+
feature: feature.name,
|
|
13824
|
+
from: milestoneName,
|
|
13825
|
+
to: feature.assignee
|
|
13826
|
+
});
|
|
13827
|
+
feature.assignee = null;
|
|
13828
|
+
} else if (feature.status === "in-progress" && feature.assignee === null) {
|
|
13829
|
+
feature.status = "planned";
|
|
13830
|
+
changes.push({
|
|
13831
|
+
kind: "demoted",
|
|
13832
|
+
feature: feature.name,
|
|
13833
|
+
from: milestoneName,
|
|
13834
|
+
to: "planned"
|
|
13835
|
+
});
|
|
13836
|
+
}
|
|
13837
|
+
}
|
|
13838
|
+
function groomFeature(feature, milestoneName, context, archived, changes) {
|
|
13839
|
+
demoteUnactionablePlanned(feature, milestoneName, changes);
|
|
13840
|
+
restoreAssigneeInvariant(feature, milestoneName, changes);
|
|
13841
|
+
if (context.archiveDone && feature.status === "done" && !context.archive && !context.isIntake) {
|
|
13842
|
+
archived.push(feature);
|
|
13843
|
+
changes.push({
|
|
13844
|
+
kind: "archived",
|
|
13845
|
+
feature: feature.name,
|
|
13846
|
+
from: milestoneName,
|
|
13847
|
+
to: "Shipped"
|
|
13848
|
+
});
|
|
13849
|
+
return false;
|
|
13850
|
+
}
|
|
13851
|
+
return true;
|
|
13852
|
+
}
|
|
13728
13853
|
function groomRoadmap(roadmap, options) {
|
|
13729
13854
|
const opts = resolveOptions(options);
|
|
13730
13855
|
const archiveDone = options?.archiveDone ?? true;
|
|
@@ -13732,49 +13857,14 @@ function groomRoadmap(roadmap, options) {
|
|
|
13732
13857
|
const archived = [];
|
|
13733
13858
|
const changes = [];
|
|
13734
13859
|
for (const milestone of next.milestones) {
|
|
13735
|
-
const
|
|
13736
|
-
|
|
13737
|
-
|
|
13738
|
-
|
|
13739
|
-
|
|
13740
|
-
|
|
13741
|
-
|
|
13742
|
-
|
|
13743
|
-
feature: feature.name,
|
|
13744
|
-
from: milestone.name,
|
|
13745
|
-
to: "backlog"
|
|
13746
|
-
});
|
|
13747
|
-
}
|
|
13748
|
-
if (feature.status !== "in-progress" && feature.assignee !== null) {
|
|
13749
|
-
changes.push({
|
|
13750
|
-
kind: "unassigned",
|
|
13751
|
-
feature: feature.name,
|
|
13752
|
-
from: milestone.name,
|
|
13753
|
-
to: feature.assignee
|
|
13754
|
-
});
|
|
13755
|
-
feature.assignee = null;
|
|
13756
|
-
} else if (feature.status === "in-progress" && feature.assignee === null) {
|
|
13757
|
-
feature.status = "planned";
|
|
13758
|
-
changes.push({
|
|
13759
|
-
kind: "demoted",
|
|
13760
|
-
feature: feature.name,
|
|
13761
|
-
from: milestone.name,
|
|
13762
|
-
to: "planned"
|
|
13763
|
-
});
|
|
13764
|
-
}
|
|
13765
|
-
if (archiveDone && feature.status === "done" && !archive && !isIntake) {
|
|
13766
|
-
archived.push(feature);
|
|
13767
|
-
changes.push({
|
|
13768
|
-
kind: "archived",
|
|
13769
|
-
feature: feature.name,
|
|
13770
|
-
from: milestone.name,
|
|
13771
|
-
to: "Shipped"
|
|
13772
|
-
});
|
|
13773
|
-
continue;
|
|
13774
|
-
}
|
|
13775
|
-
kept.push(feature);
|
|
13776
|
-
}
|
|
13777
|
-
milestone.features = kept;
|
|
13860
|
+
const context = {
|
|
13861
|
+
archiveDone,
|
|
13862
|
+
archive: opts.isArchive(milestone.name),
|
|
13863
|
+
isIntake: milestone.name === opts.intakeMilestone
|
|
13864
|
+
};
|
|
13865
|
+
milestone.features = milestone.features.filter(
|
|
13866
|
+
(feature) => groomFeature(feature, milestone.name, context, archived, changes)
|
|
13867
|
+
);
|
|
13778
13868
|
}
|
|
13779
13869
|
next.milestones = next.milestones.filter(
|
|
13780
13870
|
(m) => m.features.length > 0 || m.name === opts.intakeMilestone
|
|
@@ -15060,7 +15150,7 @@ function arrayLen(arr) {
|
|
|
15060
15150
|
return Array.isArray(arr) ? arr.length : 0;
|
|
15061
15151
|
}
|
|
15062
15152
|
async function gatherEntropyBlock(projectPath) {
|
|
15063
|
-
const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./analyzer-
|
|
15153
|
+
const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./analyzer-XRCV63KC-HLTEIKAJ.js");
|
|
15064
15154
|
const analyzer = new EntropyAnalyzer2({
|
|
15065
15155
|
rootDir: projectPath,
|
|
15066
15156
|
include: ["src/**/*.ts", "src/**/*.tsx", "packages/*/src/**/*.ts"],
|
|
@@ -15976,9 +16066,9 @@ function writeStrategyDoc(doc, opts) {
|
|
|
15976
16066
|
var WHATWG_BAD_PORTS, BAD_PORT_SET, VALID_TYPES, CONVENTIONAL_PATTERN, LOOKBACK_PATTERN, PulseDbSourceSchema, PulseSourcesSchema, PulseConfigSchema, KNOWN_SECTION_NAMES, ISO_DATE, PLACEHOLDER_INLINE, REQUIRED, ALLOWED, StrategyFrontmatterSchema, StrategySectionSchema, StrategyDocSchema, BUG_TRACK_CATEGORIES, KNOWLEDGE_TRACK_CATEGORIES, ALL_SOLUTION_CATEGORIES, ISO_DATE2, BugTrackSchema, KnowledgeTrackSchema, BaseFrontmatter, SolutionDocFrontmatterSchema, TRACK_CATEGORIES, DEFAULT_AGNIX_TIMEOUT_MS, HARNESS_AGNIX_DISABLE, HARNESS_AGNIX_BIN, CLAUDE_MD_WARN_BYTES, CLAUDE_MD_ERROR_BYTES, CONTEXT_FILES, MIN_DESCRIPTION_LENGTH, SETTINGS_PATHS, KNOWN_HOOK_EVENTS, MCP_SETTINGS_FILES, REQUIRED_SECTIONS, SETTINGS_FILES, KNOWN_AGNIX_TOOLS, ROADMAP_READ_ALLOWLIST, ROADMAP_MD, DYNAMIC_ROADMAP_IO, KEBAB_CASE, TICKET_ID, DEFAULT_SECTIONS, DEFAULT_RATIOS, NODE_TYPE_TO_CATEGORY, SECTION_LEVEL_MAP, DEFAULT_LEVEL, DEFAULT_BUDGET, DEFAULT_LOADER_CONFIG, LEVEL_FRACTIONS, PHASE_PRIORITIES, ManifestSchema, BundleConstraintsSchema, BundleSchema, ContributionsSchema, LockfilePackageSchema, LockfileSchema, SharableLayerSchema, SharableForbiddenImportSchema, SharableBoundaryConfigSchema, SharableSecurityRulesSchema, VALID_SCOPES, LINE_PATTERN, START_PATTERN, END_PATTERN, readFile72, writeFile32, unlink22, mkdir22, copyFile2, DEFAULT_FIX_CONFIG, EXPORT_TYPE_KEYWORD, ALWAYS_UNSAFE_TYPES, idCounter, DEAD_CODE_FIX_ACTIONS, MustExportRuleSchema, MustExportDefaultRuleSchema, NoExportRuleSchema, MustImportRuleSchema, NoImportRuleSchema, NamingRuleSchema, MaxExportsRuleSchema, MaxLinesRuleSchema, RequireJSDocRuleSchema, RuleSchema, ConfigPatternSchema, PatternConfigSchema, DriftConfigSchema, DeadCodeConfigSchema, EntropyConfigSchema, BaselineManager, BenchmarkRunner, RegressionDetector, SOURCE_EXTENSIONS, FUNCTION_DECL_RE, CONST_DECL_RE, CriticalPathResolver, NoOpTelemetryAdapter, NoOpExecutor, ConsoleSink, feedbackConfig, ChecklistBuilder, AgentActionEmitter, globalEmitter, FileSink, NoOpSink, ConfidenceTierSchema, RegressionResultSchema, DirectionSchema, CategoryForecastSchema, SpecImpactSignalsSchema, SpecImpactEstimateSchema, ContributingFeatureSchema, AdjustedForecastSchema, PredictionWarningSchema, StabilityForecastSchema, PredictionResultSchema, PredictionOptionsSchema, VALID_STATUSES, EM_DASH, VALID_PRIORITIES, EM_DASH2, H3_NAME, FRONTMATTER, STATUS_RANK, META_FILE, ShardStore, MonolithStore, ALL_CATEGORIES, DIRECTION_THRESHOLD, PredictionEngine, DEFAULT_COEFFICIENTS, SpecImpactEstimator, EMPTY_HISTORY, ViolationHistoryManager, NORMALIZERS, MAX_SAMPLES, DEFAULT_WINDOW_WEEKS, DEFAULT_MIN_OCCURRENCES, FailureEntrySchema, HandoffSchema, GateCheckSchema, GateResultSchema, GateConfigSchema, HarnessStateSchema, DEFAULT_STATE, HARNESS_DIR, STATE_FILE, LEARNINGS_FILE, FAILURES_FILE, HANDOFF_FILE, GATE_CONFIG_FILE, INDEX_FILE, SESSIONS_DIR, SESSION_INDEX_FILE, SUMMARY_FILE, SESSION_STATE_FILE, ARCHIVE_DIR, CONTENT_HASHES_FILE, StreamInfoSchema, StreamIndexSchema, DEFAULT_STREAM_INDEX, EVENT_LOG_FILE, EVENT_BLOBS_DIR, MAX_LINE_BYTES, BLOB_REF_KEY, SNAPSHOT_FILE, STREAMS_DIR, STREAM_NAME_REGEX, branchCache, BRANCH_CACHE_TTL_MS, STATE_FILES, STATE_DIRS, MAX_CACHE_ENTRIES, learningsCacheMap, WEIGHTS, LOCK_RETRIES, LOCK_BACKOFFS, PROMOTABLE_OUTCOMES, failuresCacheMap, FAILURE_LINE_REGEX, SAFE_GATE_COMMAND, event_sourcing_exports, ScopeSchema, envelopeShape, StateImportedPayload, DecisionRecordedPayload, PositionSetPayload, BlockerOpenedPayload, BlockerResolvedPayload, ProgressSetPayload, SessionSummarizedPayload, LANES, LaneSchema, TaskRegisteredPayload, LaneTransitionedPayload, UserInputCapturedPayload, ApprovalRequestedPayload, ApprovalResolvedPayload, EventSchema, BlobRefSchema, StoredEventSchema, cached, localCounters, CORE_HANDLERS, KIND_LABEL, MATERIALIZE_DEBOUNCE_MS, pendingTimers, inflightMaterializes, ensured, TERMINAL_LANES, NON_TERMINAL, TABLE, RuleRegistry, DEFAULT_SECURITY_CONFIG, RuleOverrideSchema, SecurityConfigSchema, secretRules, injectionRules, xssRules, cryptoRules, pathTraversalRules, networkRules, deserializationRules, agentConfigRules, mcpRules, insecureDefaultsRules, sharpEdgesRules, nodeRules, expressRules, reactRules, goRules, SecurityScanner, OSV_ENDPOINT, DEFAULT_CACHE_DIR, DEFAULT_TTL_HOURS, hiddenUnicodePatterns, reRolingPatterns, permissionEscalationPatterns, encodedPayloadPatterns, indirectInjectionPatterns, contextManipulationPatterns, socialEngineeringPatterns, suspiciousPatterns, ALL_PATTERNS, DESTRUCTIVE_BASH, TAINT_DURATION_MS, DEFAULT_SESSION_ID, SecurityCategorySnapshotSchema, SupplyChainSnapshotSchema, SecurityTimelineSnapshotSchema, FindingLifecycleSchema, SecurityTimelineFileSchema, DirectionSchema2, SecurityTrendLineSchema, TrendAttributionSchema, SecurityTrendResultSchema, TimeToFixStatsSchema, TimeToFixResultSchema, EMPTY_SUPPLY_CHAIN, SecurityTimelineManager, ALL_CHECKS, STATUS_ICONS, CINotifier, ExclusionSet, PREFIX_PATTERNS, TEST_FILE_PATTERN, MD_FILE_PATTERN, ALL_DOMAINS, SECURITY_PATTERNS, JS_EXT_FALLBACKS, SEVERITY_RANK, SEVERITY_ORDER, SEVERITY_LABELS, VALIDATED_BY_RANK, VALIDATION_SCORES, DOMAIN_BASELINES, FACTOR_WEIGHTS, EVIDENCE_SATURATION, CORROBORATED_AGREEMENT, STANDALONE_AGREEMENT, AGREEMENT_LINE_GAP, COMPLIANCE_DESCRIPTOR, EXPORT_RE, BUG_DETECTION_DESCRIPTOR, SECURITY_DESCRIPTOR, EVAL_PATTERN, SECRET_PATTERNS, SQL_CONCAT_PATTERN, SHELL_EXEC_PATTERN, ARCHITECTURE_DESCRIPTOR, LARGE_FILE_THRESHOLD, VIOLATION_FILE_RE, LEARNINGS_DESCRIPTOR, RELEVANCE_THRESHOLD, ADVERSARIAL_DESCRIPTOR, UNVERIFIED_INPUT_PATTERN, PROMISE_NO_REJECT_PATTERN, UNGUARDED_OPTIONAL_CALL, COMPOSE_NO_AWAIT, FETCH_NO_TIMEOUT, TYPESCRIPT_STRICT_DESCRIPTOR, EXPLICIT_ANY_PATTERN, TS_IGNORE_PATTERN, UNSAFE_AS_UNKNOWN, NON_NULL_ASSERTION, VAGUE_HELPER_NAME, FRONTEND_RACES_DESCRIPTOR, AGENT_DESCRIPTORS, CONDITIONAL_SUBAGENT_DESCRIPTORS, AGENT_RUNNERS, SUBAGENT_ORDER, RISK_KEYWORDS, EXCLUDED_PATH_PATTERNS, ASYNC_UI_SIGNALS, WORD_BOUNDARY, DOWNGRADE_MAP, DEFAULT_PROVIDER_TIERS, SMALL_SUGGESTION_LINE_LIMIT, FILE_LINE_RANGE_PATTERN, FILE_LINE_PATTERN, FILE_ONLY_PATTERN, SECURITY_SENSITIVE_PATH, MIGRATION_PATH, TEST_PATH, CONFIG_PATH, STAGE_DOMAINS, CI_REVIEW_VERDICT_SCHEMA_VERSION, CI_RUNNERS, CI_ASSESSMENTS, CI_REVIEW_DOMAINS, ReviewFindingSchema, CiReviewVerdictSchema, VERDICT_MAP, RUNNER_PRESETS, VERDICT_MAP2, DEFAULT_EXEC_TIMEOUT_MS, DEFAULT_EXEC_MAX_STDOUT_BYTES, STDERR_CAP_BYTES, STDERR_TAIL_BYTES, defaultExecFile, EMPTY_TIER, EM_DASH3, DEFAULT_MILESTONE, MAX_CLOSEST_MATCHES, MACHINE_ASSIGNEE_PATTERNS, EXTERNAL_ID_RE, RETRY_DEFAULTS, GitHubIssuesSyncAdapter, syncMutex, PRIORITY_RANK, PRIORITY_RANK2, POSITION_WEIGHT, DEPENDENTS_WEIGHT, AFFINITY_WEIGHT, ConflictError, DEFAULTS, GitHubHttp, ETagStore, START_MARKER, END_MARKER, SERIALIZER_FIELDS, GitHubIssuesTrackerAdapter, LINEAR_ENDPOINT, EXTERNAL_PREFIX, HISTORY_MARKER, ISSUE_FIELDS, LinearTrackerAdapter, migrate_exports, HASH_RE, DEFAULT_CATCH_ALL, DEFAULT_INTAKE, DEFAULT_MAX_ACTIVE, InteractionTypeSchema, QuestionSchema, ConfirmationSchema, TransitionSchema, EmitInteractionInputSchema, ProjectScanner, SHELL_TEMPLATE, STYLES, SCRIPTS, MockLLMService, llmService, ContentPipeline, BlueprintGenerator, TOKENS_PER_MILLION, fallback_default, LITELLM_PRICING_URL, CACHE_TTL_MS, STALENESS_WARNING_DAYS, MICRODOLLARS_PER_DOLLAR, TOKENS_PER_MILLION2, StructuralStrategy, DEFAULT_TOKEN_BUDGET, CHARS_PER_TOKEN, TRUNCATION_MARKER, TruncationStrategy, CompactionPipeline, STABILITY_LOOKUP, TIER_ORDER, AnthropicCacheAdapter, TIER_ORDER2, OpenAICacheAdapter, TIER_ORDER3, CACHED_CONTENT_MARKER, GeminiCacheAdapter, VERSION, POSTHOG_BATCH_URL, MAX_ATTEMPTS, TIMEOUT_MS, DEFAULT_CAPACITY, CacheMetricsRecorder, RETRY_BACKOFFS_MS, DEFAULT_FLUSH_INTERVAL_MS, DEFAULT_BATCH_SIZE, defaultFetch, defaultWarn, OTLPExporter, SERVICE_NAME_ATTR, SpanKind, ModeSchema, SeveritySchema, TierSchema, StrengthFindingSchema, HarnessConfigSubsetSchema, HookFileSchema, ProjectContextSchema, AuditSummarySchema, AuditResultSchema, SEVERITY_WEIGHTS, clamp, HOOK_SCRIPT_TOKEN, NEVER_BLOCKS, ALWAYS_EXIT_ZERO, EXIT_ZERO_LINE, NONZERO_EXIT, GATE, ERREXIT, strength001NonblockingHooks, BASELINE_REWRITE, strength002Autobaseline, SKIP_RE, strength003SkipList, strength004EmptyThresholds, INIT_SKILL_PATH, DEFAULT_BASIC, strength005LowestTier, AUTO_PATTERN, COMMENT_LINE, NAME_VALUE_LINE, PAT_GATING, REVIEW_SIGNAL, strength006AutoapproveBaseline, CHECK_KEYS, SIGNAL_REGISTRY, HEALTH_SIGNAL_NAMES, CHECK_SIGNAL_MAP, SIGNAL_CATEGORY_MAP, strength007SnapshotSignalMismatch, ALL_RULES, HarnessStrengthAuditor, MAX_TOP_AFFECTED, CompoundLockHeldError, KNOWN_CATEGORIES, ProposalNotFoundError, ProposalConflictError, ALLOWED_FIELD_KEYS, PII_TOKENS, PII_FIELD_DENYLIST, PII_LINE_RE, ALLOWED_SET, PulseAdapterAlreadyRegisteredError, REGISTRY, MOCK_ADAPTER_NAME, ALLOWED_FIELD_SET, adapter, LOOKBACK_RE, MAX_LINES, INLINE_TEMPLATE, TRUNCATION_MARKER2, execFileAsync, FIX_RE, EMPTY_REPO_RE, execFileAsync2, TRACK_CATEGORIES2, STOPWORDS, KEYWORD_TO_CATEGORY, SECTION_ORDER, FILENAME;
|
|
15977
16067
|
var init_dist3 = __esm({
|
|
15978
16068
|
"../core/dist/index.mjs"() {
|
|
15979
|
-
|
|
15980
|
-
|
|
15981
|
-
|
|
16069
|
+
init_chunk_OFA2AAZK();
|
|
16070
|
+
init_chunk_IHRT6II2();
|
|
16071
|
+
init_chunk_JZ7UO3OF();
|
|
15982
16072
|
init_chunk_XKLVJIPL();
|
|
15983
16073
|
init_chunk_IIEDD47I();
|
|
15984
16074
|
init_chunk_7P6ASYW6();
|
|
@@ -17106,7 +17196,7 @@ var init_dist3 = __esm({
|
|
|
17106
17196
|
check: "Context validation",
|
|
17107
17197
|
passed: graphData.graphExists && graphData.nodeCount > 0,
|
|
17108
17198
|
severity: "info",
|
|
17109
|
-
details: graphData.graphExists ? `Graph loaded: ${graphData.nodeCount} nodes, ${graphData.edgeCount} edges` : "No graph available \u2014 run harness scan to build the knowledge graph"
|
|
17199
|
+
details: graphData.graphExists ? `Graph loaded: ${graphData.nodeCount} nodes, ${graphData.edgeCount} edges` : "No graph available \u2014 run harness graph scan to build the knowledge graph"
|
|
17110
17200
|
}) : void 0
|
|
17111
17201
|
)
|
|
17112
17202
|
);
|
|
@@ -21823,14 +21913,7 @@ ${JSON.stringify(event)}`;
|
|
|
21823
21913
|
name: issue.title,
|
|
21824
21914
|
status: statusFromStateType(issue.state?.type),
|
|
21825
21915
|
summary,
|
|
21826
|
-
|
|
21827
|
-
plans: meta.plan ? [meta.plan] : [],
|
|
21828
|
-
blockedBy: meta.blocked_by ?? [],
|
|
21829
|
-
assignee: issue.assignee?.displayName ?? issue.assignee?.name ?? null,
|
|
21830
|
-
priority: meta.priority ?? priorityFromLinear(issue.priority),
|
|
21831
|
-
milestone: meta.milestone ?? null,
|
|
21832
|
-
createdAt: issue.createdAt ?? (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
21833
|
-
updatedAt: issue.updatedAt ?? null
|
|
21916
|
+
...metaDerivedFields(meta, issue)
|
|
21834
21917
|
};
|
|
21835
21918
|
}
|
|
21836
21919
|
/** Resolve (and cache) the team's first state id of each workflow type. */
|
|
@@ -21858,6 +21941,12 @@ ${JSON.stringify(event)}`;
|
|
|
21858
21941
|
if (!r.ok) return r;
|
|
21859
21942
|
return Ok(r.value.users?.nodes?.[0]?.id ?? null);
|
|
21860
21943
|
}
|
|
21944
|
+
/** Resolve an assignee to a Linear user id, or null when absent/unresolved. */
|
|
21945
|
+
async assigneeIdFor(assignee) {
|
|
21946
|
+
if (!assignee) return null;
|
|
21947
|
+
const userR = await this.resolveUserId(assignee);
|
|
21948
|
+
return userR.ok && userR.value ? userR.value : null;
|
|
21949
|
+
}
|
|
21861
21950
|
// ── Reads ──────────────────────────────────────────────────────────────
|
|
21862
21951
|
async fetchAll() {
|
|
21863
21952
|
const r = await this.gql(
|
|
@@ -21888,18 +21977,9 @@ ${JSON.stringify(event)}`;
|
|
|
21888
21977
|
async create(feature) {
|
|
21889
21978
|
const stateR = await this.resolveStateId(feature.status ?? "backlog");
|
|
21890
21979
|
if (!stateR.ok) return stateR;
|
|
21891
|
-
const
|
|
21892
|
-
const
|
|
21893
|
-
|
|
21894
|
-
title: feature.name,
|
|
21895
|
-
description: body,
|
|
21896
|
-
stateId: stateR.value,
|
|
21897
|
-
priority: linearFromPriority(feature.priority)
|
|
21898
|
-
};
|
|
21899
|
-
if (feature.assignee) {
|
|
21900
|
-
const userR = await this.resolveUserId(feature.assignee);
|
|
21901
|
-
if (userR.ok && userR.value) input.assigneeId = userR.value;
|
|
21902
|
-
}
|
|
21980
|
+
const input = this.buildCreateInput(feature, stateR.value);
|
|
21981
|
+
const assigneeId = await this.assigneeIdFor(feature.assignee);
|
|
21982
|
+
if (assigneeId) input.assigneeId = assigneeId;
|
|
21903
21983
|
const r = await this.gql(
|
|
21904
21984
|
`mutation($input:IssueCreateInput!){ issueCreate(input:$input){ issue { ${ISSUE_FIELDS} } } }`,
|
|
21905
21985
|
{ input }
|
|
@@ -21909,6 +21989,16 @@ ${JSON.stringify(event)}`;
|
|
|
21909
21989
|
if (!issue) return Err(new Error("Linear issueCreate returned no issue"));
|
|
21910
21990
|
return Ok(this.featureFromIssue(issue));
|
|
21911
21991
|
}
|
|
21992
|
+
/** Assemble the IssueCreateInput payload for a new feature (sans assignee, which is resolved async). */
|
|
21993
|
+
buildCreateInput(feature, stateId) {
|
|
21994
|
+
return {
|
|
21995
|
+
teamId: this.teamId,
|
|
21996
|
+
title: feature.name,
|
|
21997
|
+
description: serializeBodyBlock(feature.summary ?? "", metaFrom(feature)),
|
|
21998
|
+
stateId,
|
|
21999
|
+
priority: linearFromPriority(feature.priority)
|
|
22000
|
+
};
|
|
22001
|
+
}
|
|
21912
22002
|
/** Shared issueUpdate with optional optimistic-concurrency check on updatedAt. */
|
|
21913
22003
|
async issueUpdate(externalId, input, ifMatch) {
|
|
21914
22004
|
const id = this.toIssueId(externalId);
|
|
@@ -21935,6 +22025,26 @@ ${JSON.stringify(event)}`;
|
|
|
21935
22025
|
if (!issue) return Err(new Error("Linear issueUpdate returned no issue"));
|
|
21936
22026
|
return Ok(this.featureFromIssue(issue));
|
|
21937
22027
|
}
|
|
22028
|
+
/**
|
|
22029
|
+
* Merge body-backed patch fields into the current issue's harness-meta block,
|
|
22030
|
+
* returning the serialized description (so the meta block isn't clobbered).
|
|
22031
|
+
*/
|
|
22032
|
+
async mergedDescription(externalId, patch) {
|
|
22033
|
+
const cur = await this.fetchById(externalId);
|
|
22034
|
+
if (!cur.ok) return cur;
|
|
22035
|
+
if (!cur.value) return Err(new Error(`Linear issue not found: ${externalId}`));
|
|
22036
|
+
const f = cur.value.feature;
|
|
22037
|
+
const merged = {
|
|
22038
|
+
name: patch.name ?? f.name,
|
|
22039
|
+
summary: patch.summary ?? f.summary,
|
|
22040
|
+
spec: patch.spec !== void 0 ? patch.spec : f.spec,
|
|
22041
|
+
plans: patch.plans !== void 0 ? patch.plans : f.plans,
|
|
22042
|
+
blockedBy: patch.blockedBy !== void 0 ? patch.blockedBy : f.blockedBy,
|
|
22043
|
+
priority: patch.priority !== void 0 ? patch.priority : f.priority,
|
|
22044
|
+
milestone: patch.milestone !== void 0 ? patch.milestone : f.milestone
|
|
22045
|
+
};
|
|
22046
|
+
return Ok(serializeBodyBlock(merged.summary ?? "", metaFrom(merged)));
|
|
22047
|
+
}
|
|
21938
22048
|
async update(externalId, patch, ifMatch) {
|
|
21939
22049
|
const input = {};
|
|
21940
22050
|
if (patch.name !== void 0) input.title = patch.name;
|
|
@@ -21953,31 +22063,23 @@ ${JSON.stringify(event)}`;
|
|
|
21953
22063
|
"milestone"
|
|
21954
22064
|
];
|
|
21955
22065
|
if (bodyFields.some((k) => patch[k] !== void 0)) {
|
|
21956
|
-
const
|
|
21957
|
-
if (!
|
|
21958
|
-
|
|
21959
|
-
const f = cur.value.feature;
|
|
21960
|
-
const merged = {
|
|
21961
|
-
name: patch.name ?? f.name,
|
|
21962
|
-
summary: patch.summary ?? f.summary,
|
|
21963
|
-
spec: patch.spec !== void 0 ? patch.spec : f.spec,
|
|
21964
|
-
plans: patch.plans !== void 0 ? patch.plans : f.plans,
|
|
21965
|
-
blockedBy: patch.blockedBy !== void 0 ? patch.blockedBy : f.blockedBy,
|
|
21966
|
-
priority: patch.priority !== void 0 ? patch.priority : f.priority,
|
|
21967
|
-
milestone: patch.milestone !== void 0 ? patch.milestone : f.milestone
|
|
21968
|
-
};
|
|
21969
|
-
input.description = serializeBodyBlock(merged.summary ?? "", metaFrom(merged));
|
|
21970
|
-
}
|
|
21971
|
-
if (patch.assignee !== void 0) {
|
|
21972
|
-
if (patch.assignee === null) {
|
|
21973
|
-
input.assigneeId = null;
|
|
21974
|
-
} else {
|
|
21975
|
-
const userR = await this.resolveUserId(patch.assignee);
|
|
21976
|
-
if (userR.ok && userR.value) input.assigneeId = userR.value;
|
|
21977
|
-
}
|
|
22066
|
+
const descR = await this.mergedDescription(externalId, patch);
|
|
22067
|
+
if (!descR.ok) return descR;
|
|
22068
|
+
input.description = descR.value;
|
|
21978
22069
|
}
|
|
22070
|
+
await this.applyAssigneeUpdate(patch, input);
|
|
21979
22071
|
return this.issueUpdate(externalId, input, ifMatch);
|
|
21980
22072
|
}
|
|
22073
|
+
/** Resolve `patch.assignee` (name → user id, or explicit null to unassign) into the update input. */
|
|
22074
|
+
async applyAssigneeUpdate(patch, input) {
|
|
22075
|
+
if (patch.assignee === void 0) return;
|
|
22076
|
+
if (patch.assignee === null) {
|
|
22077
|
+
input.assigneeId = null;
|
|
22078
|
+
return;
|
|
22079
|
+
}
|
|
22080
|
+
const userR = await this.resolveUserId(patch.assignee);
|
|
22081
|
+
if (userR.ok && userR.value) input.assigneeId = userR.value;
|
|
22082
|
+
}
|
|
21981
22083
|
async claim(externalId, assignee, ifMatch) {
|
|
21982
22084
|
const userR = await this.resolveUserId(assignee);
|
|
21983
22085
|
if (!userR.ok) return userR;
|
|
@@ -22017,17 +22119,7 @@ ${JSON.stringify(event)}
|
|
|
22017
22119
|
{ id: this.toIssueId(externalId) }
|
|
22018
22120
|
);
|
|
22019
22121
|
if (!r.ok) return r;
|
|
22020
|
-
const events =
|
|
22021
|
-
for (const c of r.value.issue?.comments?.nodes ?? []) {
|
|
22022
|
-
if (!c.body || !c.body.includes(HISTORY_MARKER)) continue;
|
|
22023
|
-
const m = /```json\s*([\s\S]*?)\s*```/.exec(c.body);
|
|
22024
|
-
if (!m?.[1]) continue;
|
|
22025
|
-
try {
|
|
22026
|
-
const parsed = JSON.parse(m[1]);
|
|
22027
|
-
if (parsed && typeof parsed.type === "string") events.push(parsed);
|
|
22028
|
-
} catch {
|
|
22029
|
-
}
|
|
22030
|
-
}
|
|
22122
|
+
const events = collectHistoryEvents(r.value.issue?.comments?.nodes);
|
|
22031
22123
|
return Ok(typeof limit === "number" ? events.slice(0, limit) : events);
|
|
22032
22124
|
}
|
|
22033
22125
|
};
|
|
@@ -23490,6 +23582,7 @@ export {
|
|
|
23490
23582
|
parseExternalId,
|
|
23491
23583
|
buildExternalId,
|
|
23492
23584
|
GitHubIssuesSyncAdapter,
|
|
23585
|
+
parseReferencedIssues,
|
|
23493
23586
|
loadTrackerSyncConfig,
|
|
23494
23587
|
reconcileDoneFromClosedIssues,
|
|
23495
23588
|
syncToExternal,
|