runbrief 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/cli.js +478 -65
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,13 +13,13 @@ name used in the install command.
|
|
|
13
13
|
Claude Code:
|
|
14
14
|
|
|
15
15
|
```sh
|
|
16
|
-
claude mcp add --transport stdio --scope user brief -- npx -y runbrief@0.1.
|
|
16
|
+
claude mcp add --transport stdio --scope user brief -- npx -y runbrief@0.1.1
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
Codex:
|
|
20
20
|
|
|
21
21
|
```sh
|
|
22
|
-
codex mcp add brief -- npx -y runbrief@0.1.
|
|
22
|
+
codex mcp add brief -- npx -y runbrief@0.1.1
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
Generic MCP configuration:
|
|
@@ -29,7 +29,7 @@ Generic MCP configuration:
|
|
|
29
29
|
"mcpServers": {
|
|
30
30
|
"brief": {
|
|
31
31
|
"command": "npx",
|
|
32
|
-
"args": ["-y", "runbrief@0.1.
|
|
32
|
+
"args": ["-y", "runbrief@0.1.1"]
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
}
|
package/dist/cli.js
CHANGED
|
@@ -636,6 +636,13 @@ var init_dist = __esm({
|
|
|
636
636
|
sources: z.array(z.string()),
|
|
637
637
|
tokenEstimate: z.number().int().nonnegative(),
|
|
638
638
|
omitted: z.array(z.string()),
|
|
639
|
+
valueSignals: z.object({
|
|
640
|
+
relevantSourceCount: z.number().int().nonnegative(),
|
|
641
|
+
reusablePrimitiveCount: z.number().int().nonnegative(),
|
|
642
|
+
parserBackedEntityCount: z.number().int().nonnegative(),
|
|
643
|
+
appliedTeamGuidanceCount: z.number().int().nonnegative(),
|
|
644
|
+
suggestedTestCount: z.number().int().nonnegative()
|
|
645
|
+
}).optional(),
|
|
639
646
|
teamGuidance: teamGuidanceDeliverySchema.optional()
|
|
640
647
|
});
|
|
641
648
|
contextReceiptRequestSchema = z.object({
|
|
@@ -2732,6 +2739,7 @@ function saveLocalContextReceiptUnlocked(repoRoot, packet, input) {
|
|
|
2732
2739
|
mapNodeCount: packet.map.length,
|
|
2733
2740
|
memoryCount: packet.memories.length,
|
|
2734
2741
|
suggestedTests: packet.suggestedTests,
|
|
2742
|
+
...packet.valueSignals ? { valueSignals: packet.valueSignals } : {},
|
|
2735
2743
|
...packet.teamGuidance ? { teamGuidance: packet.teamGuidance } : {},
|
|
2736
2744
|
git
|
|
2737
2745
|
};
|
|
@@ -2830,6 +2838,18 @@ function buildLocalValueReport(repoRoot, repoName = path3.basename(repoRoot)) {
|
|
|
2830
2838
|
const receiptCount = receipts.length + handoffs.length;
|
|
2831
2839
|
const proofLedger = buildProofLedger(receipts, handoffs, proofLoop);
|
|
2832
2840
|
const impact = impactReportFor(receipts);
|
|
2841
|
+
const valueSignals = receipts.reduce((summary, receipt) => {
|
|
2842
|
+
summary.reusablePrimitiveCount += receipt.valueSignals?.reusablePrimitiveCount ?? 0;
|
|
2843
|
+
summary.parserBackedEntityCount += receipt.valueSignals?.parserBackedEntityCount ?? 0;
|
|
2844
|
+
summary.appliedTeamGuidanceCount += receipt.valueSignals?.appliedTeamGuidanceCount ?? 0;
|
|
2845
|
+
summary.suggestedTestTargetCount += receipt.valueSignals?.suggestedTestCount ?? 0;
|
|
2846
|
+
return summary;
|
|
2847
|
+
}, {
|
|
2848
|
+
reusablePrimitiveCount: 0,
|
|
2849
|
+
parserBackedEntityCount: 0,
|
|
2850
|
+
appliedTeamGuidanceCount: 0,
|
|
2851
|
+
suggestedTestTargetCount: 0
|
|
2852
|
+
});
|
|
2833
2853
|
const report = {
|
|
2834
2854
|
repoName,
|
|
2835
2855
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -2839,6 +2859,7 @@ function buildLocalValueReport(repoRoot, repoName = path3.basename(repoRoot)) {
|
|
|
2839
2859
|
reviewCheckCount: receipts.filter((receipt) => receipt.kind === "review").length,
|
|
2840
2860
|
handoffCount: handoffs.length,
|
|
2841
2861
|
estimatedTokensSaved,
|
|
2862
|
+
...valueSignals,
|
|
2842
2863
|
averagePacketTokens,
|
|
2843
2864
|
topSources,
|
|
2844
2865
|
recentTasks: receipts.slice(0, 8).map((receipt) => ({
|
|
@@ -11948,14 +11969,14 @@ function contextForTask(scan, request) {
|
|
|
11948
11969
|
const scoped = files.length > 0;
|
|
11949
11970
|
const rankedRules = rankRules(scan.rules, task, files);
|
|
11950
11971
|
const initialRules = rankedRules.slice(0, scoped ? 8 : 12);
|
|
11972
|
+
const initialSkills = selectSkills(scan.skills, task, files, scoped).map(compactSkillForContext);
|
|
11951
11973
|
const mapCandidates = mapCandidatesForTask(scan, task, files);
|
|
11952
11974
|
const rankedMap = rankMap(mapCandidates, task, files);
|
|
11953
|
-
const
|
|
11954
|
-
const selectedMap = takeRuleGroundedMapNodes(mapCandidates, initialGroundingRules, rankedMap, scoped ? 14 : 18).map(compactMapNodeForContext);
|
|
11975
|
+
const selectedMap = takeGuidanceGroundedMapNodes(mapCandidates, scan.sources, rulesStronglyRelevantForGrounding(initialRules, task), initialSkills, rankedMap, files, scoped ? 14 : 18).map(compactMapNodeForContext);
|
|
11955
11976
|
const suggestedTests = selectValidationForContext(scan.map, scan.sources, task, files, selectedMap, request.repoRoot);
|
|
11956
11977
|
const initialSelection = {
|
|
11957
11978
|
rules: initialRules,
|
|
11958
|
-
skills:
|
|
11979
|
+
skills: initialSkills,
|
|
11959
11980
|
map: selectedMap,
|
|
11960
11981
|
wikiPages: selectWikiPages(buildContextWiki(scan).pages, task, files, scoped, suggestedTests).map(compactWikiPageForContext),
|
|
11961
11982
|
memories: rankMemories(scan.memories, task, files).slice(0, scoped ? 4 : 8).map(compactMemoryForContext),
|
|
@@ -11968,7 +11989,7 @@ function contextForTask(scan, request) {
|
|
|
11968
11989
|
files
|
|
11969
11990
|
});
|
|
11970
11991
|
const { rules: selectedRules, skills: selectedSkills, map: budgetedMap, wikiPages: selectedWikiPages, memories: selectedMemories } = selection;
|
|
11971
|
-
const finalMap =
|
|
11992
|
+
const finalMap = takeGuidanceGroundedMapNodes(mapCandidates, scan.sources, rulesStronglyRelevantForGrounding(selectedRules, task), selectedSkills, budgetedMap, files, Math.max(budgetedMap.length, scoped ? 2 : 4)).map(compactMapNodeForContext);
|
|
11972
11993
|
const finalSuggestedTests = selectValidationForContext(scan.map, scan.sources, task, files, finalMap, request.repoRoot);
|
|
11973
11994
|
const owners = selectOwners(scan.map, files);
|
|
11974
11995
|
const sources = unique([
|
|
@@ -11978,6 +11999,7 @@ function contextForTask(scan, request) {
|
|
|
11978
11999
|
...selectedWikiPages.flatMap((page2) => page2.sourcePaths),
|
|
11979
12000
|
...selectedMemories.flatMap((memory) => memory.sourcePaths)
|
|
11980
12001
|
]);
|
|
12002
|
+
const teamGuidance = scan.teamGuidanceCatalog ? teamGuidanceDeliveryFor(scan, selectedRules, selectedSkills, selectedMemories) : void 0;
|
|
11981
12003
|
const packet = {
|
|
11982
12004
|
packetId: packetId(),
|
|
11983
12005
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -11993,19 +12015,49 @@ function contextForTask(scan, request) {
|
|
|
11993
12015
|
sources,
|
|
11994
12016
|
tokenEstimate,
|
|
11995
12017
|
omitted,
|
|
11996
|
-
|
|
11997
|
-
|
|
11998
|
-
} : {}
|
|
12018
|
+
valueSignals: contextValueSignals(finalMap, finalSuggestedTests, sources.length, teamGuidance?.applied.length ?? 0),
|
|
12019
|
+
...teamGuidance ? { teamGuidance } : {}
|
|
11999
12020
|
};
|
|
12000
12021
|
return enforceContextPacketBudget(packet, maxTokens, files);
|
|
12001
12022
|
}
|
|
12023
|
+
function contextValueSignals(map, suggestedTests, relevantSourceCount, appliedTeamGuidanceCount) {
|
|
12024
|
+
const reusablePrimitiveCount = map.filter((node) => {
|
|
12025
|
+
if (!["component", "route", "source", "risk"].includes(node.type)) {
|
|
12026
|
+
return false;
|
|
12027
|
+
}
|
|
12028
|
+
const metadata = node.metadata ?? {};
|
|
12029
|
+
return [
|
|
12030
|
+
"exports",
|
|
12031
|
+
"astFunctions",
|
|
12032
|
+
"astClasses",
|
|
12033
|
+
"astComponents",
|
|
12034
|
+
"hooks",
|
|
12035
|
+
"services",
|
|
12036
|
+
"models",
|
|
12037
|
+
"commands",
|
|
12038
|
+
"domainEntities"
|
|
12039
|
+
].some((key) => Array.isArray(metadata[key]) && metadata[key].length > 0);
|
|
12040
|
+
}).length;
|
|
12041
|
+
const parserBackedEntityCount = map.reduce((total, node) => {
|
|
12042
|
+
const value = node.metadata?.parserBackedEntityCount;
|
|
12043
|
+
return total + (typeof value === "number" && value > 0 ? value : 0);
|
|
12044
|
+
}, 0);
|
|
12045
|
+
return {
|
|
12046
|
+
relevantSourceCount,
|
|
12047
|
+
reusablePrimitiveCount,
|
|
12048
|
+
parserBackedEntityCount,
|
|
12049
|
+
appliedTeamGuidanceCount,
|
|
12050
|
+
suggestedTestCount: suggestedTests.length
|
|
12051
|
+
};
|
|
12052
|
+
}
|
|
12002
12053
|
function codebaseMapForTask(scan, request, limit = 80) {
|
|
12003
12054
|
const files = request.files ?? [];
|
|
12004
12055
|
const hasSpecificScope = files.length > 0 || wordsFor3(request.task).length > 1;
|
|
12005
12056
|
const mapCandidates = mapCandidatesForTask(scan, request.task, files);
|
|
12006
12057
|
const rankedMap = rankMap(mapCandidates, request.task, files);
|
|
12007
|
-
const
|
|
12008
|
-
const
|
|
12058
|
+
const selectedRules = rankRules(scan.rules, request.task, files).filter((rule) => ruleIsStronglyRelevantForGrounding(rule, request.task)).slice(0, files.length > 0 ? 8 : 12);
|
|
12059
|
+
const selectedSkills = selectSkills(scan.skills, request.task, files, files.length > 0);
|
|
12060
|
+
const ruleGroundedMap = takeGuidanceGroundedMapNodes(mapCandidates, scan.sources, selectedRules, selectedSkills, [], files, Math.min(8, limit));
|
|
12009
12061
|
const selected = hasSpecificScope ? diversifyMap(uniqueMapNodes([...ruleGroundedMap, ...rankedMap]), limit) : broadCodebaseOverview(scan.map, limit);
|
|
12010
12062
|
return withMapCoverageNotice(selected, scan, request, limit);
|
|
12011
12063
|
}
|
|
@@ -12100,58 +12152,100 @@ function sourceFallbackMapNode(sourcePath) {
|
|
|
12100
12152
|
}
|
|
12101
12153
|
};
|
|
12102
12154
|
}
|
|
12103
|
-
function
|
|
12104
|
-
const groundedPaths =
|
|
12105
|
-
const
|
|
12106
|
-
|
|
12107
|
-
|
|
12108
|
-
|
|
12109
|
-
|
|
12155
|
+
function takeGuidanceGroundedMapNodes(scanMap, sources, rules, skills, rankedMap, files, limit) {
|
|
12156
|
+
const groundedPaths = guidanceReferencedSourcePaths(sources, rules, skills);
|
|
12157
|
+
const nodeBySourcePath = /* @__PURE__ */ new Map();
|
|
12158
|
+
for (const node of scanMap) {
|
|
12159
|
+
const sourcePath = mapNodeSourcePath(node);
|
|
12160
|
+
if (!nodeBySourcePath.has(sourcePath))
|
|
12161
|
+
nodeBySourcePath.set(sourcePath, node);
|
|
12162
|
+
}
|
|
12163
|
+
const explicitNodes = rankedMap.filter((node) => files.includes(mapNodeSourcePath(node)));
|
|
12164
|
+
const groundedNodes = groundedPaths.map((sourcePath) => {
|
|
12165
|
+
const mappedNode = nodeBySourcePath.get(sourcePath);
|
|
12166
|
+
return mappedNode ? markGuidanceGroundedMapNode(mappedNode) : guidanceSourceFallbackMapNode(sourcePath);
|
|
12110
12167
|
});
|
|
12111
|
-
const groundedLimit = Math.min(limit, 8, Math.max(3, Math.ceil(limit / 2)));
|
|
12112
12168
|
return uniqueMapNodes([
|
|
12113
|
-
...
|
|
12169
|
+
...explicitNodes,
|
|
12170
|
+
...groundedNodes,
|
|
12114
12171
|
...rankedMap
|
|
12115
12172
|
]).slice(0, limit);
|
|
12116
12173
|
}
|
|
12117
|
-
function
|
|
12118
|
-
const
|
|
12119
|
-
const
|
|
12120
|
-
const
|
|
12121
|
-
const
|
|
12122
|
-
|
|
12123
|
-
|
|
12124
|
-
|
|
12125
|
-
|
|
12126
|
-
|
|
12174
|
+
function guidanceReferencedSourcePaths(sources, rules, skills) {
|
|
12175
|
+
const sourcePaths = new Map(sources.filter((source) => isCodeOrTestPath(source.path)).map((source) => [source.path.toLowerCase(), source.path]));
|
|
12176
|
+
const pathsByStem = /* @__PURE__ */ new Map();
|
|
12177
|
+
for (const sourcePath of sourcePaths.values()) {
|
|
12178
|
+
const rawStem = pathBasename(sourcePath).replace(/\.[^.]+$/, "");
|
|
12179
|
+
if (rawStem.length < 6 || !/[A-Z_$]/.test(rawStem))
|
|
12180
|
+
continue;
|
|
12181
|
+
const stem = rawStem.toLowerCase();
|
|
12182
|
+
pathsByStem.set(stem, [...pathsByStem.get(stem) ?? [], sourcePath]);
|
|
12183
|
+
}
|
|
12184
|
+
const guidanceText = [
|
|
12185
|
+
...rules.map((rule) => `${rule.title}
|
|
12186
|
+
${rule.body}`),
|
|
12187
|
+
...skills.map((skill) => [
|
|
12188
|
+
skill.name,
|
|
12189
|
+
skill.description,
|
|
12190
|
+
skill.body,
|
|
12191
|
+
skill.triggers.join(" "),
|
|
12192
|
+
skill.teamShare?.rationale ?? "",
|
|
12193
|
+
skill.teamShare?.guardrails.join(" ") ?? ""
|
|
12194
|
+
].join("\n"))
|
|
12195
|
+
].join("\n");
|
|
12196
|
+
const selected = [];
|
|
12197
|
+
for (const rule of rules) {
|
|
12198
|
+
const body = rule.body.toLowerCase().replaceAll("\\", "/");
|
|
12199
|
+
for (const sourcePath of rule.sourcePaths) {
|
|
12200
|
+
if (!isCodeOrTestPath(sourcePath))
|
|
12201
|
+
continue;
|
|
12202
|
+
const normalizedPath = sourcePath.toLowerCase().replaceAll("\\", "/");
|
|
12203
|
+
const rawStem = pathBasename(sourcePath).replace(/\.[^.]+$/, "");
|
|
12204
|
+
if (body.includes(normalizedPath) || body.includes(pathBasename(normalizedPath)) || rawStem.length >= 6 && /[A-Z_$]/.test(rawStem) && body.includes(rawStem.toLowerCase())) {
|
|
12205
|
+
selected.push(sourcePath);
|
|
12206
|
+
}
|
|
12207
|
+
}
|
|
12208
|
+
}
|
|
12209
|
+
for (const match of guidanceText.matchAll(/[A-Za-z0-9_.@/-]+\.(?:[cm]?[tj]sx?|py|go|rb|sql|graphql|gql)\b/g)) {
|
|
12210
|
+
const referencedPath = match[0]?.replace(/^\.\//, "").toLowerCase();
|
|
12211
|
+
const canonicalPath = referencedPath ? sourcePaths.get(referencedPath) : void 0;
|
|
12212
|
+
if (canonicalPath)
|
|
12213
|
+
selected.push(canonicalPath);
|
|
12214
|
+
}
|
|
12215
|
+
for (const match of guidanceText.matchAll(/\b[A-Za-z_$][A-Za-z0-9_$-]{5,}\b/g)) {
|
|
12216
|
+
const matches = pathsByStem.get(match[0]?.toLowerCase() ?? "") ?? [];
|
|
12217
|
+
if (matches.length === 1)
|
|
12218
|
+
selected.push(matches[0]);
|
|
12219
|
+
}
|
|
12220
|
+
return unique(selected);
|
|
12127
12221
|
}
|
|
12128
12222
|
function pathBasename(sourcePath) {
|
|
12129
12223
|
return sourcePath.split("/").at(-1) ?? sourcePath;
|
|
12130
12224
|
}
|
|
12131
|
-
function
|
|
12225
|
+
function markGuidanceGroundedMapNode(node) {
|
|
12132
12226
|
return {
|
|
12133
12227
|
...node,
|
|
12134
12228
|
metadata: {
|
|
12135
12229
|
...node.metadata ?? {},
|
|
12136
12230
|
evidenceKinds: unique([
|
|
12137
12231
|
...metadataStringsForScore(node.metadata, "evidenceKinds"),
|
|
12138
|
-
"
|
|
12232
|
+
"guidance_reference"
|
|
12139
12233
|
])
|
|
12140
12234
|
}
|
|
12141
12235
|
};
|
|
12142
12236
|
}
|
|
12143
|
-
function
|
|
12237
|
+
function guidanceSourceFallbackMapNode(sourcePath) {
|
|
12144
12238
|
return {
|
|
12145
|
-
id: idFor("map", `
|
|
12239
|
+
id: idFor("map", `guidance-source:${sourcePath}`),
|
|
12146
12240
|
type: isLikelyTestPath(sourcePath) ? "test" : "source",
|
|
12147
12241
|
name: titleFromPath(sourcePath),
|
|
12148
12242
|
path: sourcePath,
|
|
12149
|
-
summary: "Source file cited by
|
|
12150
|
-
tags: unique(["source", ...fallbackTagsForPath(sourcePath)]),
|
|
12243
|
+
summary: "Source file cited by selected repo or team guidance; included even when the broad map cap omits it.",
|
|
12244
|
+
tags: unique(["source", "guidance", ...fallbackTagsForPath(sourcePath)]),
|
|
12151
12245
|
metadata: {
|
|
12152
12246
|
sourcePath,
|
|
12153
|
-
evidenceKinds: ["
|
|
12154
|
-
entityConfidence:
|
|
12247
|
+
evidenceKinds: ["guidance_reference"],
|
|
12248
|
+
entityConfidence: 82
|
|
12155
12249
|
}
|
|
12156
12250
|
};
|
|
12157
12251
|
}
|
|
@@ -12190,6 +12284,9 @@ function uniqueMapNodes(nodes) {
|
|
|
12190
12284
|
function mapNodeSourcePath(node) {
|
|
12191
12285
|
return typeof node.metadata?.sourcePath === "string" ? node.metadata.sourcePath : node.path;
|
|
12192
12286
|
}
|
|
12287
|
+
function mapNodeHasGuidanceEvidence(node) {
|
|
12288
|
+
return metadataStringsForScore(node.metadata, "evidenceKinds").some((kind) => ["guidance_reference", "rule_reference"].includes(kind));
|
|
12289
|
+
}
|
|
12193
12290
|
function isCodeOrTestPath(sourcePath) {
|
|
12194
12291
|
return /\.(?:[cm]?[tj]sx?|py|go|rb|sql|graphql|gql)$/.test(sourcePath);
|
|
12195
12292
|
}
|
|
@@ -12793,17 +12890,17 @@ function ruleIsStronglyRelevantForGrounding(rule, task) {
|
|
|
12793
12890
|
function fitSelectionToBudget(initialSelection, options2) {
|
|
12794
12891
|
const selection = cloneSelection(initialSelection);
|
|
12795
12892
|
const omitted = [];
|
|
12796
|
-
const protectedMapPaths = new Set(selection.map.filter((node) => mapNodeRelatesToExplicitFile(node, options2.files)).map(mapNodeSourcePath));
|
|
12893
|
+
const protectedMapPaths = new Set(selection.map.filter((node) => mapNodeRelatesToExplicitFile(node, options2.files) || mapNodeHasGuidanceEvidence(node)).map(mapNodeSourcePath));
|
|
12797
12894
|
const minimums = {
|
|
12798
12895
|
rules: options2.scoped ? Math.min(selection.rules.length, 3) : 5,
|
|
12799
|
-
skills: 0,
|
|
12896
|
+
skills: selection.skills.some(isApprovedSharedSkill) ? 1 : 0,
|
|
12800
12897
|
map: options2.scoped ? Math.min(selection.map.length, 8) : 10,
|
|
12801
12898
|
wikiPages: options2.scoped ? Math.min(selection.wikiPages.length, 1) : 2,
|
|
12802
12899
|
memories: 0
|
|
12803
12900
|
};
|
|
12804
12901
|
const hardMinimums = {
|
|
12805
12902
|
rules: Math.min(selection.rules.length, options2.scoped ? 1 : 2),
|
|
12806
|
-
skills: 0,
|
|
12903
|
+
skills: selection.skills.some(isApprovedSharedSkill) ? 1 : 0,
|
|
12807
12904
|
map: Math.max(Math.min(selection.map.length, options2.scoped ? 2 : 4), protectedMapPaths.size),
|
|
12808
12905
|
wikiPages: 0,
|
|
12809
12906
|
memories: 0
|
|
@@ -12867,7 +12964,7 @@ function enforceContextPacketBudget(packet, maxTokens, explicitFiles) {
|
|
|
12867
12964
|
let trimmed = packet.omitted.length > 0;
|
|
12868
12965
|
if (trimmed)
|
|
12869
12966
|
packet.omitted = [omittedReason];
|
|
12870
|
-
const protectedMapPaths = new Set(packet.map.filter((node) => mapNodeRelatesToExplicitFile(node, explicitFiles)).map(mapNodeSourcePath));
|
|
12967
|
+
const protectedMapPaths = new Set(packet.map.filter((node) => mapNodeRelatesToExplicitFile(node, explicitFiles) || mapNodeHasGuidanceEvidence(node)).map(mapNodeSourcePath));
|
|
12871
12968
|
let tokenEstimate = estimateContextPacketTokens(packet);
|
|
12872
12969
|
const maxTrimSteps = removableContextItemCount(packet) + 1;
|
|
12873
12970
|
let trimSteps = 0;
|
|
@@ -12993,20 +13090,37 @@ function compactProtectedMapMetadata(metadata) {
|
|
|
12993
13090
|
"symbolKind",
|
|
12994
13091
|
"symbolName",
|
|
12995
13092
|
"role",
|
|
12996
|
-
"entityConfidence"
|
|
13093
|
+
"entityConfidence",
|
|
13094
|
+
"parserBackedEntityCount"
|
|
12997
13095
|
]) {
|
|
12998
13096
|
const value = metadata[key];
|
|
12999
13097
|
if (value !== void 0)
|
|
13000
13098
|
compact[key] = value;
|
|
13001
13099
|
}
|
|
13002
13100
|
for (const key of [
|
|
13101
|
+
"evidenceKinds",
|
|
13003
13102
|
"exports",
|
|
13004
13103
|
"imports",
|
|
13005
13104
|
"importedBy",
|
|
13006
13105
|
"relatedTests",
|
|
13007
13106
|
"owners",
|
|
13008
13107
|
"validationCommands",
|
|
13009
|
-
"changeRisk"
|
|
13108
|
+
"changeRisk",
|
|
13109
|
+
"astClasses",
|
|
13110
|
+
"astCommands",
|
|
13111
|
+
"astComponents",
|
|
13112
|
+
"astFunctions",
|
|
13113
|
+
"astHooks",
|
|
13114
|
+
"astJobs",
|
|
13115
|
+
"astModels",
|
|
13116
|
+
"astServices",
|
|
13117
|
+
"commands",
|
|
13118
|
+
"domainEntities",
|
|
13119
|
+
"hooks",
|
|
13120
|
+
"jobs",
|
|
13121
|
+
"models",
|
|
13122
|
+
"procedures",
|
|
13123
|
+
"services"
|
|
13010
13124
|
]) {
|
|
13011
13125
|
const value = metadata[key];
|
|
13012
13126
|
if (Array.isArray(value))
|
|
@@ -13025,6 +13139,7 @@ function refreshContextPacketDerivedFields(packet) {
|
|
|
13025
13139
|
suggestedTests: packet.suggestedTests
|
|
13026
13140
|
});
|
|
13027
13141
|
refreshTeamGuidanceDelivery(packet);
|
|
13142
|
+
packet.valueSignals = contextValueSignals(packet.map, packet.suggestedTests, packet.sources.length, packet.teamGuidance?.applied.length ?? 0);
|
|
13028
13143
|
}
|
|
13029
13144
|
function teamGuidanceDeliveryFor(scan, rules, skills, memories) {
|
|
13030
13145
|
const catalog = scan.teamGuidanceCatalog;
|
|
@@ -13127,6 +13242,9 @@ function lastDroppableRuleIndex(rules) {
|
|
|
13127
13242
|
}
|
|
13128
13243
|
return -1;
|
|
13129
13244
|
}
|
|
13245
|
+
function isApprovedSharedSkill(skill) {
|
|
13246
|
+
return skill.status === "approved";
|
|
13247
|
+
}
|
|
13130
13248
|
function compactSkillForContext(skill) {
|
|
13131
13249
|
return {
|
|
13132
13250
|
...skill,
|
|
@@ -13248,11 +13366,27 @@ var init_context = __esm({
|
|
|
13248
13366
|
]);
|
|
13249
13367
|
contextMetadataKeys = /* @__PURE__ */ new Set([
|
|
13250
13368
|
"accessControls",
|
|
13369
|
+
"agentTools",
|
|
13370
|
+
"astClasses",
|
|
13371
|
+
"astCommands",
|
|
13372
|
+
"astComponents",
|
|
13373
|
+
"astFunctions",
|
|
13374
|
+
"astHooks",
|
|
13375
|
+
"astJobs",
|
|
13376
|
+
"astModels",
|
|
13377
|
+
"astServices",
|
|
13251
13378
|
"changeRisk",
|
|
13379
|
+
"commands",
|
|
13380
|
+
"domainEntities",
|
|
13252
13381
|
"entityConfidence",
|
|
13253
13382
|
"envVars",
|
|
13254
13383
|
"evidenceKinds",
|
|
13255
13384
|
"exports",
|
|
13385
|
+
"hooks",
|
|
13386
|
+
"jobs",
|
|
13387
|
+
"models",
|
|
13388
|
+
"parserBackedEntityCount",
|
|
13389
|
+
"procedures",
|
|
13256
13390
|
"importedBy",
|
|
13257
13391
|
"imports",
|
|
13258
13392
|
"loopHints",
|
|
@@ -13260,6 +13394,7 @@ var init_context = __esm({
|
|
|
13260
13394
|
"relatedTests",
|
|
13261
13395
|
"role",
|
|
13262
13396
|
"routes",
|
|
13397
|
+
"services",
|
|
13263
13398
|
"sourcePath",
|
|
13264
13399
|
"symbolKind",
|
|
13265
13400
|
"symbolName",
|
|
@@ -26085,7 +26220,7 @@ var init_agentSetup = __esm({
|
|
|
26085
26220
|
"ide",
|
|
26086
26221
|
"generic"
|
|
26087
26222
|
];
|
|
26088
|
-
briefPublishedPackageSpec = "runbrief@0.1.
|
|
26223
|
+
briefPublishedPackageSpec = "runbrief@0.1.1";
|
|
26089
26224
|
TARGET_LABELS = {
|
|
26090
26225
|
terminal: "Terminal agent",
|
|
26091
26226
|
vscode: "VS Code",
|
|
@@ -27136,6 +27271,41 @@ var init_agentStart = __esm({
|
|
|
27136
27271
|
});
|
|
27137
27272
|
|
|
27138
27273
|
// ../core/dist/agentBeforeYouCode.js
|
|
27274
|
+
function summarizeBeforeYouCodeSharedContext(delivery) {
|
|
27275
|
+
if (!delivery) {
|
|
27276
|
+
return {
|
|
27277
|
+
status: "not_available",
|
|
27278
|
+
applied: [],
|
|
27279
|
+
availableCount: 0,
|
|
27280
|
+
omittedCount: 0,
|
|
27281
|
+
next: "Shared guidance is not available in this session; keep new learning personal until the workspace connection is ready."
|
|
27282
|
+
};
|
|
27283
|
+
}
|
|
27284
|
+
const next = delivery.status === "applied" ? "Use the applied shared guidance, then save a focused learning or reference when the pass proves a reusable pattern." : delivery.status === "available_not_applied" ? "Shared guidance exists but did not match this task; inspect the relevant team item before creating a new pattern." : "No approved shared guidance exists yet; keep this pass personal and publish only after the pattern is proven.";
|
|
27285
|
+
return {
|
|
27286
|
+
status: delivery.status,
|
|
27287
|
+
workspaceId: delivery.workspaceId,
|
|
27288
|
+
revision: delivery.revision,
|
|
27289
|
+
availableCount: delivery.availableCount,
|
|
27290
|
+
applied: delivery.applied.slice(0, 4),
|
|
27291
|
+
omittedCount: delivery.omittedCount,
|
|
27292
|
+
next
|
|
27293
|
+
};
|
|
27294
|
+
}
|
|
27295
|
+
function summarizeBeforeYouCodeReferences(beforeYouCode) {
|
|
27296
|
+
return {
|
|
27297
|
+
status: beforeYouCode.referenceFirst.status,
|
|
27298
|
+
availableCount: beforeYouCode.referenceFirst.availableCount,
|
|
27299
|
+
decision: beforeYouCode.referenceFirst.decision,
|
|
27300
|
+
references: beforeYouCode.referenceFirst.references.slice(0, 2).map((reference) => ({
|
|
27301
|
+
title: reference.title,
|
|
27302
|
+
kind: reference.kind,
|
|
27303
|
+
sourcePaths: reference.sourcePaths.slice(0, 4),
|
|
27304
|
+
useWhen: reference.useWhen.slice(0, 2),
|
|
27305
|
+
doNotCopy: reference.doNotCopy.slice(0, 2)
|
|
27306
|
+
}))
|
|
27307
|
+
};
|
|
27308
|
+
}
|
|
27139
27309
|
function missionScopeFilesFromBeforeYouCode(beforeYouCode, requestedFiles = []) {
|
|
27140
27310
|
const explicitFiles = unique(requestedFiles);
|
|
27141
27311
|
if (explicitFiles.length > 0)
|
|
@@ -27170,6 +27340,7 @@ function buildBeforeYouCodeMap(scan, input) {
|
|
|
27170
27340
|
files,
|
|
27171
27341
|
maxTokens: 2500
|
|
27172
27342
|
});
|
|
27343
|
+
const referenceFirst = referenceFirstFor(loadLocalReferenceImplementations(input.repoRoot), input.task);
|
|
27173
27344
|
const taskAwareSources = scan.sources.map((source, index) => ({
|
|
27174
27345
|
source,
|
|
27175
27346
|
index,
|
|
@@ -27192,7 +27363,7 @@ function buildBeforeYouCodeMap(scan, input) {
|
|
|
27192
27363
|
...context.map.map((node) => ({
|
|
27193
27364
|
...node,
|
|
27194
27365
|
evidenceKinds: Array.isArray(node.metadata?.evidenceKinds) ? node.metadata.evidenceKinds.filter((kind) => typeof kind === "string") : [],
|
|
27195
|
-
priority: Array.isArray(node.metadata?.evidenceKinds) && node.metadata.evidenceKinds.
|
|
27366
|
+
priority: Array.isArray(node.metadata?.evidenceKinds) && node.metadata.evidenceKinds.some((kind) => ["rule_reference", "guidance_reference"].includes(kind)) ? 3 : 0
|
|
27196
27367
|
})),
|
|
27197
27368
|
...taskAwareSources.map((node) => ({ ...node, priority: 0 })),
|
|
27198
27369
|
...taskAwareMap.map((node) => ({ ...node, priority: 0 })),
|
|
@@ -27203,26 +27374,26 @@ function buildBeforeYouCodeMap(scan, input) {
|
|
|
27203
27374
|
priority: 0
|
|
27204
27375
|
}))
|
|
27205
27376
|
], input.task);
|
|
27206
|
-
const
|
|
27377
|
+
const mappedReuseCandidateScores = insights.agentPacket.reuseGuard.candidates.map((candidate, index) => ({
|
|
27207
27378
|
candidate,
|
|
27208
27379
|
index,
|
|
27209
|
-
intentScore:
|
|
27210
|
-
})).filter(({ intentScore }) => intentScore >
|
|
27211
|
-
const inspectReuseCandidates = inspectFirst.filter((item) => (beforeYouCodePathIntentScore(item.path, input.task) >= 40 || item.evidenceKinds.
|
|
27380
|
+
intentScore: beforeYouCodeReuseScore(candidate, input.task)
|
|
27381
|
+
})).filter(({ candidate, intentScore }) => intentScore > 0 || intentScore >= 0 && candidate.evidenceKinds.some((kind) => ["ast", "parser"].includes(kind)) && candidate.symbols.length > 0).sort((a, b) => b.intentScore - a.intentScore || a.index - b.index).map(({ candidate }) => reuseCandidateFor(candidate));
|
|
27382
|
+
const inspectReuseCandidates = inspectFirst.filter((item) => (beforeYouCodePathIntentScore(item.path, input.task) >= 40 || item.evidenceKinds.some((kind) => ["rule_reference", "guidance_reference"].includes(kind))) && !/\.(test|spec)\.[cm]?[tj]sx?$/i.test(item.path)).map((item) => ({
|
|
27212
27383
|
path: item.path,
|
|
27213
27384
|
action: "Extend this existing implementation or rule it out.",
|
|
27214
27385
|
why: item.why,
|
|
27215
27386
|
evidenceKinds: item.evidenceKinds
|
|
27216
27387
|
}));
|
|
27217
27388
|
const reuseCandidates = uniqueReuseCandidates([
|
|
27218
|
-
...
|
|
27389
|
+
...mappedReuseCandidateScores,
|
|
27219
27390
|
...inspectReuseCandidates
|
|
27220
27391
|
]).sort((a, b) => {
|
|
27221
27392
|
const inspectRank = (candidate) => {
|
|
27222
27393
|
const index = inspectFirst.findIndex((item) => item.path === candidate.path);
|
|
27223
27394
|
return index < 0 ? 0 : Math.max(0, 6 - index) * 60;
|
|
27224
27395
|
};
|
|
27225
|
-
return
|
|
27396
|
+
return beforeYouCodeReuseScore(b, input.task) + inspectRank(b) - (beforeYouCodeReuseScore(a, input.task) + inspectRank(a));
|
|
27226
27397
|
}).slice(0, 5);
|
|
27227
27398
|
const taskDerivedTestFiles = inspectFirstTestTargets(inspectFirst, prefersPrimaryWorkspaceTask(input.task));
|
|
27228
27399
|
const testScopeFiles = files.length > 0 ? files : taskDerivedTestFiles.length > 0 ? taskDerivedTestFiles : target.changedFiles;
|
|
@@ -27245,7 +27416,7 @@ function buildBeforeYouCodeMap(scan, input) {
|
|
|
27245
27416
|
const validationChecklist = validationChecklistFor({
|
|
27246
27417
|
task: input.task,
|
|
27247
27418
|
likelyTests,
|
|
27248
|
-
reuseStatus:
|
|
27419
|
+
reuseStatus: reuseStatusFor(reuseCandidates)
|
|
27249
27420
|
});
|
|
27250
27421
|
const productOperatingContext = buildProductOperatingContext(scan, {
|
|
27251
27422
|
task: input.task,
|
|
@@ -27261,6 +27432,7 @@ function buildBeforeYouCodeMap(scan, input) {
|
|
|
27261
27432
|
...target.dirty && files.length === 0 ? ["Dirty worktree is broad; classify baseline before editing."] : []
|
|
27262
27433
|
]).slice(0, 5);
|
|
27263
27434
|
const status = inspectFirst.length === 0 && reuseCandidates.length === 0 ? "needs_narrower_scope" : "ready";
|
|
27435
|
+
const reuseSummary = reuseCandidates.length > 0 ? `${reuseCandidates.length} focused reuse candidate${reuseCandidates.length === 1 ? "" : "s"} matched this task; extend or explicitly rule them out before creating new code.` : "No task-relevant reuse candidate is grounded yet; narrow the task or search once more before creating new code.";
|
|
27264
27436
|
const headline = status === "ready" ? `${scan.repoName}: inspect ${inspectFirst.length} file${inspectFirst.length === 1 ? "" : "s"} and rule out ${reuseCandidates.length} reuse candidate${reuseCandidates.length === 1 ? "" : "s"} before coding.` : `${scan.repoName}: no focused code map yet; narrow by folder, feature, or proposed files before coding.`;
|
|
27265
27437
|
const taskSize = taskSizeFor({
|
|
27266
27438
|
task: input.task,
|
|
@@ -27276,6 +27448,8 @@ function buildBeforeYouCodeMap(scan, input) {
|
|
|
27276
27448
|
reuseCandidates,
|
|
27277
27449
|
likelyTests,
|
|
27278
27450
|
productOperatingContext,
|
|
27451
|
+
...context.teamGuidance ? { teamGuidance: context.teamGuidance } : {},
|
|
27452
|
+
referenceFirst,
|
|
27279
27453
|
validationChecklist,
|
|
27280
27454
|
stopSignals: stopSignals2
|
|
27281
27455
|
});
|
|
@@ -27288,6 +27462,8 @@ function buildBeforeYouCodeMap(scan, input) {
|
|
|
27288
27462
|
productOperatingContext,
|
|
27289
27463
|
validationChecklist,
|
|
27290
27464
|
stopSignals: stopSignals2,
|
|
27465
|
+
...context.teamGuidance ? { teamGuidance: context.teamGuidance } : {},
|
|
27466
|
+
referenceFirst,
|
|
27291
27467
|
maxLines: input.maxLines ?? 30
|
|
27292
27468
|
});
|
|
27293
27469
|
return {
|
|
@@ -27298,10 +27474,13 @@ function buildBeforeYouCodeMap(scan, input) {
|
|
|
27298
27474
|
cockpit,
|
|
27299
27475
|
inspectFirst,
|
|
27300
27476
|
reuseFirst: {
|
|
27301
|
-
status:
|
|
27302
|
-
summary:
|
|
27303
|
-
candidates: reuseCandidates
|
|
27477
|
+
status: reuseStatusFor(reuseCandidates),
|
|
27478
|
+
summary: reuseSummary,
|
|
27479
|
+
candidates: reuseCandidates,
|
|
27480
|
+
decision: reuseCandidates.length > 0 ? "For each candidate, choose reuse, adapt, or rule out and record the decision before creating a new primitive." : "No reuse candidate is grounded yet; run one focused search before creating a new primitive."
|
|
27304
27481
|
},
|
|
27482
|
+
...context.teamGuidance ? { teamGuidance: context.teamGuidance } : {},
|
|
27483
|
+
referenceFirst,
|
|
27305
27484
|
likelyTests,
|
|
27306
27485
|
exactTests,
|
|
27307
27486
|
productOperatingContext,
|
|
@@ -27312,6 +27491,71 @@ function buildBeforeYouCodeMap(scan, input) {
|
|
|
27312
27491
|
next: status === "ready" ? "Inspect these files and reuse candidates before editing; cite the reuse decision in the final handoff." : "Run brief.codebase_map or brief.context_for_task with a narrower task, folder, or file list before editing."
|
|
27313
27492
|
};
|
|
27314
27493
|
}
|
|
27494
|
+
function reuseStatusFor(candidates) {
|
|
27495
|
+
if (candidates.length === 0)
|
|
27496
|
+
return "missing";
|
|
27497
|
+
return candidates.length >= 3 || candidates.some((candidate) => candidate.evidenceKinds.includes("ast")) ? "strong" : "partial";
|
|
27498
|
+
}
|
|
27499
|
+
function beforeYouCodeReuseScore(candidate, task) {
|
|
27500
|
+
const candidateText2 = "symbols" in candidate ? [
|
|
27501
|
+
candidate.path,
|
|
27502
|
+
candidate.name,
|
|
27503
|
+
...candidate.symbols,
|
|
27504
|
+
...candidate.relatedEntities
|
|
27505
|
+
].join(" ") : [candidate.path, candidate.action, candidate.why].join(" ");
|
|
27506
|
+
const taskTerms = new Set(reuseTerms(task));
|
|
27507
|
+
const candidateTerms = new Set(reuseTerms(candidateText2));
|
|
27508
|
+
const symbolMatches = [...taskTerms].filter((term) => candidateTerms.has(term)).length;
|
|
27509
|
+
return beforeYouCodePathIntentScore(candidate.path, task) + Math.min(48, symbolMatches * 12);
|
|
27510
|
+
}
|
|
27511
|
+
function reuseTerms(input) {
|
|
27512
|
+
return referenceQueryTerms(input.replace(/([a-z0-9])([A-Z])/g, "$1 $2"));
|
|
27513
|
+
}
|
|
27514
|
+
function referenceFirstFor(references, task) {
|
|
27515
|
+
const active = references.filter((reference) => reference.status !== "archived");
|
|
27516
|
+
const terms = referenceQueryTerms(task);
|
|
27517
|
+
const scored = active.map((reference, index) => ({
|
|
27518
|
+
reference,
|
|
27519
|
+
index,
|
|
27520
|
+
score: terms.reduce((score, term) => {
|
|
27521
|
+
const haystack = [
|
|
27522
|
+
reference.title,
|
|
27523
|
+
reference.summary,
|
|
27524
|
+
reference.kind,
|
|
27525
|
+
...reference.tags,
|
|
27526
|
+
...reference.appliesTo,
|
|
27527
|
+
...reference.useWhen,
|
|
27528
|
+
...reference.sourcePaths
|
|
27529
|
+
].join(" ").toLowerCase();
|
|
27530
|
+
return score + (haystack.includes(term) ? 1 : 0);
|
|
27531
|
+
}, 0)
|
|
27532
|
+
})).sort((a, b) => b.score - a.score || b.reference.updatedAt.localeCompare(a.reference.updatedAt) || a.index - b.index);
|
|
27533
|
+
const matched = scored.filter((item) => item.score > 0).map((item) => item.reference);
|
|
27534
|
+
const selected = (matched.length > 0 ? matched : []).slice(0, 4);
|
|
27535
|
+
const status = selected.length > 0 ? "matched" : active.length > 0 ? "available_unmatched" : "none";
|
|
27536
|
+
return {
|
|
27537
|
+
status,
|
|
27538
|
+
availableCount: active.length,
|
|
27539
|
+
references: selected,
|
|
27540
|
+
decision: status === "matched" ? "Inspect the cited source paths and reuse or adapt the reference; honor its do-not-copy guardrails." : status === "available_unmatched" ? "Saved references exist, but none match this task; search the reference library before creating a new pattern." : "No saved reference matches this task; prove the new pattern before saving it for reuse."
|
|
27541
|
+
};
|
|
27542
|
+
}
|
|
27543
|
+
function referenceQueryTerms(input) {
|
|
27544
|
+
const ignored = /* @__PURE__ */ new Set([
|
|
27545
|
+
"after",
|
|
27546
|
+
"before",
|
|
27547
|
+
"create",
|
|
27548
|
+
"existing",
|
|
27549
|
+
"make",
|
|
27550
|
+
"new",
|
|
27551
|
+
"reuse",
|
|
27552
|
+
"task",
|
|
27553
|
+
"the",
|
|
27554
|
+
"this",
|
|
27555
|
+
"with"
|
|
27556
|
+
]);
|
|
27557
|
+
return unique(input.toLowerCase().split(/[^a-z0-9]+/).filter((term) => term.length >= 4 && !ignored.has(term)));
|
|
27558
|
+
}
|
|
27315
27559
|
function testRecommendationMatchesWorkspace(recommendation, targetFiles) {
|
|
27316
27560
|
const scopes = unique(targetFiles.map(workspaceScopeForFile).filter(Boolean));
|
|
27317
27561
|
if (scopes.length === 0)
|
|
@@ -27344,7 +27588,13 @@ function cockpitFor(input) {
|
|
|
27344
27588
|
...input.inspectFirst[0] ? [`Inspect ${input.inspectFirst[0].path}.`] : ["Narrow the task until Brief can name an inspect-first file."],
|
|
27345
27589
|
...input.reuseCandidates[0] ? [`Reuse or rule out ${input.reuseCandidates[0].path}.`] : ["Search once more before creating a new primitive."]
|
|
27346
27590
|
]).slice(0, 4);
|
|
27347
|
-
const
|
|
27591
|
+
const sharedMemory = input.teamGuidance?.applied.slice(0, 2).map((item) => `Shared ${item.kind}: ${item.label}`) ?? [];
|
|
27592
|
+
const productMemory = unique([
|
|
27593
|
+
...sharedMemory,
|
|
27594
|
+
...input.referenceFirst.status === "matched" ? input.referenceFirst.references.slice(0, 1).map((reference) => `Saved reference: ${reference.title}`) : input.referenceFirst.status === "available_unmatched" ? ["Saved references exist, but none match this task yet."] : [],
|
|
27595
|
+
...input.teamGuidance?.status === "available_not_applied" ? ["Shared guidance is available, but none matched this task yet."] : [],
|
|
27596
|
+
...input.productOperatingContext.status === "not_applicable" ? [] : input.productOperatingContext.productMemoryCandidates
|
|
27597
|
+
]).slice(0, 3);
|
|
27348
27598
|
const reuseDecision = input.reuseCandidates.slice(0, 3).map((candidate) => `${candidate.path} - ${candidate.action}`);
|
|
27349
27599
|
const validation = unique([
|
|
27350
27600
|
...input.likelyTests.slice(0, mode === "mission" ? 3 : 2),
|
|
@@ -27484,7 +27734,7 @@ function inspectFilesFor(nodes, contextMap, task) {
|
|
|
27484
27734
|
})).filter(({ intentScore }) => intentScore > -100);
|
|
27485
27735
|
const seen = /* @__PURE__ */ new Set();
|
|
27486
27736
|
const candidates = [...fromNodes, ...fromContext];
|
|
27487
|
-
const focusedCandidates = candidates.filter((item) => item.intentScore > 0);
|
|
27737
|
+
const focusedCandidates = candidates.filter((item) => item.intentScore > 0 || item.evidenceKinds.some((kind) => ["rule_reference", "guidance_reference"].includes(kind)));
|
|
27488
27738
|
const ranked = (focusedCandidates.length >= 3 ? focusedCandidates : candidates).sort((a, b) => b.intentScore - a.intentScore || b.originPriority - a.originPriority || a.index - b.index).filter((item) => {
|
|
27489
27739
|
const sourcePath = item.path.split("#", 1)[0] ?? item.path;
|
|
27490
27740
|
if (seen.has(sourcePath))
|
|
@@ -27609,7 +27859,7 @@ function beforeYouCodePathIntentScore(path20, task) {
|
|
|
27609
27859
|
const wantsBilling = /\b(bill(?:ing)?|checkout|paid|payment|price|pricing|stripe|subscription)\b/.test(lowerTask);
|
|
27610
27860
|
const wantsWorkspaceBootstrap = /\b(onboarding|workspace creation|workspace bootstrap)\b/.test(lowerTask);
|
|
27611
27861
|
const wantsConnector = /\b(agent action|connector|first useful|mcp|setup)\b/.test(lowerTask);
|
|
27612
|
-
const wantsTeam = /\b(invite|member|team)\b/.test(lowerTask);
|
|
27862
|
+
const wantsTeam = /\b(invite|member|team (?:member|access|setup|management)|workspace team)\b/.test(lowerTask);
|
|
27613
27863
|
const wantsAutoEngagement = /\b(auto[- ]?engage|automatically|by default|default engagement|reminder)\b/.test(lowerTask);
|
|
27614
27864
|
const wantsRecommendations = /\b(context|recommendations?|reuse|tests?|test guidance|test recommendations?)\b/.test(lowerTask);
|
|
27615
27865
|
if (wantsInterface && wantsLanding && /(landinginteractive|landing-page|src\/app\/page\.[cm]?[tj]sx?$)/.test(lowerPath)) {
|
|
@@ -27868,10 +28118,20 @@ function compactTextFor2(input) {
|
|
|
27868
28118
|
`Target: ${input.target.repoName} | ${input.target.branch ?? "branch unknown"} | ${input.target.repoRoot}`,
|
|
27869
28119
|
`Worktree: ${input.target.dirty ? "dirty" : "clean"}${input.target.changedFiles.length ? `; changed ${input.target.changedFiles.slice(0, 4).join(", ")}` : ""}${input.target.untrackedFiles.length ? `; untracked ${input.target.untrackedFiles.slice(0, 3).join(", ")}` : ""}`,
|
|
27870
28120
|
...input.target.requestedFiles.length ? [`Scope files: ${input.target.requestedFiles.slice(0, 5).join(", ")}`] : [],
|
|
28121
|
+
...input.teamGuidance ? [
|
|
28122
|
+
`Shared guidance: ${input.teamGuidance.applied.length > 0 ? input.teamGuidance.applied.slice(0, 2).map((item) => item.label).join(", ") : input.teamGuidance.status === "available_not_applied" ? "available, but none matched this task" : "none approved yet"}`
|
|
28123
|
+
] : [],
|
|
28124
|
+
...input.referenceFirst.status === "matched" ? [
|
|
28125
|
+
`Saved reference: ${input.referenceFirst.references.slice(0, 2).map((reference) => reference.title).join(", ")}`
|
|
28126
|
+
] : input.referenceFirst.status === "available_unmatched" ? [
|
|
28127
|
+
"Saved references exist, but none match this task; search before creating."
|
|
28128
|
+
] : [],
|
|
27871
28129
|
"Inspect first:",
|
|
27872
28130
|
...itemLines2(input.inspectFirst, (item) => `${item.path} - ${item.why}`, "No focused files yet; narrow the request.", 5),
|
|
27873
28131
|
"Reuse before create:",
|
|
27874
28132
|
...itemLines2(input.reuseCandidates, (item) => `${item.path} - ${item.action}`, "No reuse candidates yet; run a narrower codebase_map query.", 4),
|
|
28133
|
+
"Reuse decision: reuse, adapt, or rule out each candidate before creating a new primitive.",
|
|
28134
|
+
`Reference decision: ${input.referenceFirst.decision}`,
|
|
27875
28135
|
...input.productOperatingContext.status === "not_applicable" ? [] : [
|
|
27876
28136
|
"Product guardrails:",
|
|
27877
28137
|
...itemLines2(input.productOperatingContext.productRules, (item) => item.rule, "No product rules found; capture acceptance criteria before editing.", 3),
|
|
@@ -27899,6 +28159,7 @@ var init_agentBeforeYouCode = __esm({
|
|
|
27899
28159
|
init_productOperatingContext();
|
|
27900
28160
|
init_pathIntent();
|
|
27901
28161
|
init_testRecommendations();
|
|
28162
|
+
init_localReferenceImplementations();
|
|
27902
28163
|
init_utils();
|
|
27903
28164
|
}
|
|
27904
28165
|
});
|
|
@@ -28759,7 +29020,16 @@ function collectFindings(input) {
|
|
|
28759
29020
|
findings.push(...bugBarFindings(input.diff, input.changedFiles));
|
|
28760
29021
|
}
|
|
28761
29022
|
if (input.policy.enabledGates.includes("tests")) {
|
|
28762
|
-
|
|
29023
|
+
const behaviorChangeInput = {
|
|
29024
|
+
changedFiles: input.changedFiles,
|
|
29025
|
+
diff: input.diff,
|
|
29026
|
+
suggestedTests: input.context.suggestedTests
|
|
29027
|
+
};
|
|
29028
|
+
if (input.validationEvidence) {
|
|
29029
|
+
behaviorChangeInput.validationEvidence = input.validationEvidence;
|
|
29030
|
+
}
|
|
29031
|
+
const behaviorFindings = behaviorChangeFindings(behaviorChangeInput);
|
|
29032
|
+
findings.push(...behaviorFindings.length > 0 ? [] : missingTestFindings(input.changedFiles, input.context.suggestedTests, input.validationEvidence), ...behaviorFindings);
|
|
28763
29033
|
}
|
|
28764
29034
|
if (input.policy.enabledGates.includes("runtime_evidence")) {
|
|
28765
29035
|
const runtimeEvidenceInput = {
|
|
@@ -29767,6 +30037,50 @@ function missingTestFindings(changedFiles, suggestedTests, validationEvidence) {
|
|
|
29767
30037
|
}
|
|
29768
30038
|
];
|
|
29769
30039
|
}
|
|
30040
|
+
function behaviorChangeFindings(input) {
|
|
30041
|
+
const changedTestFiles = input.changedFiles.filter(isTestLikePath);
|
|
30042
|
+
if (changedTestFiles.length > 0)
|
|
30043
|
+
return [];
|
|
30044
|
+
const hits = addedLinesMatching(input.diff, /(?:\b(?:router\.(?:get|post|put|patch|delete|use)|app\.(?:get|post|put|patch|delete|use)|registerTool|publicProcedure|protectedProcedure|zaniaInternalProcedure|fetch|sendEmail|enqueue|publish|writeFile(?:Sync)?|requireAuth|authorize|permission|featureFlag|process\.env\.[A-Z0-9_]+)\b|\b(?:insert|update|delete|upsert)\s*\()/i).filter((hit) => !isTestLikePath(hit.file));
|
|
30045
|
+
if (hits.length === 0)
|
|
30046
|
+
return [];
|
|
30047
|
+
const proofTargets = input.suggestedTests.slice(0, 8);
|
|
30048
|
+
if (validationEvidenceCoversSuggestedTests(input.validationEvidence, proofTargets)) {
|
|
30049
|
+
return [];
|
|
30050
|
+
}
|
|
30051
|
+
const behaviorKinds = unique(hits.flatMap((hit) => behaviorKindForLine(hit.line))).slice(0, 5);
|
|
30052
|
+
const files = unique(hits.map((hit) => hit.file));
|
|
30053
|
+
return [
|
|
30054
|
+
{
|
|
30055
|
+
id: idFor("finding", `behavior-change:${locationsKey(hits)}:${behaviorKinds.join(",")}`),
|
|
30056
|
+
gateId: "tests",
|
|
30057
|
+
severity: "medium",
|
|
30058
|
+
title: `Behavior change: ${behaviorKinds.join(", ")} needs focused proof`,
|
|
30059
|
+
body: [
|
|
30060
|
+
`Brief found added ${behaviorKinds.join(", ")} signals in ${files.join(", ")}. This is more than a structural edit: it can change a user path, data write, access boundary, external side effect, or agent contract.`,
|
|
30061
|
+
proofTargets.length > 0 ? `Run the nearest mapped proof first: ${proofTargets.join(", ")}.` : "Add the nearest page, route, persistence, auth, or integration proof before handoff.",
|
|
30062
|
+
"A broad typecheck alone does not prove this behavior stayed correct."
|
|
30063
|
+
].join(" "),
|
|
30064
|
+
files,
|
|
30065
|
+
ruleIds: [],
|
|
30066
|
+
suggestedTests: proofTargets
|
|
30067
|
+
}
|
|
30068
|
+
];
|
|
30069
|
+
}
|
|
30070
|
+
function behaviorKindForLine(line) {
|
|
30071
|
+
const kinds = [];
|
|
30072
|
+
if (/\b(?:router\.|app\.|registerTool|publicProcedure|protectedProcedure|zaniaInternalProcedure)\b/i.test(line))
|
|
30073
|
+
kinds.push("route or agent contract");
|
|
30074
|
+
if (/\b(?:insert|update|delete|upsert)\s*\(/i.test(line))
|
|
30075
|
+
kinds.push("persistence");
|
|
30076
|
+
if (/\b(?:requireAuth|authorize|permission|process\.env\.)\b/i.test(line))
|
|
30077
|
+
kinds.push("access or configuration");
|
|
30078
|
+
if (/\b(?:fetch|sendEmail|enqueue|publish|writeFile)\b/i.test(line))
|
|
30079
|
+
kinds.push("external side effect");
|
|
30080
|
+
if (/\bfeatureFlag\b/i.test(line))
|
|
30081
|
+
kinds.push("feature flag");
|
|
30082
|
+
return kinds.length > 0 ? kinds : ["runtime behavior"];
|
|
30083
|
+
}
|
|
29770
30084
|
function validationEvidenceCoversSuggestedTests(validationEvidence, suggestedTests) {
|
|
29771
30085
|
const passedCommands = (validationEvidence ?? []).filter((item) => item.status === "passed").map((item) => item.command.toLowerCase());
|
|
29772
30086
|
if (passedCommands.length === 0)
|
|
@@ -34644,7 +34958,7 @@ var init_installStatus = __esm({
|
|
|
34644
34958
|
"../mcp/src/installStatus.ts"() {
|
|
34645
34959
|
"use strict";
|
|
34646
34960
|
init_serverInstructions();
|
|
34647
|
-
briefConnectorVersion = "0.1.
|
|
34961
|
+
briefConnectorVersion = "0.1.1";
|
|
34648
34962
|
}
|
|
34649
34963
|
});
|
|
34650
34964
|
|
|
@@ -34675,6 +34989,11 @@ function buildCompactStartEnvelope(input) {
|
|
|
34675
34989
|
path: item.path,
|
|
34676
34990
|
action: compactLine(item.action, 160)
|
|
34677
34991
|
})),
|
|
34992
|
+
reuseDecision: compactLine(beforeYouCode.reuseFirst.decision, 240),
|
|
34993
|
+
sharedContext: summarizeBeforeYouCodeSharedContext(
|
|
34994
|
+
beforeYouCode.teamGuidance
|
|
34995
|
+
),
|
|
34996
|
+
referenceFirst: summarizeBeforeYouCodeReferences(beforeYouCode),
|
|
34678
34997
|
validation: beforeYouCode.likelyTests.slice(0, 3),
|
|
34679
34998
|
result: input.result,
|
|
34680
34999
|
stopSignals: beforeYouCode.stopSignals.slice(0, 2),
|
|
@@ -34700,6 +35019,9 @@ function formatCompactStartText(envelope) {
|
|
|
34700
35019
|
),
|
|
34701
35020
|
"Reuse:",
|
|
34702
35021
|
...listLines(envelope.reuse.map((item) => `${item.path} - ${item.action}`)),
|
|
35022
|
+
`Reuse decision: ${envelope.reuseDecision}`,
|
|
35023
|
+
`Shared context: ${envelope.sharedContext.status === "applied" ? envelope.sharedContext.applied.map((item) => item.label).join(", ") : envelope.sharedContext.status}`,
|
|
35024
|
+
`Saved reference: ${envelope.referenceFirst.status === "matched" ? envelope.referenceFirst.references.map((reference) => reference.title).join(", ") : envelope.referenceFirst.status}`,
|
|
34703
35025
|
"Validate:",
|
|
34704
35026
|
...listLines(envelope.validation),
|
|
34705
35027
|
`Result: ${envelope.result.summary}`,
|
|
@@ -35142,7 +35464,7 @@ function renderWikiRefreshWorkflow(options2 = {}) {
|
|
|
35142
35464
|
" with:",
|
|
35143
35465
|
" node-version: 22",
|
|
35144
35466
|
" - name: Refresh wiki",
|
|
35145
|
-
' run: npx -y runbrief@0.1.
|
|
35467
|
+
' run: npx -y runbrief@0.1.1 wiki init --repo "$GITHUB_WORKSPACE" --update --no-agent-files',
|
|
35146
35468
|
" - name: Open refresh PR",
|
|
35147
35469
|
" uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7.0.11",
|
|
35148
35470
|
" with:",
|
|
@@ -35420,6 +35742,40 @@ var init_mapResponse = __esm({
|
|
|
35420
35742
|
}
|
|
35421
35743
|
});
|
|
35422
35744
|
|
|
35745
|
+
// ../mcp/src/scanFreshness.ts
|
|
35746
|
+
function scanFreshnessFor(repoRoot, scan) {
|
|
35747
|
+
const gitRoot = runGit(repoRoot, ["rev-parse", "--show-toplevel"]);
|
|
35748
|
+
const gitAvailable = Boolean(gitRoot);
|
|
35749
|
+
const branch = runGit(repoRoot, ["branch", "--show-current"]) || null;
|
|
35750
|
+
const commit = runGit(repoRoot, ["rev-parse", "HEAD"]) || null;
|
|
35751
|
+
const statusLines = (gitAvailable ? runGit(repoRoot, ["status", "--short"]) : "").split("\n").map((line) => line.trim()).filter(Boolean);
|
|
35752
|
+
return {
|
|
35753
|
+
status: !gitAvailable ? "git_unavailable" : scan.stats.mapPartial ? "partial_coverage" : statusLines.length > 0 ? "working_tree_changed" : "current_at_scan",
|
|
35754
|
+
git: {
|
|
35755
|
+
available: gitAvailable,
|
|
35756
|
+
detachedHead: gitAvailable && !branch
|
|
35757
|
+
},
|
|
35758
|
+
scannedAt: scan.scannedAt,
|
|
35759
|
+
branch,
|
|
35760
|
+
commit,
|
|
35761
|
+
changedPathCount: statusLines.length,
|
|
35762
|
+
changedPaths: statusLines.map((line) => line.replace(/^[ MADRCU?!]{1,3}\s+/, "")).slice(0, 24),
|
|
35763
|
+
mapCoverage: {
|
|
35764
|
+
nodes: scan.stats.mapNodeCount,
|
|
35765
|
+
candidates: scan.stats.mapTotalCandidateCount ?? scan.stats.mapNodeCount,
|
|
35766
|
+
omitted: scan.stats.mapOmittedCount ?? 0,
|
|
35767
|
+
partial: Boolean(scan.stats.mapPartial)
|
|
35768
|
+
},
|
|
35769
|
+
next: !gitAvailable ? "Git metadata is unavailable; verify the repo target before trusting map freshness." : statusLines.length > 0 ? "Rescan after the current edits settle; changed paths may invalidate reuse and wiki evidence." : scan.stats.mapPartial ? "Narrow the scan by area or raise maxFiles before treating the map as complete." : !branch ? "The map was generated from a detached commit and clean working tree; verify the intended branch before editing." : "The map was generated from the current commit and clean working tree."
|
|
35770
|
+
};
|
|
35771
|
+
}
|
|
35772
|
+
var init_scanFreshness = __esm({
|
|
35773
|
+
"../mcp/src/scanFreshness.ts"() {
|
|
35774
|
+
"use strict";
|
|
35775
|
+
init_dist2();
|
|
35776
|
+
}
|
|
35777
|
+
});
|
|
35778
|
+
|
|
35423
35779
|
// ../mcp/src/workflowWiringResponse.ts
|
|
35424
35780
|
function selectWorkflowWiringResponse(report, detail) {
|
|
35425
35781
|
return detail === "expanded" ? report : summarizeAgentWorkflowWiring(report);
|
|
@@ -35712,6 +36068,7 @@ function summarizePacket(packet) {
|
|
|
35712
36068
|
memories: packet.memories,
|
|
35713
36069
|
sources: packet.sources,
|
|
35714
36070
|
omitted: packet.omitted,
|
|
36071
|
+
...packet.valueSignals ? { valueSignals: packet.valueSignals } : {},
|
|
35715
36072
|
...packet.teamGuidance ? { teamGuidance: packet.teamGuidance } : {}
|
|
35716
36073
|
};
|
|
35717
36074
|
}
|
|
@@ -36147,8 +36504,13 @@ function summarizeBeforeYouCodeForStart(beforeYouCode) {
|
|
|
36147
36504
|
reuseFirst: {
|
|
36148
36505
|
status: beforeYouCode.reuseFirst.status,
|
|
36149
36506
|
summary: beforeYouCode.reuseFirst.summary,
|
|
36507
|
+
decision: beforeYouCode.reuseFirst.decision,
|
|
36150
36508
|
candidates: beforeYouCode.reuseFirst.candidates.slice(0, 2)
|
|
36151
36509
|
},
|
|
36510
|
+
sharedContext: summarizeBeforeYouCodeSharedContext(
|
|
36511
|
+
beforeYouCode.teamGuidance
|
|
36512
|
+
),
|
|
36513
|
+
referenceFirst: summarizeBeforeYouCodeReferences(beforeYouCode),
|
|
36152
36514
|
likelyTests: beforeYouCode.likelyTests.slice(0, 3),
|
|
36153
36515
|
productOperatingContext: {
|
|
36154
36516
|
status: beforeYouCode.productOperatingContext.status,
|
|
@@ -36307,10 +36669,11 @@ var init_server = __esm({
|
|
|
36307
36669
|
init_wikiInit();
|
|
36308
36670
|
init_workspace();
|
|
36309
36671
|
init_handoffAutofill();
|
|
36672
|
+
init_scanFreshness();
|
|
36310
36673
|
server = new McpServer(
|
|
36311
36674
|
{
|
|
36312
36675
|
name: "brief",
|
|
36313
|
-
version: "0.1.
|
|
36676
|
+
version: "0.1.1"
|
|
36314
36677
|
},
|
|
36315
36678
|
{
|
|
36316
36679
|
instructions: briefMcpInstructions
|
|
@@ -37115,6 +37478,7 @@ var init_server = __esm({
|
|
|
37115
37478
|
},
|
|
37116
37479
|
reuse: {
|
|
37117
37480
|
status: beforeYouCode.reuseFirst.status,
|
|
37481
|
+
decision: beforeYouCode.reuseFirst.decision,
|
|
37118
37482
|
candidates: beforeYouCode.reuseFirst.candidates.slice(0, 3).map(({ path: candidatePath, action, why }) => ({
|
|
37119
37483
|
path: candidatePath,
|
|
37120
37484
|
action,
|
|
@@ -37126,6 +37490,17 @@ var init_server = __esm({
|
|
|
37126
37490
|
status: beforeYouCode.productOperatingContext.status,
|
|
37127
37491
|
taskClasses: beforeYouCode.productOperatingContext.taskClasses
|
|
37128
37492
|
},
|
|
37493
|
+
autoEngage: {
|
|
37494
|
+
status: "active",
|
|
37495
|
+
firstCall: "brief.next",
|
|
37496
|
+
beforeEditing: "brief.before_you_code or brief.start",
|
|
37497
|
+
beforeHandoff: "brief.review_diff",
|
|
37498
|
+
finalRecap: "one or two truthful lines; no receipt dump"
|
|
37499
|
+
},
|
|
37500
|
+
sharedContext: summarizeBeforeYouCodeSharedContext(
|
|
37501
|
+
beforeYouCode.teamGuidance
|
|
37502
|
+
),
|
|
37503
|
+
referenceFirst: summarizeBeforeYouCodeReferences(beforeYouCode),
|
|
37129
37504
|
...learnedWorkflow ? {
|
|
37130
37505
|
learnedWorkflow: {
|
|
37131
37506
|
name: learnedWorkflow.name,
|
|
@@ -37133,7 +37508,12 @@ var init_server = __esm({
|
|
|
37133
37508
|
preservedGates: learnedWorkflow.preservedGates
|
|
37134
37509
|
}
|
|
37135
37510
|
} : {},
|
|
37136
|
-
teamContext: {
|
|
37511
|
+
teamContext: {
|
|
37512
|
+
status: teamContext.status,
|
|
37513
|
+
sharedContext: summarizeBeforeYouCodeSharedContext(
|
|
37514
|
+
beforeYouCode.teamGuidance
|
|
37515
|
+
)
|
|
37516
|
+
},
|
|
37137
37517
|
detailHint: 'Call brief.next again with detail: "expanded" only for expanded proof and workflow diagnostics.',
|
|
37138
37518
|
next: fullResponse.next
|
|
37139
37519
|
});
|
|
@@ -37594,6 +37974,7 @@ var init_server = __esm({
|
|
|
37594
37974
|
const cloudSync = await syncScanSummary(scan, repoRoot);
|
|
37595
37975
|
return jsonText({
|
|
37596
37976
|
...summarizeScan(scan),
|
|
37977
|
+
scanFreshness: scanFreshnessFor(repoRoot, scan),
|
|
37597
37978
|
rootResolution,
|
|
37598
37979
|
repoTarget,
|
|
37599
37980
|
cloudSync
|
|
@@ -39036,6 +39417,7 @@ init_startSummary();
|
|
|
39036
39417
|
init_wikiInit();
|
|
39037
39418
|
init_handoffAutofill();
|
|
39038
39419
|
init_mapResponse();
|
|
39420
|
+
init_scanFreshness();
|
|
39039
39421
|
import { chmodSync as chmodSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync7 } from "node:fs";
|
|
39040
39422
|
import path19 from "node:path";
|
|
39041
39423
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
@@ -39239,6 +39621,7 @@ async function runCli(commandName, commandArgs) {
|
|
|
39239
39621
|
repoTarget,
|
|
39240
39622
|
scannedAt: scan.scannedAt,
|
|
39241
39623
|
stats: scan.stats,
|
|
39624
|
+
scanFreshness: scanFreshnessFor(repoRoot, scan),
|
|
39242
39625
|
cloudSync,
|
|
39243
39626
|
webAppStatus: webAppStatusForScan(cloudSync),
|
|
39244
39627
|
next: nextScanStep(cloudSync)
|
|
@@ -39325,6 +39708,7 @@ async function runCli(commandName, commandArgs) {
|
|
|
39325
39708
|
},
|
|
39326
39709
|
reuse: {
|
|
39327
39710
|
status: beforeYouCode.reuseFirst.status,
|
|
39711
|
+
decision: beforeYouCode.reuseFirst.decision,
|
|
39328
39712
|
candidates: beforeYouCode.reuseFirst.candidates.slice(0, 3).map(({ path: candidatePath, action, why }) => ({
|
|
39329
39713
|
path: candidatePath,
|
|
39330
39714
|
action,
|
|
@@ -39336,6 +39720,15 @@ async function runCli(commandName, commandArgs) {
|
|
|
39336
39720
|
status: beforeYouCode.productOperatingContext.status,
|
|
39337
39721
|
taskClasses: beforeYouCode.productOperatingContext.taskClasses
|
|
39338
39722
|
},
|
|
39723
|
+
sharedContext: summarizeBeforeYouCodeSharedContext(
|
|
39724
|
+
beforeYouCode.teamGuidance
|
|
39725
|
+
),
|
|
39726
|
+
autoEngage: {
|
|
39727
|
+
status: autoEngage.status,
|
|
39728
|
+
chatFeedback: autoEngage.chatFeedback.slice(0, 1),
|
|
39729
|
+
finalRecapPolicy: autoEngage.finalRecapPolicy
|
|
39730
|
+
},
|
|
39731
|
+
referenceFirst: summarizeBeforeYouCodeReferences(beforeYouCode),
|
|
39339
39732
|
...learnedWorkflow ? {
|
|
39340
39733
|
learnedWorkflow: {
|
|
39341
39734
|
name: learnedWorkflow.name,
|
|
@@ -39343,7 +39736,12 @@ async function runCli(commandName, commandArgs) {
|
|
|
39343
39736
|
preservedGates: learnedWorkflow.preservedGates
|
|
39344
39737
|
}
|
|
39345
39738
|
} : {},
|
|
39346
|
-
teamContext: {
|
|
39739
|
+
teamContext: {
|
|
39740
|
+
status: teamContext.status,
|
|
39741
|
+
sharedContext: summarizeBeforeYouCodeSharedContext(
|
|
39742
|
+
beforeYouCode.teamGuidance
|
|
39743
|
+
)
|
|
39744
|
+
},
|
|
39347
39745
|
detailHint: "Run the same command with --full for expanded proof and workflow diagnostics.",
|
|
39348
39746
|
next: fullResponse.next
|
|
39349
39747
|
}
|
|
@@ -39803,6 +40201,10 @@ async function runCli(commandName, commandArgs) {
|
|
|
39803
40201
|
repoTarget,
|
|
39804
40202
|
cockpit: beforeYouCode.cockpit,
|
|
39805
40203
|
beforeYouCode: summarizeBeforeYouCodeForCli(beforeYouCode),
|
|
40204
|
+
sharedContext: summarizeBeforeYouCodeSharedContext(
|
|
40205
|
+
beforeYouCode.teamGuidance
|
|
40206
|
+
),
|
|
40207
|
+
referenceFirst: summarizeBeforeYouCodeReferences(beforeYouCode),
|
|
39806
40208
|
teamContext: summarizeTeamContext(teamContext),
|
|
39807
40209
|
next: "Read cockpit.compactText first. For micro/small passes, stay lightweight unless scope grows; for medium/large passes, call brief.start or mission_plan before editing."
|
|
39808
40210
|
});
|
|
@@ -40299,7 +40701,7 @@ async function runCli(commandName, commandArgs) {
|
|
|
40299
40701
|
});
|
|
40300
40702
|
return;
|
|
40301
40703
|
}
|
|
40302
|
-
if (isCommand(commandName, "review-diff", "review_diff")) {
|
|
40704
|
+
if (isCommand(commandName, "review-diff", "review", "review_diff")) {
|
|
40303
40705
|
const baseRef = option2(commandArgs, "base");
|
|
40304
40706
|
const task = option2(commandArgs, "task");
|
|
40305
40707
|
const files = filesOption2(commandArgs);
|
|
@@ -40961,7 +41363,7 @@ function cliCommandHelp() {
|
|
|
40961
41363
|
},
|
|
40962
41364
|
{
|
|
40963
41365
|
command: "review-diff",
|
|
40964
|
-
aliases: ["review_diff"],
|
|
41366
|
+
aliases: ["review", "review_diff"],
|
|
40965
41367
|
purpose: "Review the current diff for bugs, missing tests, reuse gaps, trust boundaries, design adherence, and proof.",
|
|
40966
41368
|
repoBound: true,
|
|
40967
41369
|
usage: 'brief review-diff --repo /path/to/repo --base main --task "Prepare PR" --json',
|
|
@@ -41686,6 +42088,7 @@ function printContextSummary(packet, localReceipt, teamContext) {
|
|
|
41686
42088
|
`Sources: ${packet.sources.length}`,
|
|
41687
42089
|
teamContextLine(teamContext),
|
|
41688
42090
|
teamGuidanceLine(packet),
|
|
42091
|
+
valueSignalLine(packet),
|
|
41689
42092
|
"",
|
|
41690
42093
|
"Rules:",
|
|
41691
42094
|
...packet.rules.length > 0 ? packet.rules.slice(0, 8).map((rule) => `- [${rule.enforcement}] ${rule.title}`) : ["- none"],
|
|
@@ -41730,6 +42133,11 @@ function teamGuidanceLine(packet) {
|
|
|
41730
42133
|
if (!delivery) return "Team guidance applied: not connected";
|
|
41731
42134
|
return `Team guidance applied: ${delivery.applied.length}/${delivery.availableCount} approved items (${delivery.revision})`;
|
|
41732
42135
|
}
|
|
42136
|
+
function valueSignalLine(packet) {
|
|
42137
|
+
const signals = packet.valueSignals;
|
|
42138
|
+
if (!signals) return "Value signals: not available";
|
|
42139
|
+
return `Value signals: ${signals.relevantSourceCount} relevant sources, ${signals.reusablePrimitiveCount} reusable primitives, ${signals.parserBackedEntityCount} parser-backed entities, ${signals.appliedTeamGuidanceCount} team guidance items, ${signals.suggestedTestCount} test targets`;
|
|
42140
|
+
}
|
|
41733
42141
|
function writeHookFiles2(repoRoot, files) {
|
|
41734
42142
|
const written = [];
|
|
41735
42143
|
for (const file of files) {
|
|
@@ -41773,8 +42181,13 @@ function summarizeBeforeYouCodeForCli(beforeYouCode) {
|
|
|
41773
42181
|
reuseFirst: {
|
|
41774
42182
|
status: beforeYouCode.reuseFirst.status,
|
|
41775
42183
|
summary: beforeYouCode.reuseFirst.summary,
|
|
42184
|
+
decision: beforeYouCode.reuseFirst.decision,
|
|
41776
42185
|
candidates: beforeYouCode.reuseFirst.candidates.slice(0, 2)
|
|
41777
42186
|
},
|
|
42187
|
+
sharedContext: summarizeBeforeYouCodeSharedContext(
|
|
42188
|
+
beforeYouCode.teamGuidance
|
|
42189
|
+
),
|
|
42190
|
+
referenceFirst: summarizeBeforeYouCodeReferences(beforeYouCode),
|
|
41778
42191
|
likelyTests: beforeYouCode.likelyTests.slice(0, 3),
|
|
41779
42192
|
productOperatingContext: {
|
|
41780
42193
|
status: beforeYouCode.productOperatingContext.status,
|