@xera-ai/core 0.8.0 → 0.9.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/bin/internal.js +34 -6
- package/package.json +3 -3
- package/src/bin-internal/doctor.ts +15 -7
- package/src/bin-internal/fetch.ts +37 -4
package/dist/bin/internal.js
CHANGED
|
@@ -8395,16 +8395,19 @@ function checkRootScripts(repoRoot) {
|
|
|
8395
8395
|
const missing = REQUIRED_SCRIPTS.filter((s) => typeof scripts[s] !== "string");
|
|
8396
8396
|
return missing.map((s) => ({ ok: false, message: `root package.json missing script: ${s}` }));
|
|
8397
8397
|
}
|
|
8398
|
+
function isXeraMonorepo(repoRoot) {
|
|
8399
|
+
return existsSync9(join8(repoRoot, "packages/skills")) && existsSync9(join8(repoRoot, "packages/prompts"));
|
|
8400
|
+
}
|
|
8398
8401
|
async function doctorCmd(argv, opts = {}) {
|
|
8399
8402
|
const repoRoot = opts.cwd ?? process.cwd();
|
|
8400
8403
|
const autoEnrich = argv.includes("--auto-enrich");
|
|
8401
|
-
const results = [
|
|
8404
|
+
const results = isXeraMonorepo(repoRoot) ? [
|
|
8402
8405
|
...checkGoldenEvalDir(repoRoot),
|
|
8403
8406
|
...checkRubricPrompt(repoRoot),
|
|
8404
8407
|
...checkEvalSkill(repoRoot),
|
|
8405
8408
|
...checkPromptInjectionPreamble(repoRoot),
|
|
8406
8409
|
...checkRootScripts(repoRoot)
|
|
8407
|
-
];
|
|
8410
|
+
] : [];
|
|
8408
8411
|
const cost = summarizeCost(repoRoot, 7);
|
|
8409
8412
|
if (cost.totalCalls > 0) {
|
|
8410
8413
|
console.log("");
|
|
@@ -9565,9 +9568,12 @@ async function fetchCmd(argv, opts = {}) {
|
|
|
9565
9568
|
} : { story: config.jira.fields.story };
|
|
9566
9569
|
t = await client.fetchTicket(ticket, fieldMap);
|
|
9567
9570
|
}
|
|
9568
|
-
const
|
|
9571
|
+
const body = renderStoryBody(t);
|
|
9572
|
+
const storyHash = hashString(body);
|
|
9573
|
+
const acLines = parseAcLines(t.acceptanceCriteria);
|
|
9574
|
+
const full = renderStory(t.key, t.summary, storyHash, acLines, body);
|
|
9569
9575
|
mkdirSync10(dirname5(paths.storyPath), { recursive: true });
|
|
9570
|
-
writeFileSync9(paths.storyPath,
|
|
9576
|
+
writeFileSync9(paths.storyPath, full);
|
|
9571
9577
|
const existing = readMeta(paths.metaPath);
|
|
9572
9578
|
writeMeta(paths.metaPath, {
|
|
9573
9579
|
ticket,
|
|
@@ -9575,13 +9581,19 @@ async function fetchCmd(argv, opts = {}) {
|
|
|
9575
9581
|
xera_version: "0.1.0",
|
|
9576
9582
|
prompts_version: "1.0.0",
|
|
9577
9583
|
...existing ?? {},
|
|
9578
|
-
story_hash:
|
|
9584
|
+
story_hash: storyHash,
|
|
9579
9585
|
fetched_at: new Date().toISOString()
|
|
9580
9586
|
});
|
|
9581
9587
|
console.log(`[xera:fetch] wrote ${paths.storyPath}`);
|
|
9582
9588
|
return 0;
|
|
9583
9589
|
}
|
|
9584
|
-
function
|
|
9590
|
+
function parseAcLines(raw) {
|
|
9591
|
+
if (!raw?.trim())
|
|
9592
|
+
return [];
|
|
9593
|
+
return raw.trim().split(`
|
|
9594
|
+
`).map((l) => l.replace(/^[\s\-*]+/, "").trim()).filter(Boolean);
|
|
9595
|
+
}
|
|
9596
|
+
function renderStoryBody(t) {
|
|
9585
9597
|
const lines = [];
|
|
9586
9598
|
lines.push(`# ${t.key}: ${t.summary}`, "");
|
|
9587
9599
|
const story = t.story.trim();
|
|
@@ -9604,6 +9616,22 @@ function renderStory(t) {
|
|
|
9604
9616
|
return lines.join(`
|
|
9605
9617
|
`);
|
|
9606
9618
|
}
|
|
9619
|
+
function renderStory(key, summary, storyHash, acLines, body) {
|
|
9620
|
+
const yamlLines = [
|
|
9621
|
+
"---",
|
|
9622
|
+
`ticketId: ${key}`,
|
|
9623
|
+
`summary: ${JSON.stringify(summary)}`,
|
|
9624
|
+
`storyHash: ${storyHash}`
|
|
9625
|
+
];
|
|
9626
|
+
if (acLines.length > 0) {
|
|
9627
|
+
yamlLines.push("acceptanceCriteria:");
|
|
9628
|
+
for (const ac of acLines)
|
|
9629
|
+
yamlLines.push(` - ${JSON.stringify(ac)}`);
|
|
9630
|
+
}
|
|
9631
|
+
yamlLines.push("---", "");
|
|
9632
|
+
return yamlLines.join(`
|
|
9633
|
+
`) + body;
|
|
9634
|
+
}
|
|
9607
9635
|
|
|
9608
9636
|
// src/bin-internal/index.ts
|
|
9609
9637
|
init_graph_backfill();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xera-ai/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"zod": "4.4.3",
|
|
34
|
-
"@xera-ai/web": "^0.
|
|
35
|
-
"@xera-ai/http": "^0.
|
|
34
|
+
"@xera-ai/web": "^0.9.0",
|
|
35
|
+
"@xera-ai/http": "^0.9.0",
|
|
36
36
|
"@playwright/test": "1.60.0",
|
|
37
37
|
"fflate": "0.8.3",
|
|
38
38
|
"yaml": "2.9.0"
|
|
@@ -117,16 +117,24 @@ function checkRootScripts(repoRoot: string): CheckResult[] {
|
|
|
117
117
|
return missing.map((s) => ({ ok: false, message: `root package.json missing script: ${s}` }));
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
function isXeraMonorepo(repoRoot: string): boolean {
|
|
121
|
+
return (
|
|
122
|
+
existsSync(join(repoRoot, 'packages/skills')) && existsSync(join(repoRoot, 'packages/prompts'))
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
120
126
|
export async function doctorCmd(argv: string[], opts: DoctorOpts = {}): Promise<number> {
|
|
121
127
|
const repoRoot = opts.cwd ?? process.cwd();
|
|
122
128
|
const autoEnrich = argv.includes('--auto-enrich');
|
|
123
|
-
const results: CheckResult[] =
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
129
|
+
const results: CheckResult[] = isXeraMonorepo(repoRoot)
|
|
130
|
+
? [
|
|
131
|
+
...checkGoldenEvalDir(repoRoot),
|
|
132
|
+
...checkRubricPrompt(repoRoot),
|
|
133
|
+
...checkEvalSkill(repoRoot),
|
|
134
|
+
...checkPromptInjectionPreamble(repoRoot),
|
|
135
|
+
...checkRootScripts(repoRoot),
|
|
136
|
+
]
|
|
137
|
+
: [];
|
|
130
138
|
// Cost summary (past 7 days)
|
|
131
139
|
const cost = summarizeCost(repoRoot, 7);
|
|
132
140
|
if (cost.totalCalls > 0) {
|
|
@@ -43,9 +43,12 @@ export async function fetchCmd(argv: string[], opts: FetchCmdOpts = {}): Promise
|
|
|
43
43
|
t = await client.fetchTicket(ticket, fieldMap);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
const
|
|
46
|
+
const body = renderStoryBody(t);
|
|
47
|
+
const storyHash = hashString(body);
|
|
48
|
+
const acLines = parseAcLines(t.acceptanceCriteria);
|
|
49
|
+
const full = renderStory(t.key, t.summary, storyHash, acLines, body);
|
|
47
50
|
mkdirSync(dirname(paths.storyPath), { recursive: true });
|
|
48
|
-
writeFileSync(paths.storyPath,
|
|
51
|
+
writeFileSync(paths.storyPath, full);
|
|
49
52
|
|
|
50
53
|
const existing = readMeta(paths.metaPath);
|
|
51
54
|
writeMeta(paths.metaPath, {
|
|
@@ -55,7 +58,7 @@ export async function fetchCmd(argv: string[], opts: FetchCmdOpts = {}): Promise
|
|
|
55
58
|
prompts_version: '1.0.0',
|
|
56
59
|
...(existing ?? {}),
|
|
57
60
|
// Re-stamp the just-fetched fields:
|
|
58
|
-
story_hash:
|
|
61
|
+
story_hash: storyHash,
|
|
59
62
|
fetched_at: new Date().toISOString(),
|
|
60
63
|
});
|
|
61
64
|
|
|
@@ -63,7 +66,16 @@ export async function fetchCmd(argv: string[], opts: FetchCmdOpts = {}): Promise
|
|
|
63
66
|
return 0;
|
|
64
67
|
}
|
|
65
68
|
|
|
66
|
-
function
|
|
69
|
+
function parseAcLines(raw: string | undefined): string[] {
|
|
70
|
+
if (!raw?.trim()) return [];
|
|
71
|
+
return raw
|
|
72
|
+
.trim()
|
|
73
|
+
.split('\n')
|
|
74
|
+
.map((l) => l.replace(/^[\s\-*]+/, '').trim())
|
|
75
|
+
.filter(Boolean);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function renderStoryBody(t: JiraTicket): string {
|
|
67
79
|
const lines: string[] = [];
|
|
68
80
|
lines.push(`# ${t.key}: ${t.summary}`, '');
|
|
69
81
|
|
|
@@ -93,3 +105,24 @@ function renderStory(t: JiraTicket): string {
|
|
|
93
105
|
}
|
|
94
106
|
return lines.join('\n');
|
|
95
107
|
}
|
|
108
|
+
|
|
109
|
+
function renderStory(
|
|
110
|
+
key: string,
|
|
111
|
+
summary: string,
|
|
112
|
+
storyHash: string,
|
|
113
|
+
acLines: string[],
|
|
114
|
+
body: string,
|
|
115
|
+
): string {
|
|
116
|
+
const yamlLines = [
|
|
117
|
+
'---',
|
|
118
|
+
`ticketId: ${key}`,
|
|
119
|
+
`summary: ${JSON.stringify(summary)}`,
|
|
120
|
+
`storyHash: ${storyHash}`,
|
|
121
|
+
];
|
|
122
|
+
if (acLines.length > 0) {
|
|
123
|
+
yamlLines.push('acceptanceCriteria:');
|
|
124
|
+
for (const ac of acLines) yamlLines.push(` - ${JSON.stringify(ac)}`);
|
|
125
|
+
}
|
|
126
|
+
yamlLines.push('---', '');
|
|
127
|
+
return yamlLines.join('\n') + body;
|
|
128
|
+
}
|