@minhpnq1807/contextos 0.5.38 → 0.5.39
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/CHANGELOG.md +8 -0
- package/package.json +1 -1
- package/plugins/ctx/lib/reporter.js +87 -65
- package/plugins/ctx/lib/stop-hook.js +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.39
|
|
4
|
+
|
|
5
|
+
- **Report layout fix:** Replaced ASCII table formatting with clean markdown output. Reports now render correctly in all agent UIs (Antigravity, Claude Code, Codex) without truncation or line-wrapping issues.
|
|
6
|
+
- **Skills & workflows in report:** `Suggested Skills` and `Suggested Workflows` sections now appear in the compliance report when available. Data is passed through from `stop-hook.js` → `buildReport()` → `formatReport()`.
|
|
7
|
+
- **No more truncation:** All rules now display in the report — removed the artificial item limits that caused `... N more` messages.
|
|
8
|
+
- **Emoji status indicators:** Rule outcomes use ✅/❌/❓/⚠️ prefixes for quick scanning.
|
|
9
|
+
|
|
10
|
+
|
|
3
11
|
## 0.5.38
|
|
4
12
|
|
|
5
13
|
- **Unified agent branding:** All user-facing text now shows `antigravity` instead of `agy`. Internal value remains `agy` for backward compatibility. Interactive prompts display "Antigravity" without the parenthetical alias.
|
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { isSystemUserRule } from "./analyzer.js";
|
|
2
|
-
import { section, table, truncateCell } from "./terminal-ui.js";
|
|
3
2
|
|
|
4
|
-
export function buildReport({ cwd, prompt, relevantFiles, scheduled, gitSnapshot, compliance, runtimeEvidence }) {
|
|
3
|
+
export function buildReport({ cwd, prompt, relevantFiles, suggestedSkills, suggestedWorkflows, scheduled, gitSnapshot, compliance, runtimeEvidence }) {
|
|
5
4
|
const actionableCompliance = compliance.filter((item) => !isSystemUserRule(item.rule));
|
|
6
5
|
const followed = actionableCompliance.filter((item) => item.status === "followed");
|
|
7
6
|
const ignored = actionableCompliance.filter((item) => item.status === "ignored");
|
|
@@ -16,6 +15,8 @@ export function buildReport({ cwd, prompt, relevantFiles, scheduled, gitSnapshot
|
|
|
16
15
|
prompt,
|
|
17
16
|
injectedRuleCount: (scheduled?.highRules?.length || 0) + (scheduled?.midRules?.length || 0),
|
|
18
17
|
relevantFiles,
|
|
18
|
+
suggestedSkills: suggestedSkills || [],
|
|
19
|
+
suggestedWorkflows: suggestedWorkflows || [],
|
|
19
20
|
changedFiles: gitSnapshot.changedFiles,
|
|
20
21
|
warnings: gitSnapshot.warnings || [],
|
|
21
22
|
runtimeEvidence: summarizeRuntimeEvidence(runtimeEvidence),
|
|
@@ -33,47 +34,77 @@ export function buildReport({ cwd, prompt, relevantFiles, scheduled, gitSnapshot
|
|
|
33
34
|
export function formatReport(report) {
|
|
34
35
|
report = sanitizeReport(report);
|
|
35
36
|
const lines = [];
|
|
36
|
-
lines.push("ContextOS
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
37
|
+
lines.push("# ContextOS Report\n");
|
|
38
|
+
|
|
39
|
+
// Summary
|
|
40
|
+
lines.push("## Summary");
|
|
41
|
+
lines.push(`- **Efficiency:** ${report.efficiencyScore == null ? "unknown" : `${report.efficiencyScore}%`}`);
|
|
42
|
+
lines.push(`- **Injected rules:** ${report.injectedRuleCount || 0}`);
|
|
43
|
+
lines.push(`- **Measured rules:** ${report.measuredRuleCount ?? ((report.followed?.length || 0) + (report.ignored?.length || 0))}`);
|
|
44
|
+
lines.push(`- **Changed files:** ${report.changedFiles?.length ? report.changedFiles.length : "none detected"}`);
|
|
45
|
+
lines.push("");
|
|
46
|
+
|
|
47
|
+
// Rule Outcomes
|
|
48
|
+
lines.push("## Rule Outcomes");
|
|
49
|
+
lines.push(`- ✅ Followed: ${report.followed?.length || 0}`);
|
|
50
|
+
lines.push(`- ❌ Ignored: ${report.ignored?.length || 0}`);
|
|
51
|
+
lines.push(`- ❓ Unknown: ${report.unknown?.length || 0}`);
|
|
52
|
+
lines.push(`- ⚠️ Unmeasurable: ${report.unmeasurable?.length || 0}`);
|
|
53
|
+
lines.push("");
|
|
54
|
+
|
|
55
|
+
// Suggested Files
|
|
53
56
|
if (report.relevantFiles?.length) {
|
|
54
|
-
lines.push(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
lines.push("## Suggested Files");
|
|
58
|
+
for (const [index, file] of report.relevantFiles.entries()) {
|
|
59
|
+
const score = typeof file.score === "number" ? ` (${file.score.toFixed(2)})` : "";
|
|
60
|
+
lines.push(`${index + 1}. ${file.path}${score}`);
|
|
61
|
+
}
|
|
62
|
+
lines.push("");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Suggested Skills
|
|
66
|
+
if (report.suggestedSkills?.length) {
|
|
67
|
+
lines.push("## Suggested Skills");
|
|
68
|
+
for (const skill of report.suggestedSkills) {
|
|
69
|
+
const desc = skill.description ? `: ${truncate(skill.description, 80)}` : "";
|
|
70
|
+
lines.push(`- **${skill.name}**${desc}`);
|
|
71
|
+
}
|
|
72
|
+
lines.push("");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Suggested Workflows
|
|
76
|
+
if (report.suggestedWorkflows?.length) {
|
|
77
|
+
lines.push("## Suggested Workflows");
|
|
78
|
+
for (const workflow of report.suggestedWorkflows) {
|
|
79
|
+
const name = workflow.title || workflow.name;
|
|
80
|
+
const chain = workflow.chain?.length ? ` → ${workflow.chain.join(" → ")}` : "";
|
|
81
|
+
lines.push(`- **${name}**${chain}`);
|
|
82
|
+
}
|
|
83
|
+
lines.push("");
|
|
60
84
|
}
|
|
85
|
+
|
|
86
|
+
// Runtime Telemetry
|
|
61
87
|
if (report.runtimeEvidence?.signals?.length) {
|
|
62
|
-
lines.push(
|
|
63
|
-
|
|
88
|
+
lines.push("## Runtime Telemetry");
|
|
89
|
+
for (const signal of report.runtimeEvidence.signals) {
|
|
90
|
+
lines.push(`- ${signal}`);
|
|
91
|
+
}
|
|
92
|
+
lines.push("");
|
|
64
93
|
}
|
|
65
94
|
|
|
66
|
-
|
|
95
|
+
// Warnings
|
|
96
|
+
for (const warning of report.warnings || []) lines.push(`> ⚠️ ${warning}\n`);
|
|
67
97
|
|
|
98
|
+
// Rule details
|
|
68
99
|
appendBucket(lines, "Followed", report.followed);
|
|
69
100
|
appendBucket(lines, "Ignored", report.ignored);
|
|
70
101
|
appendBucket(lines, "Unknown", report.unknown);
|
|
71
102
|
appendBucket(lines, "Unmeasurable", report.unmeasurable);
|
|
72
103
|
|
|
73
104
|
if (report.ignored?.length) {
|
|
74
|
-
lines.push(
|
|
105
|
+
lines.push(`> **Suggestion:** Fix ignored rule evidence first: ${truncate(report.ignored[0].rule?.content || "", 70)}`);
|
|
75
106
|
} else if (report.unknown?.length && !(report.followed?.length || report.ignored?.length)) {
|
|
76
|
-
lines.push("Suggestion
|
|
107
|
+
lines.push("> **Suggestion:** These rules need runtime evidence or more concrete keywords before ContextOS can score them from git diff.");
|
|
77
108
|
}
|
|
78
109
|
|
|
79
110
|
return lines.join("\n");
|
|
@@ -82,15 +113,15 @@ export function formatReport(report) {
|
|
|
82
113
|
export function formatEvidence(report) {
|
|
83
114
|
report = sanitizeReport(report);
|
|
84
115
|
const lines = [];
|
|
85
|
-
lines.push("ContextOS
|
|
86
|
-
|
|
87
|
-
lines.push(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
116
|
+
lines.push("# ContextOS Evidence\n");
|
|
117
|
+
|
|
118
|
+
lines.push("## Summary");
|
|
119
|
+
lines.push(`- **Prompt:** ${truncate(report.prompt || "(empty)", 100)}`);
|
|
120
|
+
lines.push(`- **Efficiency:** ${report.efficiencyScore == null ? "unknown" : `${report.efficiencyScore}%`}`);
|
|
121
|
+
lines.push(`- **Changed files:** ${report.changedFiles?.length ? report.changedFiles.join(", ") : "none detected"}`);
|
|
122
|
+
lines.push("");
|
|
92
123
|
|
|
93
|
-
for (const warning of report.warnings || []) lines.push(
|
|
124
|
+
for (const warning of report.warnings || []) lines.push(`> ⚠️ ${warning}\n`);
|
|
94
125
|
|
|
95
126
|
const items = [
|
|
96
127
|
...(report.followed || []).map((item) => ({ ...item, status: "followed" })),
|
|
@@ -105,43 +136,34 @@ export function formatEvidence(report) {
|
|
|
105
136
|
return lines.join("\n");
|
|
106
137
|
}
|
|
107
138
|
|
|
108
|
-
lines.push(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
item.status.toUpperCase()
|
|
112
|
-
|
|
113
|
-
item.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
items.forEach((item, index) => {
|
|
119
|
-
lines.push(section(`${index + 1}. ${item.status.toUpperCase()}`));
|
|
120
|
-
lines.push(table(["Field", "Value"], [
|
|
121
|
-
["Rule", truncateCell(item.rule?.content || "(missing rule)", 120)],
|
|
122
|
-
["Source", item.rule?.sourcePath || ""],
|
|
123
|
-
["Score", typeof item.rule?.score === "number" ? item.rule.score.toFixed(2) : ""],
|
|
124
|
-
["Kind", item.kind || ""],
|
|
125
|
-
["Keywords", item.keywords?.length ? truncateCell(item.keywords.join(", "), 120) : ""],
|
|
126
|
-
["Evidence", truncateCell(item.evidence || "(none)", 120)]
|
|
127
|
-
].filter(([, value]) => value !== "")));
|
|
139
|
+
lines.push("## Evidence Details\n");
|
|
140
|
+
for (const [index, item] of items.entries()) {
|
|
141
|
+
const statusIcon = { followed: "✅", ignored: "❌", unknown: "❓", unmeasurable: "⚠️" }[item.status] || "";
|
|
142
|
+
lines.push(`### ${index + 1}. ${statusIcon} ${item.status.toUpperCase()}`);
|
|
143
|
+
lines.push(`- **Rule:** ${truncate(item.rule?.content || "(missing rule)", 120)}`);
|
|
144
|
+
if (item.rule?.sourcePath) lines.push(`- **Source:** ${item.rule.sourcePath}`);
|
|
145
|
+
if (typeof item.rule?.score === "number") lines.push(`- **Score:** ${item.rule.score.toFixed(2)}`);
|
|
146
|
+
if (item.kind) lines.push(`- **Kind:** ${item.kind}`);
|
|
147
|
+
lines.push(`- **Evidence:** ${truncate(item.evidence || "(none)", 120)}`);
|
|
128
148
|
for (const line of item.matchedLines || []) {
|
|
129
149
|
const where = line.file ? `${line.file}${typeof line.line === "number" ? `:${line.line}` : ""}` : "diff";
|
|
130
|
-
lines.push(`
|
|
150
|
+
lines.push(` - Match: \`${where}\` ${truncate(line.content || "", 100)}`);
|
|
131
151
|
}
|
|
132
|
-
|
|
152
|
+
lines.push("");
|
|
153
|
+
}
|
|
133
154
|
|
|
134
155
|
return lines.join("\n");
|
|
135
156
|
}
|
|
136
157
|
|
|
137
158
|
function appendBucket(lines, label, items = []) {
|
|
138
159
|
if (!items.length) return;
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
lines.push(
|
|
160
|
+
const icon = { Followed: "✅", Ignored: "❌", Unknown: "❓", Unmeasurable: "⚠️" }[label] || "";
|
|
161
|
+
lines.push(`### ${icon} ${label}`);
|
|
162
|
+
for (const item of items) {
|
|
163
|
+
lines.push(`- **Rule:** ${truncate(item.rule.content, 100)}`);
|
|
164
|
+
lines.push(` - Evidence: ${truncate(item.evidence, 100)}`);
|
|
143
165
|
}
|
|
144
|
-
|
|
166
|
+
lines.push("");
|
|
145
167
|
}
|
|
146
168
|
|
|
147
169
|
function truncate(value, max) {
|
|
@@ -42,6 +42,8 @@ export function handleStopPayload(payload, { contextPath, reportPath, historyPat
|
|
|
42
42
|
cwd,
|
|
43
43
|
prompt: promptContext?.prompt || "",
|
|
44
44
|
relevantFiles: promptContext?.relevantFiles || [],
|
|
45
|
+
suggestedSkills: promptContext?.suggestedSkills || [],
|
|
46
|
+
suggestedWorkflows: promptContext?.suggestedWorkflows || [],
|
|
45
47
|
scheduled,
|
|
46
48
|
gitSnapshot,
|
|
47
49
|
compliance,
|