@oqtopus-team/pi-qdash 0.1.5 → 0.1.8
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 +4 -2
- package/extensions/qdash.ts +49 -48
- package/extensions/tools/task-knowledge.ts +144 -0
- package/package.json +5 -2
- package/skills/qdash/SKILL.md +52 -48
- package/skills/qdash-calibration-agent/SKILL.md +13 -53
- package/skills/qdash-timeseries-diagnosis/SKILL.md +8 -1
- package/skills/qdash-two-qubit-calibration-diagnosis/SKILL.md +7 -63
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ It uses [`@oqtopus-team/qdash-client`](https://www.npmjs.com/package/@oqtopus-te
|
|
|
16
16
|
|
|
17
17
|
## Key Features
|
|
18
18
|
|
|
19
|
-
- **Read-only investigation**: dedicated tools to inspect chips, qubits, couplings, calibration task results, executions, issues, and Forum posts. Secrets are redacted from tool output.
|
|
19
|
+
- **Read-only investigation**: dedicated tools to inspect chips, qubits, couplings, calibration task results, task knowledge (`qdash_get_task_knowledge`), executions, issues, and Forum posts. Secrets are redacted from tool output.
|
|
20
20
|
- **Dashboards and insights**: compact dashboards, triage overviews, target-level incident reports, degradation reports, and wiring insights.
|
|
21
21
|
- **Agent calibration workflow**: create agent sessions, submit and track agent actions, and commit/apply calibration candidates. Write operations are approval-gated.
|
|
22
22
|
- **Figures**: fetch calibration PNG/JSON figures and render them in the interactive TUI.
|
|
@@ -43,7 +43,9 @@ Or try it without installing:
|
|
|
43
43
|
pi -e npm:@oqtopus-team/pi-qdash
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
Requires pi v0.74.0 or later.
|
|
46
|
+
Requires Node.js 20 or later and pi v0.74.0 or later. The extension tracks
|
|
47
|
+
`@oqtopus-team/qdash-client` 1.9.x and uses its authenticated high-level and
|
|
48
|
+
generated API clients.
|
|
47
49
|
|
|
48
50
|
## Quick Start
|
|
49
51
|
|
package/extensions/qdash.ts
CHANGED
|
@@ -4,7 +4,13 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
5
|
|
|
6
6
|
import type { ExtensionAPI, Theme } from "@earendil-works/pi-coding-agent";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
QDashClient,
|
|
9
|
+
defaultConfigPath,
|
|
10
|
+
type CooldownResponse,
|
|
11
|
+
type DownloadedFile,
|
|
12
|
+
type TaskResultFigureOptions,
|
|
13
|
+
} from "@oqtopus-team/qdash-client";
|
|
8
14
|
import { Text, truncateToWidth } from "@earendil-works/pi-tui";
|
|
9
15
|
import { Type } from "typebox";
|
|
10
16
|
|
|
@@ -19,6 +25,7 @@ import { toTextToolResult, toToolResult } from "./lib/results.js";
|
|
|
19
25
|
import { ansi, boxLinesToWidth, boxed, formatNumber, textComponent } from "./lib/render.js";
|
|
20
26
|
import { plotSeriesLines, timeseriesPlotComponent, timeseriesPoints } from "./lib/timeseries-plot.js";
|
|
21
27
|
import { installQDashWriteGate } from "./lib/write-gate.js";
|
|
28
|
+
import { registerTaskKnowledgeTool } from "./tools/task-knowledge.js";
|
|
22
29
|
import { registerTimeseriesComparisonTool } from "./tools/timeseries.js";
|
|
23
30
|
import { analyzeWiringMarkdown, wiringInsightLines, type WiringInsights } from "./lib/wiring-analysis.js";
|
|
24
31
|
|
|
@@ -397,6 +404,9 @@ async function defaultChipId(client: QDashClient, chipId?: string): Promise<stri
|
|
|
397
404
|
return chipId ?? currentContext.chipId ?? client.getDefaultChipId();
|
|
398
405
|
}
|
|
399
406
|
|
|
407
|
+
// Keep arbitrary GET access isolated for qdash_raw_get and legacy filters that are
|
|
408
|
+
// not represented in the generated OpenAPI surface. Normal operations should use
|
|
409
|
+
// QDashClient's high-level methods or client.api so upgrades remain type-checked.
|
|
400
410
|
async function rawGet<T>(client: QDashClient, path: string, query?: Record<string, unknown>): Promise<T> {
|
|
401
411
|
return (client as unknown as { get<T>(path: string, query?: Record<string, unknown>): Promise<T> }).get(path, cleanQuery(query));
|
|
402
412
|
}
|
|
@@ -472,19 +482,6 @@ function requireValue(value: string | undefined, name: string): string {
|
|
|
472
482
|
return value;
|
|
473
483
|
}
|
|
474
484
|
|
|
475
|
-
type CooldownRecord = {
|
|
476
|
-
cooldown_id: string;
|
|
477
|
-
cryo_id: string;
|
|
478
|
-
description?: string;
|
|
479
|
-
started_at: string;
|
|
480
|
-
ended_at?: string | null;
|
|
481
|
-
chip_ids?: string[];
|
|
482
|
-
wiring_info?: string;
|
|
483
|
-
wiring_blocks?: Record<string, unknown>[];
|
|
484
|
-
};
|
|
485
|
-
|
|
486
|
-
type CooldownListResponse = { cooldowns?: CooldownRecord[] };
|
|
487
|
-
|
|
488
485
|
type CooldownWiringParams = {
|
|
489
486
|
profile?: string;
|
|
490
487
|
configPath?: string;
|
|
@@ -502,7 +499,7 @@ type WiringInsightParams = CooldownWiringParams & {
|
|
|
502
499
|
color?: boolean;
|
|
503
500
|
};
|
|
504
501
|
|
|
505
|
-
function newestCooldown(cooldowns:
|
|
502
|
+
function newestCooldown(cooldowns: CooldownResponse[]): CooldownResponse | undefined {
|
|
506
503
|
return [...cooldowns].sort((a, b) => {
|
|
507
504
|
const activeDifference = Number(a.ended_at != null) - Number(b.ended_at != null);
|
|
508
505
|
if (activeDifference !== 0) return activeDifference;
|
|
@@ -514,15 +511,15 @@ async function resolveCooldownWiring(params: CooldownWiringParams) {
|
|
|
514
511
|
params = applyQDashContext(params);
|
|
515
512
|
const client = await makeClient(params);
|
|
516
513
|
let selection: string;
|
|
517
|
-
let cooldown:
|
|
514
|
+
let cooldown: CooldownResponse;
|
|
518
515
|
let resolvedChipId = params.chipId ?? currentContext.chipId;
|
|
519
516
|
|
|
520
517
|
if (params.cooldownId) {
|
|
521
|
-
cooldown = await
|
|
518
|
+
cooldown = await client.api.getCooldown(params.cooldownId);
|
|
522
519
|
selection = "explicit cooldownId";
|
|
523
520
|
} else {
|
|
524
521
|
resolvedChipId = params.chipId ?? (params.cryoId ? undefined : await defaultChipId(client));
|
|
525
|
-
const response = await
|
|
522
|
+
const response = await client.api.listCooldowns({
|
|
526
523
|
cryo_id: params.cryoId,
|
|
527
524
|
chip_id: resolvedChipId,
|
|
528
525
|
});
|
|
@@ -531,7 +528,7 @@ async function resolveCooldownWiring(params: CooldownWiringParams) {
|
|
|
531
528
|
const scope = params.cryoId ? `cryo ${params.cryoId}` : `chip ${resolvedChipId}`;
|
|
532
529
|
throw new Error(`No cooldown containing wiring information was found for ${scope}`);
|
|
533
530
|
}
|
|
534
|
-
cooldown = await
|
|
531
|
+
cooldown = await client.api.getCooldown(selected.cooldown_id);
|
|
535
532
|
selection = params.cryoId ? "active/newest cooldown for cryo" : "active/newest cooldown for chip";
|
|
536
533
|
}
|
|
537
534
|
|
|
@@ -539,14 +536,14 @@ async function resolveCooldownWiring(params: CooldownWiringParams) {
|
|
|
539
536
|
const wiringInfo = typeof cooldown.wiring_info === "string" ? cooldown.wiring_info.trim() : "";
|
|
540
537
|
const includeBlocks = params.includeBlocks === true || !wiringInfo;
|
|
541
538
|
const history = params.includeHistory
|
|
542
|
-
? await
|
|
539
|
+
? await client.api.listCooldownWiringEvents(cooldown.cooldown_id, {
|
|
543
540
|
limit: params.historyLimit ?? 20,
|
|
544
541
|
skip: 0,
|
|
545
542
|
})
|
|
546
543
|
: undefined;
|
|
547
544
|
let cryostat: unknown;
|
|
548
545
|
try {
|
|
549
|
-
cryostat = await
|
|
546
|
+
cryostat = await client.api.getCryostat(cooldown.cryo_id);
|
|
550
547
|
} catch {
|
|
551
548
|
// Wiring remains useful on servers where cryostat detail is not accessible.
|
|
552
549
|
}
|
|
@@ -594,9 +591,9 @@ async function buildDashboard(params: { profile?: string; configPath?: string; u
|
|
|
594
591
|
const chipId = await defaultChipId(client, params.chipId);
|
|
595
592
|
const [chips, openIssues, recentExecutions, failedTaskResults, provenanceStats] = await Promise.allSettled([
|
|
596
593
|
client.listChips(),
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
594
|
+
client.api.listIssues({ is_closed: false, limit }),
|
|
595
|
+
client.api.listExecutions({ chip_id: chipId, limit }),
|
|
596
|
+
client.api.listTaskResults({ chip_id: chipId, status: "failed", limit }),
|
|
600
597
|
client.getProvenanceStats(),
|
|
601
598
|
]);
|
|
602
599
|
const value = <T>(result: PromiseSettledResult<T>): T | { error: string } => result.status === "fulfilled" ? result.value : { error: result.reason instanceof Error ? result.reason.message : String(result.reason) };
|
|
@@ -738,7 +735,7 @@ async function buildRecentCalibrationSummary(params: { profile?: string; configP
|
|
|
738
735
|
const chipId = await defaultChipId(client, params.chipId);
|
|
739
736
|
const end = new Date();
|
|
740
737
|
const start = new Date(end.getTime() - (params.withinHours ?? 24) * 3600_000);
|
|
741
|
-
const payload = await
|
|
738
|
+
const payload = await client.api.listTaskResults({ chip_id: chipId, start_from: start.toISOString(), start_to: end.toISOString(), limit: params.limit ?? 30 });
|
|
742
739
|
const items = arrayFromPayload(payload).filter((item): item is Record<string, unknown> => Boolean(item) && typeof item === "object");
|
|
743
740
|
const byTarget = new Map<string, Record<string, unknown>[]>();
|
|
744
741
|
for (const item of items) {
|
|
@@ -939,7 +936,7 @@ async function buildTargetOperationsReport(params: { profile?: string; configPat
|
|
|
939
936
|
const [latestTarget, results, issues, forumPosts] = await Promise.all([
|
|
940
937
|
kind === "qubit" ? client.getChipQubit(chipId, id) : client.getChipCoupling(chipId, id),
|
|
941
938
|
client.listTaskResults({ chipId, qid, couplingId, startAt: start.toISOString(), endAt: end.toISOString(), limit }),
|
|
942
|
-
|
|
939
|
+
client.api.listIssues({ is_closed: false, limit: 100 }),
|
|
943
940
|
client.listForumPosts({ chipId, status: "open", targetType: kind, targetId: id, limit }),
|
|
944
941
|
]);
|
|
945
942
|
const recentResults = arrayFromPayload(results).filter((item): item is Record<string, unknown> => Boolean(item) && typeof item === "object");
|
|
@@ -1123,7 +1120,7 @@ async function buildCalibrationValidation(params: { profile?: string; configPath
|
|
|
1123
1120
|
const task = await client.getTaskResult(params.taskId) as unknown as Record<string, unknown>;
|
|
1124
1121
|
const status = firstString(task, ["status"])?.toLowerCase() ?? "unknown";
|
|
1125
1122
|
const figurePaths = taskFigurePaths(task, 20);
|
|
1126
|
-
const issuesPayload = await
|
|
1123
|
+
const issuesPayload = await client.api.getTaskResultIssues(params.taskId).catch(() => []);
|
|
1127
1124
|
const issues = arrayFromPayload(issuesPayload).filter((item): item is Record<string, unknown> => Boolean(item) && typeof item === "object");
|
|
1128
1125
|
const afterExecutionId = firstString(task, ["execution_id", "executionId"]);
|
|
1129
1126
|
const comparison = params.beforeExecutionId && afterExecutionId
|
|
@@ -1256,10 +1253,10 @@ async function buildDashboardInsights(params: { profile?: string; configPath?: s
|
|
|
1256
1253
|
const start = new Date(end.getTime() - (params.withinHours ?? 168) * 3600_000);
|
|
1257
1254
|
const [forums, issues, failed, metrics, aiInsights] = await Promise.allSettled([
|
|
1258
1255
|
client.listForumPosts({ chipId, status: "open", limit }),
|
|
1259
|
-
|
|
1260
|
-
|
|
1256
|
+
client.api.listIssues({ is_closed: false, limit }),
|
|
1257
|
+
client.api.listTaskResults({ chip_id: chipId, status: "failed", start_from: start.toISOString(), start_to: end.toISOString(), limit }),
|
|
1261
1258
|
client.getChipMetrics(chipId),
|
|
1262
|
-
|
|
1259
|
+
client.api.getDashboardAiInsights(chipId, { latest_only: true, start_at: start.toISOString(), end_at: end.toISOString() }),
|
|
1263
1260
|
]);
|
|
1264
1261
|
const value = <T>(result: PromiseSettledResult<T>): T | undefined => result.status === "fulfilled" ? result.value : undefined;
|
|
1265
1262
|
const insightMap = new Map<string, DashboardInsight>();
|
|
@@ -1485,19 +1482,19 @@ async function executeQuery(params: QDashQueryParams) {
|
|
|
1485
1482
|
case "chip_qubit": return client.getChipQubit(await defaultChipId(client, params.chipId), requireValue(params.qid, "qid"));
|
|
1486
1483
|
case "chip_couplings": return client.listChipCouplings(await defaultChipId(client, params.chipId), { limit: params.limit, offset: params.offset });
|
|
1487
1484
|
case "chip_coupling": return client.getChipCoupling(await defaultChipId(client, params.chipId), requireValue(params.couplingId, "couplingId"));
|
|
1488
|
-
case "cryostats": return
|
|
1489
|
-
case "cryostat": return
|
|
1490
|
-
case "cooldowns": return
|
|
1491
|
-
case "cooldown": return
|
|
1492
|
-
case "cooldown_wiring_events": return
|
|
1485
|
+
case "cryostats": return client.api.listCryostats();
|
|
1486
|
+
case "cryostat": return client.api.getCryostat(requireValue(params.cryoId, "cryoId"));
|
|
1487
|
+
case "cooldowns": return client.api.listCooldowns({ cryo_id: params.cryoId, chip_id: params.chipId });
|
|
1488
|
+
case "cooldown": return client.api.getCooldown(requireValue(params.cooldownId, "cooldownId"));
|
|
1489
|
+
case "cooldown_wiring_events": return client.api.listCooldownWiringEvents(requireValue(params.cooldownId, "cooldownId"), { limit: params.limit, skip: params.skip });
|
|
1493
1490
|
case "timeseries": return client.getTaskResultsTimeseries({ chipId: await defaultChipId(client, params.chipId), parameter: requireValue(params.parameter, "parameter"), tag: params.tag, qid: params.qid, startAt: requireValue(params.startAt, "startAt"), endAt: requireValue(params.endAt, "endAt") });
|
|
1494
1491
|
case "task_results": return rawGet(client, "/task-results", { chip_id: params.chipId, task_name: params.taskName, qid: params.qid, coupling_id: params.couplingId, execution_id: params.executionId, username: params.username, status: params.status, start_from: params.startFrom ?? params.startAt, start_to: params.startTo ?? params.endAt, message_contains: params.messageContains, limit: params.limit, skip: params.skip });
|
|
1495
1492
|
case "task_result": return client.getTaskResult(requireValue(params.taskId, "taskId"));
|
|
1496
|
-
case "task_note": return
|
|
1497
|
-
case "task_result_issues": return
|
|
1498
|
-
case "qubit_latest": return
|
|
1493
|
+
case "task_note": return client.api.getTaskNote(requireValue(params.taskId, "taskId"));
|
|
1494
|
+
case "task_result_issues": return client.api.getTaskResultIssues(requireValue(params.taskId, "taskId"));
|
|
1495
|
+
case "qubit_latest": return client.api.getLatestQubitTaskResults({ chip_id: await defaultChipId(client, params.chipId), task: requireValue(params.task ?? params.taskName, "task") });
|
|
1499
1496
|
case "qubit_history": return rawGet(client, `/task-results/qubits/${pathPart(requireValue(params.qid, "qid"))}/history`, { chip_id: await defaultChipId(client, params.chipId), task: requireValue(params.task ?? params.taskName, "task"), date: requireValue(params.date, "date") });
|
|
1500
|
-
case "coupling_latest": return
|
|
1497
|
+
case "coupling_latest": return client.api.getLatestCouplingTaskResults({ chip_id: await defaultChipId(client, params.chipId), task: requireValue(params.task ?? params.taskName, "task") });
|
|
1501
1498
|
case "coupling_history": return rawGet(client, `/task-results/couplings/${pathPart(requireValue(params.couplingId, "couplingId"))}/history`, { chip_id: await defaultChipId(client, params.chipId), task: requireValue(params.task ?? params.taskName, "task"), date: requireValue(params.date, "date") });
|
|
1502
1499
|
case "tasks": return client.listTasks(params.backend);
|
|
1503
1500
|
case "task_knowledge": return params.taskName ? client.getTaskKnowledge(params.taskName) : client.listTaskKnowledge();
|
|
@@ -1507,23 +1504,26 @@ async function executeQuery(params: QDashQueryParams) {
|
|
|
1507
1504
|
case "files_tree": return client.getFilesTree();
|
|
1508
1505
|
case "file_content": return client.getFileContent(requireValue(params.path, "path"));
|
|
1509
1506
|
case "git_status": return client.getGitStatus();
|
|
1510
|
-
case "issues": return
|
|
1511
|
-
case "issue_knowledge": return
|
|
1507
|
+
case "issues": return client.api.listIssues({ task_id: params.taskId, is_closed: params.isClosed, limit: params.limit, skip: params.skip });
|
|
1508
|
+
case "issue_knowledge": return client.api.listIssueKnowledge({ status: params.status, task_name: params.taskName, limit: params.limit, skip: params.skip });
|
|
1512
1509
|
case "flows": return client.listFlows();
|
|
1513
1510
|
case "flow": return client.getFlow(requireValue(params.flowName, "flowName"));
|
|
1514
1511
|
case "flow_templates": return client.listFlowTemplates();
|
|
1515
1512
|
case "flow_template": return client.getFlowTemplate(requireValue(params.templateId, "templateId"));
|
|
1516
|
-
case "flow_helper_files": return
|
|
1517
|
-
case "flow_helper_file": return
|
|
1513
|
+
case "flow_helper_files": return client.api.listFlowHelperFiles();
|
|
1514
|
+
case "flow_helper_file": return client.api.getFlowHelperFile(requireValue(params.filename, "filename"));
|
|
1518
1515
|
case "executions": return rawGet(client, "/executions", { chip_id: params.chipId, flow_name: params.flowName, status: params.status, skip: params.skip, limit: params.limit });
|
|
1519
1516
|
case "execution": return client.getExecution(requireValue(params.executionId, "executionId"));
|
|
1520
|
-
case "ai_reviews": return
|
|
1521
|
-
case "ai_review_runs": return
|
|
1522
|
-
case "ai_review_run": return
|
|
1517
|
+
case "ai_reviews": return client.api.listTaskResultAiReviews({ chip_id: params.chipId, task_name: params.taskName, status: params.status, decision: params.decision, latest_only: params.latestOnly, skip: params.skip, limit: params.limit });
|
|
1518
|
+
case "ai_review_runs": return client.api.listTaskResultAiReviewRuns({ chip_id: params.chipId, task_name: params.taskName, skip: params.skip, limit: params.limit });
|
|
1519
|
+
case "ai_review_run": return client.api.getTaskResultAiReviewRun(requireValue(params.reviewRunId, "reviewRunId"));
|
|
1523
1520
|
case "forum_posts": return client.listForumPosts({ status: params.status, chipId: params.chipId, limit: params.limit, skip: params.skip });
|
|
1524
1521
|
case "provenance_stats": return client.getProvenanceStats();
|
|
1525
|
-
case "provenance_history": return
|
|
1526
|
-
case "provenance_changes":
|
|
1522
|
+
case "provenance_history": return client.api.getParameterHistory({ parameter_name: requireValue(params.parameterName ?? params.parameter, "parameterName"), qid: requireValue(params.qid, "qid"), limit: params.limit });
|
|
1523
|
+
case "provenance_changes": {
|
|
1524
|
+
const parameterName = params.parameterName ?? params.parameter;
|
|
1525
|
+
return client.getRecentChanges({ parameterNames: parameterName ? [parameterName] : undefined, withinHours: params.withinHours, limit: params.limit });
|
|
1526
|
+
}
|
|
1527
1527
|
case "provenance_lineage": return client.getProvenanceLineage(requireValue(params.entityId, "entityId"));
|
|
1528
1528
|
case "provenance_impact": return client.getProvenanceImpact(requireValue(params.entityId, "entityId"));
|
|
1529
1529
|
}
|
|
@@ -1531,6 +1531,7 @@ async function executeQuery(params: QDashQueryParams) {
|
|
|
1531
1531
|
|
|
1532
1532
|
export default function qdashExtension(pi: ExtensionAPI) {
|
|
1533
1533
|
installQDashWriteGate(pi);
|
|
1534
|
+
registerTaskKnowledgeTool(pi, { makeClient });
|
|
1534
1535
|
|
|
1535
1536
|
pi.registerTool({
|
|
1536
1537
|
name: "qdash_config_info",
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import type { QDashClient } from "@oqtopus-team/qdash-client";
|
|
3
|
+
import { Type } from "typebox";
|
|
4
|
+
|
|
5
|
+
import { toTextToolResult } from "../lib/results.js";
|
|
6
|
+
|
|
7
|
+
type TaskKnowledgeParams = {
|
|
8
|
+
profile?: string;
|
|
9
|
+
configPath?: string;
|
|
10
|
+
useEnv?: boolean;
|
|
11
|
+
taskName: string;
|
|
12
|
+
format?: "markdown" | "summary";
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
type TaskKnowledge = {
|
|
16
|
+
name: string;
|
|
17
|
+
summary?: string;
|
|
18
|
+
what_it_measures?: string;
|
|
19
|
+
expected_result?: Record<string, unknown>;
|
|
20
|
+
failure_modes?: Array<Record<string, unknown>>;
|
|
21
|
+
check_questions?: string[];
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
type TaskKnowledgeList = { items?: Array<{ name?: string }> } | Array<{ name?: string }>;
|
|
25
|
+
|
|
26
|
+
export type TaskKnowledgeDependencies = {
|
|
27
|
+
makeClient(params: TaskKnowledgeParams): Promise<QDashClient>;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
function text(value: unknown): string | undefined {
|
|
31
|
+
if (typeof value !== "string") return undefined;
|
|
32
|
+
const trimmed = value.trim();
|
|
33
|
+
return trimmed || undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function bulletLines(items: string[]): string[] {
|
|
37
|
+
return items.length ? items.map((item) => `- ${item}`) : ["- Not documented."];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function taskKnowledgeSummary(knowledge: TaskKnowledge): string {
|
|
41
|
+
const expected = knowledge.expected_result ?? {};
|
|
42
|
+
const expectedLines = [
|
|
43
|
+
text(expected.description),
|
|
44
|
+
text(expected.good_visual) && `Good visual: ${text(expected.good_visual)}`,
|
|
45
|
+
text(expected.typical_range) && `Typical range: ${text(expected.typical_range)}`,
|
|
46
|
+
].filter((value): value is string => Boolean(value));
|
|
47
|
+
const failureLines = (knowledge.failure_modes ?? []).map((mode) => {
|
|
48
|
+
const description = text(mode.description) ?? "Unspecified failure mode";
|
|
49
|
+
const cause = text(mode.cause);
|
|
50
|
+
const nextAction = text(mode.next_action);
|
|
51
|
+
return [description, cause && `Cause: ${cause}`, nextAction && `Next: ${nextAction}`].filter(Boolean).join(" — ");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return [
|
|
55
|
+
`# ${knowledge.name}`,
|
|
56
|
+
"",
|
|
57
|
+
...(text(knowledge.summary) ? [text(knowledge.summary)!, ""] : []),
|
|
58
|
+
"## What it measures",
|
|
59
|
+
"",
|
|
60
|
+
text(knowledge.what_it_measures) ?? "Not documented.",
|
|
61
|
+
"",
|
|
62
|
+
"## Expected result",
|
|
63
|
+
"",
|
|
64
|
+
...bulletLines(expectedLines),
|
|
65
|
+
"",
|
|
66
|
+
"## Failure modes",
|
|
67
|
+
"",
|
|
68
|
+
...bulletLines(failureLines),
|
|
69
|
+
"",
|
|
70
|
+
"## Check questions",
|
|
71
|
+
"",
|
|
72
|
+
...bulletLines((knowledge.check_questions ?? []).filter((item) => Boolean(text(item)))),
|
|
73
|
+
].join("\n");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function knownNames(payload: TaskKnowledgeList): string[] {
|
|
77
|
+
const items = Array.isArray(payload) ? payload : payload.items ?? [];
|
|
78
|
+
return items.map((item) => text(item.name)).filter((name): name is string => Boolean(name));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function similarTaskNames(taskName: string, names: string[], limit = 5): string[] {
|
|
82
|
+
const needle = taskName.toLowerCase();
|
|
83
|
+
return names
|
|
84
|
+
.filter((name) => {
|
|
85
|
+
const candidate = name.toLowerCase();
|
|
86
|
+
return candidate.startsWith(needle) || needle.startsWith(candidate) || candidate.includes(needle) || needle.includes(candidate);
|
|
87
|
+
})
|
|
88
|
+
.sort((a, b) => {
|
|
89
|
+
const aPrefix = a.toLowerCase().startsWith(needle) ? 0 : 1;
|
|
90
|
+
const bPrefix = b.toLowerCase().startsWith(needle) ? 0 : 1;
|
|
91
|
+
return aPrefix - bPrefix || a.length - b.length || a.localeCompare(b);
|
|
92
|
+
})
|
|
93
|
+
.slice(0, limit);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function notFound(error: unknown): boolean {
|
|
97
|
+
if (!error || typeof error !== "object") return false;
|
|
98
|
+
const value = error as { status?: unknown; statusCode?: unknown; response?: { status?: unknown }; message?: unknown };
|
|
99
|
+
return value.status === 404 || value.statusCode === 404 || value.response?.status === 404 || /\b404\b|not found/i.test(String(value.message ?? ""));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function registerTaskKnowledgeTool(pi: Pick<ExtensionAPI, "registerTool">, deps: TaskKnowledgeDependencies): void {
|
|
103
|
+
pi.registerTool({
|
|
104
|
+
name: "qdash_get_task_knowledge",
|
|
105
|
+
label: "QDash Task Knowledge",
|
|
106
|
+
description: "Get task knowledge when asked how to interpret a result, what curve or outcome is expected, which failure modes apply, or what to try next.",
|
|
107
|
+
promptSnippet: "Read QDash task knowledge before interpreting calibration results",
|
|
108
|
+
promptGuidelines: [
|
|
109
|
+
"Use qdash_get_task_knowledge before interpreting task-specific physics, expected curves, failure modes, or next diagnostic checks.",
|
|
110
|
+
"This tool is read-only and does not execute tasks or change parameters.",
|
|
111
|
+
],
|
|
112
|
+
parameters: Type.Object({
|
|
113
|
+
profile: Type.Optional(Type.String({ description: "QDash profile name. Defaults to env when QDASH_BASE_URL is set, otherwise 'default'." })),
|
|
114
|
+
configPath: Type.Optional(Type.String({ description: "Optional path to qdash config.ini." })),
|
|
115
|
+
useEnv: Type.Optional(Type.Boolean({ description: "Force QDASH_* environment variables instead of a profile." })),
|
|
116
|
+
taskName: Type.String({ description: "QDash task name, for example CheckRabi." }),
|
|
117
|
+
format: Type.Optional(Type.Union([Type.Literal("markdown"), Type.Literal("summary")], { description: "Output format. Defaults to markdown." })),
|
|
118
|
+
}),
|
|
119
|
+
async execute(_toolCallId, params: TaskKnowledgeParams) {
|
|
120
|
+
const client = await deps.makeClient(params);
|
|
121
|
+
const format = params.format ?? "markdown";
|
|
122
|
+
try {
|
|
123
|
+
const data = format === "summary"
|
|
124
|
+
? await client.getTaskKnowledge(params.taskName) as unknown as TaskKnowledge
|
|
125
|
+
: await client.getTaskKnowledgeMarkdown(params.taskName);
|
|
126
|
+
const markdown = format === "summary"
|
|
127
|
+
? taskKnowledgeSummary(data as TaskKnowledge)
|
|
128
|
+
: typeof data === "string"
|
|
129
|
+
? data
|
|
130
|
+
: text((data as { markdown?: unknown })?.markdown) ?? JSON.stringify(data, null, 2);
|
|
131
|
+
return toTextToolResult(markdown, data, { taskName: params.taskName, format, found: true });
|
|
132
|
+
} catch (error) {
|
|
133
|
+
if (!notFound(error)) throw error;
|
|
134
|
+
const listed = await client.listTaskKnowledge() as TaskKnowledgeList;
|
|
135
|
+
const suggestions = similarTaskNames(params.taskName, knownNames(listed));
|
|
136
|
+
const markdown = [
|
|
137
|
+
`No task knowledge found for \`${params.taskName}\`.`,
|
|
138
|
+
...(suggestions.length ? ["", "Similar known task names:", ...suggestions.map((name) => `- \`${name}\``)] : ["", "No similar known task names were found."]),
|
|
139
|
+
].join("\n");
|
|
140
|
+
return toTextToolResult(markdown, { taskName: params.taskName, found: false, suggestions }, { taskName: params.taskName, format, found: false });
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oqtopus-team/pi-qdash",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "Pi extension for querying QDash via @oqtopus-team/qdash-client",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"author": "OQTOPUS Team <oqtopus-team@googlegroups.com>",
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": ">=20.0.0"
|
|
10
|
+
},
|
|
8
11
|
"repository": {
|
|
9
12
|
"type": "git",
|
|
10
13
|
"url": "git+https://github.com/oqtopus-team/pi-qdash.git"
|
|
@@ -24,7 +27,7 @@
|
|
|
24
27
|
"access": "public"
|
|
25
28
|
},
|
|
26
29
|
"dependencies": {
|
|
27
|
-
"@oqtopus-team/qdash-client": "^
|
|
30
|
+
"@oqtopus-team/qdash-client": "^1.9.11"
|
|
28
31
|
},
|
|
29
32
|
"peerDependencies": {
|
|
30
33
|
"@earendil-works/pi-coding-agent": "*",
|
package/skills/qdash/SKILL.md
CHANGED
|
@@ -9,55 +9,45 @@ Use the pi-qdash tools instead of scraping the UI or hand-writing auth headers.
|
|
|
9
9
|
|
|
10
10
|
## Preferred tools
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
- `
|
|
16
|
-
- `
|
|
17
|
-
- `
|
|
18
|
-
- `
|
|
19
|
-
- `
|
|
20
|
-
- `
|
|
21
|
-
- `
|
|
22
|
-
- `
|
|
23
|
-
- `
|
|
24
|
-
- `
|
|
25
|
-
- `
|
|
26
|
-
- `
|
|
27
|
-
- `
|
|
28
|
-
|
|
29
|
-
- `
|
|
30
|
-
|
|
31
|
-
- `qdash_dashboard`
|
|
32
|
-
- `
|
|
33
|
-
- `qdash_recent_calibration_summary`
|
|
34
|
-
- `
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
- `
|
|
38
|
-
- `
|
|
39
|
-
- `
|
|
40
|
-
- `
|
|
41
|
-
|
|
42
|
-
- `
|
|
43
|
-
- `
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
- `chips`, `default_chip`, `metrics_config`, `chip_metrics`
|
|
47
|
-
- `chip_qubits`, `chip_qubit`, `chip_couplings`, `chip_coupling`
|
|
48
|
-
- `cryostats`, `cryostat`, `cooldowns`, `cooldown`, `cooldown_wiring_events`
|
|
49
|
-
- `timeseries`, `task_results`, `task_result`, `task_note`, `task_result_issues`
|
|
50
|
-
- `qubit_latest`, `qubit_history`, `coupling_latest`, `coupling_history`
|
|
51
|
-
- `tasks`, `task_knowledge`, `task_knowledge_markdown`
|
|
52
|
-
- `projects`, `project`, `files_tree`, `file_content`, `git_status`
|
|
53
|
-
- `issues`, `issue_knowledge`
|
|
54
|
-
- `flows`, `flow`, `flow_templates`, `flow_template`, `flow_helper_files`, `flow_helper_file`
|
|
55
|
-
- `executions`, `execution`, `ai_reviews`, `ai_review_runs`, `ai_review_run`
|
|
56
|
-
- `forum_posts`, `provenance_stats`, `provenance_history`, `provenance_changes`, `provenance_lineage`, `provenance_impact`
|
|
57
|
-
6. `qdash_raw_get` — read-only GET endpoints not covered by `qdash_query`.
|
|
12
|
+
Prefer the dedicated tool that matches the question. Use `qdash_query` only as a fallback when no dedicated tool covers the read-only operation.
|
|
13
|
+
|
|
14
|
+
1. Dedicated read-only tools:
|
|
15
|
+
- `qdash_list_chips`, `qdash_get_default_chip` — list chips or resolve the active chip
|
|
16
|
+
- `qdash_get_chip_metrics`, `qdash_list_chip_qubits`, `qdash_list_chip_couplings` — inspect chip metrics and topology targets
|
|
17
|
+
- `qdash_list_cryostats`, `qdash_list_cooldowns` — establish cryostat and cooldown context
|
|
18
|
+
- `qdash_get_cooldown_wiring`, `qdash_wiring_insights`, `qdash_list_cooldown_wiring_events` — inspect current wiring, attenuation, and changes
|
|
19
|
+
- `qdash_get_timeseries`, `qdash_plot_timeseries` — inspect one target metric over time
|
|
20
|
+
- `qdash_inspect_timeseries_csv`, `qdash_compare_timeseries` — validate and compare multiple QDash or CSV timeseries
|
|
21
|
+
- `qdash_list_task_results`, `qdash_get_task_result` — find and inspect calibration results
|
|
22
|
+
- `qdash_get_task_knowledge` — interpret a task's purpose, expected result, failure modes, and check questions
|
|
23
|
+
- `qdash_list_issues` — inspect tracked issues
|
|
24
|
+
- `qdash_list_flows`, `qdash_get_flow` — list or inspect calibration flows
|
|
25
|
+
- `qdash_list_executions`, `qdash_get_execution`, `qdash_wait_execution`, `qdash_compare_executions` — inspect, await, or compare executions
|
|
26
|
+
- `qdash_list_ai_reviews`, `qdash_get_provenance_stats` — inspect AI reviews or provenance status
|
|
27
|
+
- `qdash_list_forum_posts`, `qdash_get_forum_post`, `qdash_list_forum_replies` — inspect Forum context
|
|
28
|
+
- `qdash_preview_forum_evidence_reply`, `qdash_preview_forum_image_reply` — preview evidence or image replies without writing
|
|
29
|
+
- `qdash_get_figure`, `qdash_get_task_figures`, `qdash_recent_calibration_figure`, `qdash_analyze_figure_json`, `qdash_build_qcal_evidence` — inspect or package figure evidence
|
|
30
|
+
2. Read-only overview and planning tools:
|
|
31
|
+
- `qdash_dashboard`, `qdash_dashboard_insights`, `qdash_triage_overview` — summarize status, insights, and investigation priorities
|
|
32
|
+
- `qdash_investigate`, `qdash_target_report`, `qdash_compare_calibration` — investigate target history and compare calibrations
|
|
33
|
+
- `qdash_recent_calibration_summary`, `qdash_recommend_next_action` — summarize outcomes and recommend a safe next action
|
|
34
|
+
- `qdash_degradation_report`, `qdash_plan_calibration`, `qdash_validate_calibration` — inspect drift, plan work, and validate results
|
|
35
|
+
3. Write-oriented workflow tools, only after explicit confirmation:
|
|
36
|
+
- `qdash_create_agent_session`, `qdash_submit_agent_action`, `qdash_execute_agent_action` — create or execute a scoped agent workflow
|
|
37
|
+
- `qdash_commit_agent_candidate`, `qdash_commit_agent_campaign_candidates` — commit reviewed candidate parameters
|
|
38
|
+
- `qdash_apply_agent_candidate_commit` — apply a reviewed candidate commit
|
|
39
|
+
- `qdash_create_forum_post`, `qdash_update_forum_post` — create or update Forum content
|
|
40
|
+
- `qdash_create_forum_evidence_reply`, `qdash_create_forum_image_reply` — publish previously reviewed evidence replies
|
|
41
|
+
4. Agent workflow state tools:
|
|
42
|
+
- `qdash_get_agent_session`, `qdash_get_agent_action`, `qdash_list_agent_actions`, `qdash_wait_agent_action` — inspect agent workflow state
|
|
43
|
+
- `qdash_list_agent_action_candidates`, `qdash_get_agent_candidate_commit`, `qdash_wait_agent_candidate_apply` — inspect candidates and apply status
|
|
44
|
+
5. `qdash_query` — fallback for read-only operations without a dedicated tool.
|
|
45
|
+
6. `qdash_raw_get` — last-resort read-only GET for an uncovered endpoint.
|
|
58
46
|
|
|
59
47
|
## Session context
|
|
60
48
|
|
|
49
|
+
When running in pi CLI, use `qdash_config_info` if the profile or non-secret connection settings are unclear.
|
|
50
|
+
|
|
61
51
|
Use these commands to make pi behave like a QDash-specific harness with persistent session-local context:
|
|
62
52
|
|
|
63
53
|
```text
|
|
@@ -76,6 +66,20 @@ Use these commands to make pi behave like a QDash-specific harness with persiste
|
|
|
76
66
|
|
|
77
67
|
Prefer the current context when the user has already selected a profile/chip/session. Tools use that context when parameters are omitted.
|
|
78
68
|
|
|
69
|
+
## Cooldown-aware investigations
|
|
70
|
+
|
|
71
|
+
Treat cooldown identity as mandatory investigation context whenever comparing calibration results, coherence metrics, drift, failures, or Forum evidence across time:
|
|
72
|
+
|
|
73
|
+
1. Call `qdash_list_cooldowns` for the chip early in the investigation and record the relevant `cooldown_id`, `started_at`, and `ended_at` boundaries.
|
|
74
|
+
2. Assign every result or Forum observation used in a comparison to a cooldown. Prefer an explicit `cooldown_id`; when it is absent, infer membership only from the chip association and timestamp boundaries, and label it as inferred.
|
|
75
|
+
3. Do not describe values from different cooldowns as one continuous degradation, recovery, or before/after trend. Partition the evidence by cooldown first. Cross-cooldown comparison is allowed only when it is explicitly identified as such.
|
|
76
|
+
4. State plainly whether the compared evidence comes from the same cooldown, different cooldowns, or an unresolved cooldown context. Include the cooldown IDs in the report and in Forum evidence replies when relevant.
|
|
77
|
+
5. Same cooldown does not guarantee identical measurement conditions. If cabling, attenuation, instruments, or wiring may have changed, inspect `qdash_get_cooldown_wiring` with history or `qdash_list_cooldown_wiring_events`, then distinguish a cooldown boundary from an in-cooldown wiring change.
|
|
78
|
+
6. Do not treat a temporary disconnect/reconnect as a new cooldown unless QDash records a new cooldown. Describe it as an in-cooldown wiring event and report whether the wiring was nominally restored.
|
|
79
|
+
7. Prefer same-cooldown, temporally adjacent measurements for physical interpretation. Older-cooldown evidence may provide context but must not be used to explain a current-cooldown anomaly without an explicit caveat.
|
|
80
|
+
|
|
81
|
+
Before publishing investigated evidence, verify that every date-based claim respects these rules.
|
|
82
|
+
|
|
79
83
|
## Generic timeseries comparison
|
|
80
84
|
|
|
81
85
|
Use `qdash_compare_timeseries` when the investigation needs to align multiple
|
|
@@ -116,8 +120,8 @@ If `QDASH_BASE_URL` is set and no profile is specified, the tools default to env
|
|
|
116
120
|
|
|
117
121
|
When the user wants to preserve an investigated observation in QDash forum/notes:
|
|
118
122
|
|
|
119
|
-
1. Inspect the task result, task figure, timeseries/history,
|
|
120
|
-
2. Summarize the observation as evidence, not as an automatic calibration decision.
|
|
123
|
+
1. Inspect the task result, task figure, timeseries/history, related Forum context, and cooldown membership first.
|
|
124
|
+
2. Summarize the observation as evidence, not as an automatic calibration decision. State whether compared observations are from the same cooldown, and separate in-cooldown wiring changes from cooldown boundaries.
|
|
121
125
|
3. Prefer replying to an existing target/coupling forum thread when one exists.
|
|
122
126
|
4. Use `qdash_create_forum_evidence_reply` for task-result evidence so figures are embedded as QDash UI image blocks (`/api/executions/figure?path=...`) and visible in the forum.
|
|
123
127
|
5. For locally generated analysis images, call `qdash_preview_forum_image_reply` first, show the exact paths and reply text, then use `qdash_create_forum_image_reply` only after explicit confirmation. Supported images are PNG, JPEG, GIF, and WebP up to 5 MB each.
|
|
@@ -9,7 +9,7 @@ metadata:
|
|
|
9
9
|
maturity: experimental
|
|
10
10
|
safety_level: operational-write-gated
|
|
11
11
|
default_mode: one-target-one-action
|
|
12
|
-
source_of_truth: pi-qdash skills
|
|
12
|
+
source_of_truth: procedures in pi-qdash skills; task physics and interpretation in qdash-task-knowledge
|
|
13
13
|
preferred_qubit_recovery_recipe: CheckRabi -> CheckChevron -> Configure -> CheckRabi
|
|
14
14
|
requires_confirmation_for:
|
|
15
15
|
- agent session creation
|
|
@@ -26,28 +26,32 @@ metadata:
|
|
|
26
26
|
|
|
27
27
|
# QDash Calibration Agent
|
|
28
28
|
|
|
29
|
-
This skill defines how pi should behave as a conservative, confirmation-gated calibration execution agent. It
|
|
29
|
+
This skill defines how pi should behave as a conservative, confirmation-gated calibration execution agent. It orchestrates safe operational steps after diagnosis. Task physics, expected results, and failure modes come from QDash task knowledge; this skill owns procedure and safety gates.
|
|
30
30
|
|
|
31
31
|
## Core principles
|
|
32
32
|
|
|
33
33
|
- Work one target at a time: one qubit or one coupling per action/session when possible.
|
|
34
34
|
- Diagnose before changing parameters.
|
|
35
|
-
-
|
|
35
|
+
- Establish cooldown identity before interpreting history: partition evidence by `cooldown_id`, never present different cooldowns as one continuous trend, and distinguish cooldown boundaries from in-cooldown wiring changes.
|
|
36
|
+
- Prefer read-only inspection first: dashboard, cooldowns and wiring events, failed task results, history, figures, forum posts, and task knowledge when available.
|
|
36
37
|
- Use narrow agent session policies with the smallest allowed task/action/parameter scope.
|
|
37
38
|
- Do not commit or apply parameter candidates until a validation task succeeds and the user explicitly confirms.
|
|
38
39
|
- Avoid blind parameter sweeps. If two conservative probes fail, step back to a diagnostic task.
|
|
39
|
-
- Record
|
|
40
|
+
- Record task-specific lessons as task-knowledge cases; update this skill only for reusable procedure or safety guidance.
|
|
40
41
|
|
|
41
42
|
## Standard workflow
|
|
42
43
|
|
|
43
44
|
1. Establish context:
|
|
44
45
|
- profile and chip
|
|
46
|
+
- active/relevant `cooldown_id` and its time boundaries via `qdash_list_cooldowns`
|
|
47
|
+
- any in-cooldown wiring changes relevant to the target
|
|
45
48
|
- failed task(s)
|
|
46
49
|
- qid/coupling_id
|
|
47
50
|
- recent executions and open forum/issue context
|
|
48
51
|
2. Read evidence:
|
|
49
52
|
- `qdash_list_task_results`
|
|
50
53
|
- `qdash_get_task_result`
|
|
54
|
+
- `qdash_get_task_knowledge` for every task whose result will be interpreted
|
|
51
55
|
- `qdash_get_task_figures` when figures exist
|
|
52
56
|
- forum posts for the target when relevant
|
|
53
57
|
3. Make a one-step plan.
|
|
@@ -61,7 +65,7 @@ This skill defines how pi should behave as a conservative, confirmation-gated ca
|
|
|
61
65
|
|
|
62
66
|
### CheckRabi returns non-finite frequency, NaN, or low R²
|
|
63
67
|
|
|
64
|
-
|
|
68
|
+
Read `CheckRabi` and `CheckChevron` with `qdash_get_task_knowledge` before interpreting the failure or proposing recovery. Do not repeatedly perturb parameters without diagnosis.
|
|
65
69
|
|
|
66
70
|
Canonical recovery sequence:
|
|
67
71
|
|
|
@@ -78,26 +82,9 @@ Recommended sequence:
|
|
|
78
82
|
5. If successful, inspect candidates and only then consider committing/applying parameters with explicit user confirmation.
|
|
79
83
|
6. If still failing after `Configure`, request human review and inspect raw/figure data.
|
|
80
84
|
|
|
81
|
-
Known successful pattern:
|
|
82
|
-
|
|
83
|
-
- Q33 on mackerel / `144Qv1`, 2026-07-14:
|
|
84
|
-
- repeated `CheckRabi` failures with `non-finite frequency: nan`
|
|
85
|
-
- `CheckChevron` succeeded and estimated:
|
|
86
|
-
- `qubit_frequency = 4.186021437949582 GHz`
|
|
87
|
-
- `control_amplitude = 0.196626929963469 a.u.`
|
|
88
|
-
- `Configure` completed
|
|
89
|
-
- `CheckRabi` then completed with the CheckChevron estimates:
|
|
90
|
-
- `rabi_frequency = 12.664970037417886 MHz`
|
|
91
|
-
- `control_amplitude = 0.19406572753680693 a.u.`
|
|
92
|
-
|
|
93
85
|
### CheckChevron interpretation and suggestions
|
|
94
86
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
- Clear vertex/fringes: use estimated `qubit_frequency` and `control_amplitude`, then run `Configure -> CheckRabi` for validation.
|
|
98
|
-
- Faint fringes: suspect insufficient drive, readout fidelity, or initialization/readout contrast; suggest readout diagnostics before parameter commits.
|
|
99
|
-
- No visible chevron: inspect readout path first (`CheckReadoutFrequency`, `ReadoutClassification`) or request human review.
|
|
100
|
-
- Asymmetric/double chevron: suspect TLS, higher-level transitions, AC Stark shift, or frequency collision; avoid committing simple Rabi outputs without review.
|
|
87
|
+
Read `CheckChevron` with `qdash_get_task_knowledge` before judging its figure, estimates, expected curve, or failure mode.
|
|
101
88
|
|
|
102
89
|
If `CheckChevron` fails:
|
|
103
90
|
|
|
@@ -106,36 +93,11 @@ If `CheckChevron` fails:
|
|
|
106
93
|
3. Classify the failure message and input/output parameters.
|
|
107
94
|
4. Suggest the next diagnostic, but require user confirmation before another operational action.
|
|
108
95
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
- `Qubit frequency too low/high`, boundary hit, or fitted frequency outside normal operating range:
|
|
112
|
-
- Treat the Chevron estimate as unsafe.
|
|
113
|
-
- Do not commit/apply candidates.
|
|
114
|
-
- Do not run `Configure -> CheckRabi` from this estimate.
|
|
115
|
-
- Suggest `CheckQubitSpectroscopy`, coarse frequency search review, or human figure review.
|
|
116
|
-
- Abnormally large `coarse_control_amplitude`:
|
|
117
|
-
- Suspect the coarse search latched onto a wrong transition, poor readout contrast, or an invalid operating point.
|
|
118
|
-
- Suggest spectroscopy/readout diagnostics rather than stronger drive.
|
|
119
|
-
- Failed fit but visually plausible chevron:
|
|
120
|
-
- Ask the user to inspect figures.
|
|
121
|
-
- Consider adjusted scan bounds only with explicit user guidance.
|
|
122
|
-
- Faint/washed-out chevron:
|
|
123
|
-
- Suggest `ReadoutClassification`, `CheckReadoutFrequency`, and initialization/readout checks.
|
|
124
|
-
|
|
125
|
-
Known failed pattern:
|
|
126
|
-
|
|
127
|
-
- Q35 on mackerel / `144Qv1`, 2026-07-14:
|
|
128
|
-
- repeated `CheckRabi` failures with `non-finite frequency: nan`
|
|
129
|
-
- `CheckChevron` failed with `Qubit frequency too low for qid=35: 2.759894 GHz < 3.0 GHz`
|
|
130
|
-
- input `coarse_qubit_frequency = 2.894185298591617 GHz`
|
|
131
|
-
- input `coarse_control_amplitude = 0.5623413251903492 a.u.`
|
|
132
|
-
- Suggested action: stop, inspect figures, and investigate spectroscopy/coarse frequency/readout state before any Configure/Rabi retry.
|
|
96
|
+
Use the returned task knowledge to choose the next diagnostic. Treat unsafe estimates as non-committable, stop before `Configure -> CheckRabi`, and require confirmation for any additional task.
|
|
133
97
|
|
|
134
98
|
### CheckT2Echo failures
|
|
135
99
|
|
|
136
|
-
|
|
137
|
-
- If `T2_echo` is much shorter than `2*T1`, suspect noise/refocusing issues.
|
|
138
|
-
- Verify π/π/2 pulses before treating echo as a pure coherence problem.
|
|
100
|
+
Read `CheckT2Echo`, `CheckT1`, and `CheckRamsey` with `qdash_get_task_knowledge`, then compare their recent results before choosing a diagnostic.
|
|
139
101
|
|
|
140
102
|
## Coupling / two-qubit recovery rules
|
|
141
103
|
|
|
@@ -150,9 +112,7 @@ For `ZX90InterleavedRandomizedBenchmarking` or two-qubit validation failures, do
|
|
|
150
112
|
5. `CheckBellStateTomography`
|
|
151
113
|
6. then RB validation
|
|
152
114
|
|
|
153
|
-
Treat `completed` as execution status, not proof of quality.
|
|
154
|
-
|
|
155
|
-
If CR rotation is weak, inspect qubit detuning/frequency collisions and coupling history before increasing CR amplitude.
|
|
115
|
+
Treat `completed` as execution status, not proof of quality. Before interpreting Bell, tomography, coherence-limit, CR, ZX90, or IRB output, read each relevant task with `qdash_get_task_knowledge`; then correlate the returned criteria with figures and same-cooldown history.
|
|
156
116
|
|
|
157
117
|
## Session policy guidelines
|
|
158
118
|
|
|
@@ -22,9 +22,12 @@ checks.
|
|
|
22
22
|
move together. The sensor itself may be a proxy for an unmeasured actuator,
|
|
23
23
|
vibration, electrical noise, magnetic noise, or control cycle.
|
|
24
24
|
- Count observed cycles, not raw sample points, when judging periodic evidence.
|
|
25
|
+
- Resolve cooldown boundaries before interpreting drift or shared periodicity. Analyze each cooldown separately by default; never smooth, interpolate, correlate, or fit a period across a cooldown boundary unless an explicit cross-cooldown comparison is intended and clearly reported.
|
|
25
26
|
|
|
26
27
|
## Workflow
|
|
27
28
|
|
|
29
|
+
When a compared QDash series comes from a task-specific output, call `qdash_get_task_knowledge` for that task before assigning physical meaning to its values, expected behavior, or failure modes.
|
|
30
|
+
|
|
28
31
|
### 1. Fix the investigation scope
|
|
29
32
|
|
|
30
33
|
Record the reusable scope with `/qdash-investigation-setup` when multiple
|
|
@@ -32,6 +35,8 @@ comparison passes are expected. The JSON context accepts arbitrary QDash
|
|
|
32
35
|
series, CSV mappings, window/timezone, and transform defaults. Record:
|
|
33
36
|
|
|
34
37
|
- QDash profile and chip
|
|
38
|
+
- cooldown IDs and start/end boundaries from `qdash_list_cooldowns`
|
|
39
|
+
- any in-cooldown wiring events that overlap the window
|
|
35
40
|
- metrics and target IDs
|
|
36
41
|
- tags
|
|
37
42
|
- start/end timestamps
|
|
@@ -45,7 +50,9 @@ a timezone from the host machine.
|
|
|
45
50
|
### 2. Inspect source integrity
|
|
46
51
|
|
|
47
52
|
Before comparing, use `qdash_inspect_timeseries_csv` for local files whose
|
|
48
|
-
schema or time encoding is not already established.
|
|
53
|
+
schema or time encoding is not already established. Use `qdash_list_cooldowns`
|
|
54
|
+
to split the requested window at cooldown boundaries, and inspect cooldown
|
|
55
|
+
wiring events when hardware conditions may have changed. Then:
|
|
49
56
|
|
|
50
57
|
- verify first/last timestamps and overlap
|
|
51
58
|
- check source point counts and cadence
|
|
@@ -17,7 +17,8 @@ Use this skill when investigating coupling-level calibration quality, especially
|
|
|
17
17
|
|
|
18
18
|
- Treat `completed` as execution status, not proof of calibration quality.
|
|
19
19
|
- Diagnose from evidence before suggesting operational actions.
|
|
20
|
-
-
|
|
20
|
+
- Resolve cooldown membership before comparing calibrations or coherence limits. Keep different cooldowns separate, and distinguish a cooldown boundary from an in-cooldown wiring change.
|
|
21
|
+
- Prefer read-only tools first: `qdash_list_cooldowns`, `qdash_target_report`, `qdash_list_task_results`, `qdash_get_task_result`, `qdash_analyze_figure_json`, and `qdash_get_task_figures`.
|
|
21
22
|
- Do not rerun RB first when validation quality is suspicious. Walk back through prerequisites.
|
|
22
23
|
- Do not commit or apply candidates without explicit user confirmation, and only after downstream validation.
|
|
23
24
|
|
|
@@ -25,8 +26,8 @@ Use this skill when investigating coupling-level calibration quality, especially
|
|
|
25
26
|
|
|
26
27
|
For a coupling `cA-B`:
|
|
27
28
|
|
|
28
|
-
1. Build context with `qdash_target_report
|
|
29
|
-
2. Inspect the latest tasks in this chain:
|
|
29
|
+
1. Build context with `qdash_list_cooldowns`, `qdash_target_report`, and recent task results for the coupling. Record the cooldown ID for each result and inspect wiring events when measurement conditions may have changed.
|
|
30
|
+
2. Inspect the latest same-cooldown tasks in this chain by default, and call `qdash_get_task_knowledge` for each task before interpreting its outputs or figures:
|
|
30
31
|
- `CheckCrossResonance`
|
|
31
32
|
- `CreateZX90`
|
|
32
33
|
- `CheckZX90`
|
|
@@ -45,51 +46,9 @@ For a coupling `cA-B`:
|
|
|
45
46
|
|
|
46
47
|
## Interpretation rules
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
Use `qdash_get_task_knowledge` for `CheckCrossResonance`, `CheckZX90`, `CheckBellState`, `CheckBellStateTomography`, `Check2QGateCoherenceLimit`, and `ZX90InterleavedRandomizedBenchmarking` as applicable. Apply the returned expected-result descriptions, criteria, failure modes, and check questions to the measured outputs.
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
- Bell-state tomography fidelity is below ~0.8.
|
|
53
|
-
- IRB fidelity has a large uncertainty/error bar, or `n_trials` is small.
|
|
54
|
-
- Coherence-limit fidelity is high but Bell/IRB fidelity is much lower.
|
|
55
|
-
- `CheckZX90` repeated-pulse traces do not show a stable/consistent response.
|
|
56
|
-
- CR parameter generation succeeds but `cr_amplitude` is near saturation or `zx_rotation_rate` is very small.
|
|
57
|
-
|
|
58
|
-
### Coherence limit gap
|
|
59
|
-
|
|
60
|
-
If `two_qubit_gate_coherence_limit` is high but measured Bell/IRB fidelity is low, do not attribute the issue primarily to T1/T2. Suspect control/calibration issues such as:
|
|
61
|
-
|
|
62
|
-
- ZX90 angle error
|
|
63
|
-
- CR phase error
|
|
64
|
-
- cancel-pulse amplitude/phase mismatch
|
|
65
|
-
- rotary compensation mismatch
|
|
66
|
-
- readout/classification contribution to validation figures
|
|
67
|
-
|
|
68
|
-
### Bell tomography signals
|
|
69
|
-
|
|
70
|
-
For a Bell target resembling `( |00> + |11> ) / sqrt(2)`:
|
|
71
|
-
|
|
72
|
-
- Large `|10>` or `|01>` population suggests population/conditional-rotation error, not just dephasing.
|
|
73
|
-
- Weak `|00><11|` coherence suggests phase, dephasing, or preparation error.
|
|
74
|
-
- Large imaginary coherence can indicate phase-compensation error.
|
|
75
|
-
|
|
76
|
-
Use the heatmap summaries from `qdash_analyze_figure_json` as numeric evidence. Do not overfit a single plot; correlate with `CheckZX90` and IRB.
|
|
77
|
-
|
|
78
|
-
### CheckZX90 repeated-pulse signals
|
|
79
|
-
|
|
80
|
-
Look for stable repeated-pulse behavior. Warnings include:
|
|
81
|
-
|
|
82
|
-
- Large scatter or non-decaying erratic points after the first few repetitions.
|
|
83
|
-
- Large first-step contrast followed by a non-zero offset.
|
|
84
|
-
- Different qualitative behavior between control and target qubit plots.
|
|
85
|
-
|
|
86
|
-
These symptoms point toward angle/phase/cancel/rotary issues and should be investigated before trusting IRB.
|
|
87
|
-
|
|
88
|
-
### IRB caveats
|
|
89
|
-
|
|
90
|
-
- A `completed` IRB with large error bar is weak evidence.
|
|
91
|
-
- Small `n_trials` should be reported explicitly.
|
|
92
|
-
- If Bell tomography is poor, do not use IRB alone as a pass signal.
|
|
51
|
+
Treat `completed` only as execution status. Correlate task knowledge with `qdash_analyze_figure_json`, same-cooldown history, and adjacent validation tasks; do not overfit one plot or use IRB alone as a pass signal.
|
|
93
52
|
|
|
94
53
|
## Recommended action sequence
|
|
95
54
|
|
|
@@ -107,19 +66,4 @@ Inspect figures/results
|
|
|
107
66
|
|
|
108
67
|
Each operational step requires explicit confirmation. Validate Bell/tomography before using IRB as the final quality signal.
|
|
109
68
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
Symptoms observed:
|
|
113
|
-
|
|
114
|
-
- `CheckCrossResonance` completed with `zx_rotation_rate ~ 1.69e-3`.
|
|
115
|
-
- `Check2QGateCoherenceLimit` reported ~0.978.
|
|
116
|
-
- `CheckBellStateTomography` reported `bell_state_fidelity ~ 0.60`.
|
|
117
|
-
- Bell tomography had high `|10>` component/population (~0.29) and non-ideal coherence.
|
|
118
|
-
- `ZX90InterleavedRandomizedBenchmarking` completed with `zx90_gate_fidelity ~0.94` but large error (~0.087) and `n_trials=10`.
|
|
119
|
-
- `CheckZX90` repeated-pulse traces were not clean/stable.
|
|
120
|
-
|
|
121
|
-
Interpretation:
|
|
122
|
-
|
|
123
|
-
- This is not primarily coherence-limited.
|
|
124
|
-
- Suspect ZX90 angle/phase/cancel/rotary calibration quality.
|
|
125
|
-
- Prefer walking back through `CheckCrossResonance -> CreateZX90 -> CheckZX90`, then validate with Bell tomography before trusting IRB.
|
|
69
|
+
Historical postmortem cases belong in QDash task knowledge. Retrieve them through `qdash_get_task_knowledge` rather than encoding device-specific values in this procedural skill.
|