@oqtopus-team/pi-qdash 0.1.5 → 0.1.6
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 -1
- package/extensions/qdash.ts +47 -48
- package/package.json +5 -2
- package/skills/qdash/SKILL.md +16 -2
- package/skills/qdash-calibration-agent/SKILL.md +4 -1
- package/skills/qdash-timeseries-diagnosis/SKILL.md +6 -1
- package/skills/qdash-two-qubit-calibration-diagnosis/SKILL.md +4 -3
package/README.md
CHANGED
|
@@ -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
|
|
|
@@ -397,6 +403,9 @@ async function defaultChipId(client: QDashClient, chipId?: string): Promise<stri
|
|
|
397
403
|
return chipId ?? currentContext.chipId ?? client.getDefaultChipId();
|
|
398
404
|
}
|
|
399
405
|
|
|
406
|
+
// Keep arbitrary GET access isolated for qdash_raw_get and legacy filters that are
|
|
407
|
+
// not represented in the generated OpenAPI surface. Normal operations should use
|
|
408
|
+
// QDashClient's high-level methods or client.api so upgrades remain type-checked.
|
|
400
409
|
async function rawGet<T>(client: QDashClient, path: string, query?: Record<string, unknown>): Promise<T> {
|
|
401
410
|
return (client as unknown as { get<T>(path: string, query?: Record<string, unknown>): Promise<T> }).get(path, cleanQuery(query));
|
|
402
411
|
}
|
|
@@ -472,19 +481,6 @@ function requireValue(value: string | undefined, name: string): string {
|
|
|
472
481
|
return value;
|
|
473
482
|
}
|
|
474
483
|
|
|
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
484
|
type CooldownWiringParams = {
|
|
489
485
|
profile?: string;
|
|
490
486
|
configPath?: string;
|
|
@@ -502,7 +498,7 @@ type WiringInsightParams = CooldownWiringParams & {
|
|
|
502
498
|
color?: boolean;
|
|
503
499
|
};
|
|
504
500
|
|
|
505
|
-
function newestCooldown(cooldowns:
|
|
501
|
+
function newestCooldown(cooldowns: CooldownResponse[]): CooldownResponse | undefined {
|
|
506
502
|
return [...cooldowns].sort((a, b) => {
|
|
507
503
|
const activeDifference = Number(a.ended_at != null) - Number(b.ended_at != null);
|
|
508
504
|
if (activeDifference !== 0) return activeDifference;
|
|
@@ -514,15 +510,15 @@ async function resolveCooldownWiring(params: CooldownWiringParams) {
|
|
|
514
510
|
params = applyQDashContext(params);
|
|
515
511
|
const client = await makeClient(params);
|
|
516
512
|
let selection: string;
|
|
517
|
-
let cooldown:
|
|
513
|
+
let cooldown: CooldownResponse;
|
|
518
514
|
let resolvedChipId = params.chipId ?? currentContext.chipId;
|
|
519
515
|
|
|
520
516
|
if (params.cooldownId) {
|
|
521
|
-
cooldown = await
|
|
517
|
+
cooldown = await client.api.getCooldown(params.cooldownId);
|
|
522
518
|
selection = "explicit cooldownId";
|
|
523
519
|
} else {
|
|
524
520
|
resolvedChipId = params.chipId ?? (params.cryoId ? undefined : await defaultChipId(client));
|
|
525
|
-
const response = await
|
|
521
|
+
const response = await client.api.listCooldowns({
|
|
526
522
|
cryo_id: params.cryoId,
|
|
527
523
|
chip_id: resolvedChipId,
|
|
528
524
|
});
|
|
@@ -531,7 +527,7 @@ async function resolveCooldownWiring(params: CooldownWiringParams) {
|
|
|
531
527
|
const scope = params.cryoId ? `cryo ${params.cryoId}` : `chip ${resolvedChipId}`;
|
|
532
528
|
throw new Error(`No cooldown containing wiring information was found for ${scope}`);
|
|
533
529
|
}
|
|
534
|
-
cooldown = await
|
|
530
|
+
cooldown = await client.api.getCooldown(selected.cooldown_id);
|
|
535
531
|
selection = params.cryoId ? "active/newest cooldown for cryo" : "active/newest cooldown for chip";
|
|
536
532
|
}
|
|
537
533
|
|
|
@@ -539,14 +535,14 @@ async function resolveCooldownWiring(params: CooldownWiringParams) {
|
|
|
539
535
|
const wiringInfo = typeof cooldown.wiring_info === "string" ? cooldown.wiring_info.trim() : "";
|
|
540
536
|
const includeBlocks = params.includeBlocks === true || !wiringInfo;
|
|
541
537
|
const history = params.includeHistory
|
|
542
|
-
? await
|
|
538
|
+
? await client.api.listCooldownWiringEvents(cooldown.cooldown_id, {
|
|
543
539
|
limit: params.historyLimit ?? 20,
|
|
544
540
|
skip: 0,
|
|
545
541
|
})
|
|
546
542
|
: undefined;
|
|
547
543
|
let cryostat: unknown;
|
|
548
544
|
try {
|
|
549
|
-
cryostat = await
|
|
545
|
+
cryostat = await client.api.getCryostat(cooldown.cryo_id);
|
|
550
546
|
} catch {
|
|
551
547
|
// Wiring remains useful on servers where cryostat detail is not accessible.
|
|
552
548
|
}
|
|
@@ -594,9 +590,9 @@ async function buildDashboard(params: { profile?: string; configPath?: string; u
|
|
|
594
590
|
const chipId = await defaultChipId(client, params.chipId);
|
|
595
591
|
const [chips, openIssues, recentExecutions, failedTaskResults, provenanceStats] = await Promise.allSettled([
|
|
596
592
|
client.listChips(),
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
593
|
+
client.api.listIssues({ is_closed: false, limit }),
|
|
594
|
+
client.api.listExecutions({ chip_id: chipId, limit }),
|
|
595
|
+
client.api.listTaskResults({ chip_id: chipId, status: "failed", limit }),
|
|
600
596
|
client.getProvenanceStats(),
|
|
601
597
|
]);
|
|
602
598
|
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 +734,7 @@ async function buildRecentCalibrationSummary(params: { profile?: string; configP
|
|
|
738
734
|
const chipId = await defaultChipId(client, params.chipId);
|
|
739
735
|
const end = new Date();
|
|
740
736
|
const start = new Date(end.getTime() - (params.withinHours ?? 24) * 3600_000);
|
|
741
|
-
const payload = await
|
|
737
|
+
const payload = await client.api.listTaskResults({ chip_id: chipId, start_from: start.toISOString(), start_to: end.toISOString(), limit: params.limit ?? 30 });
|
|
742
738
|
const items = arrayFromPayload(payload).filter((item): item is Record<string, unknown> => Boolean(item) && typeof item === "object");
|
|
743
739
|
const byTarget = new Map<string, Record<string, unknown>[]>();
|
|
744
740
|
for (const item of items) {
|
|
@@ -939,7 +935,7 @@ async function buildTargetOperationsReport(params: { profile?: string; configPat
|
|
|
939
935
|
const [latestTarget, results, issues, forumPosts] = await Promise.all([
|
|
940
936
|
kind === "qubit" ? client.getChipQubit(chipId, id) : client.getChipCoupling(chipId, id),
|
|
941
937
|
client.listTaskResults({ chipId, qid, couplingId, startAt: start.toISOString(), endAt: end.toISOString(), limit }),
|
|
942
|
-
|
|
938
|
+
client.api.listIssues({ is_closed: false, limit: 100 }),
|
|
943
939
|
client.listForumPosts({ chipId, status: "open", targetType: kind, targetId: id, limit }),
|
|
944
940
|
]);
|
|
945
941
|
const recentResults = arrayFromPayload(results).filter((item): item is Record<string, unknown> => Boolean(item) && typeof item === "object");
|
|
@@ -1123,7 +1119,7 @@ async function buildCalibrationValidation(params: { profile?: string; configPath
|
|
|
1123
1119
|
const task = await client.getTaskResult(params.taskId) as unknown as Record<string, unknown>;
|
|
1124
1120
|
const status = firstString(task, ["status"])?.toLowerCase() ?? "unknown";
|
|
1125
1121
|
const figurePaths = taskFigurePaths(task, 20);
|
|
1126
|
-
const issuesPayload = await
|
|
1122
|
+
const issuesPayload = await client.api.getTaskResultIssues(params.taskId).catch(() => []);
|
|
1127
1123
|
const issues = arrayFromPayload(issuesPayload).filter((item): item is Record<string, unknown> => Boolean(item) && typeof item === "object");
|
|
1128
1124
|
const afterExecutionId = firstString(task, ["execution_id", "executionId"]);
|
|
1129
1125
|
const comparison = params.beforeExecutionId && afterExecutionId
|
|
@@ -1256,10 +1252,10 @@ async function buildDashboardInsights(params: { profile?: string; configPath?: s
|
|
|
1256
1252
|
const start = new Date(end.getTime() - (params.withinHours ?? 168) * 3600_000);
|
|
1257
1253
|
const [forums, issues, failed, metrics, aiInsights] = await Promise.allSettled([
|
|
1258
1254
|
client.listForumPosts({ chipId, status: "open", limit }),
|
|
1259
|
-
|
|
1260
|
-
|
|
1255
|
+
client.api.listIssues({ is_closed: false, limit }),
|
|
1256
|
+
client.api.listTaskResults({ chip_id: chipId, status: "failed", start_from: start.toISOString(), start_to: end.toISOString(), limit }),
|
|
1261
1257
|
client.getChipMetrics(chipId),
|
|
1262
|
-
|
|
1258
|
+
client.api.getDashboardAiInsights(chipId, { latest_only: true, start_at: start.toISOString(), end_at: end.toISOString() }),
|
|
1263
1259
|
]);
|
|
1264
1260
|
const value = <T>(result: PromiseSettledResult<T>): T | undefined => result.status === "fulfilled" ? result.value : undefined;
|
|
1265
1261
|
const insightMap = new Map<string, DashboardInsight>();
|
|
@@ -1485,19 +1481,19 @@ async function executeQuery(params: QDashQueryParams) {
|
|
|
1485
1481
|
case "chip_qubit": return client.getChipQubit(await defaultChipId(client, params.chipId), requireValue(params.qid, "qid"));
|
|
1486
1482
|
case "chip_couplings": return client.listChipCouplings(await defaultChipId(client, params.chipId), { limit: params.limit, offset: params.offset });
|
|
1487
1483
|
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
|
|
1484
|
+
case "cryostats": return client.api.listCryostats();
|
|
1485
|
+
case "cryostat": return client.api.getCryostat(requireValue(params.cryoId, "cryoId"));
|
|
1486
|
+
case "cooldowns": return client.api.listCooldowns({ cryo_id: params.cryoId, chip_id: params.chipId });
|
|
1487
|
+
case "cooldown": return client.api.getCooldown(requireValue(params.cooldownId, "cooldownId"));
|
|
1488
|
+
case "cooldown_wiring_events": return client.api.listCooldownWiringEvents(requireValue(params.cooldownId, "cooldownId"), { limit: params.limit, skip: params.skip });
|
|
1493
1489
|
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
1490
|
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
1491
|
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
|
|
1492
|
+
case "task_note": return client.api.getTaskNote(requireValue(params.taskId, "taskId"));
|
|
1493
|
+
case "task_result_issues": return client.api.getTaskResultIssues(requireValue(params.taskId, "taskId"));
|
|
1494
|
+
case "qubit_latest": return client.api.getLatestQubitTaskResults({ chip_id: await defaultChipId(client, params.chipId), task: requireValue(params.task ?? params.taskName, "task") });
|
|
1499
1495
|
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
|
|
1496
|
+
case "coupling_latest": return client.api.getLatestCouplingTaskResults({ chip_id: await defaultChipId(client, params.chipId), task: requireValue(params.task ?? params.taskName, "task") });
|
|
1501
1497
|
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
1498
|
case "tasks": return client.listTasks(params.backend);
|
|
1503
1499
|
case "task_knowledge": return params.taskName ? client.getTaskKnowledge(params.taskName) : client.listTaskKnowledge();
|
|
@@ -1507,23 +1503,26 @@ async function executeQuery(params: QDashQueryParams) {
|
|
|
1507
1503
|
case "files_tree": return client.getFilesTree();
|
|
1508
1504
|
case "file_content": return client.getFileContent(requireValue(params.path, "path"));
|
|
1509
1505
|
case "git_status": return client.getGitStatus();
|
|
1510
|
-
case "issues": return
|
|
1511
|
-
case "issue_knowledge": return
|
|
1506
|
+
case "issues": return client.api.listIssues({ task_id: params.taskId, is_closed: params.isClosed, limit: params.limit, skip: params.skip });
|
|
1507
|
+
case "issue_knowledge": return client.api.listIssueKnowledge({ status: params.status, task_name: params.taskName, limit: params.limit, skip: params.skip });
|
|
1512
1508
|
case "flows": return client.listFlows();
|
|
1513
1509
|
case "flow": return client.getFlow(requireValue(params.flowName, "flowName"));
|
|
1514
1510
|
case "flow_templates": return client.listFlowTemplates();
|
|
1515
1511
|
case "flow_template": return client.getFlowTemplate(requireValue(params.templateId, "templateId"));
|
|
1516
|
-
case "flow_helper_files": return
|
|
1517
|
-
case "flow_helper_file": return
|
|
1512
|
+
case "flow_helper_files": return client.api.listFlowHelperFiles();
|
|
1513
|
+
case "flow_helper_file": return client.api.getFlowHelperFile(requireValue(params.filename, "filename"));
|
|
1518
1514
|
case "executions": return rawGet(client, "/executions", { chip_id: params.chipId, flow_name: params.flowName, status: params.status, skip: params.skip, limit: params.limit });
|
|
1519
1515
|
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
|
|
1516
|
+
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 });
|
|
1517
|
+
case "ai_review_runs": return client.api.listTaskResultAiReviewRuns({ chip_id: params.chipId, task_name: params.taskName, skip: params.skip, limit: params.limit });
|
|
1518
|
+
case "ai_review_run": return client.api.getTaskResultAiReviewRun(requireValue(params.reviewRunId, "reviewRunId"));
|
|
1523
1519
|
case "forum_posts": return client.listForumPosts({ status: params.status, chipId: params.chipId, limit: params.limit, skip: params.skip });
|
|
1524
1520
|
case "provenance_stats": return client.getProvenanceStats();
|
|
1525
|
-
case "provenance_history": return
|
|
1526
|
-
case "provenance_changes":
|
|
1521
|
+
case "provenance_history": return client.api.getParameterHistory({ parameter_name: requireValue(params.parameterName ?? params.parameter, "parameterName"), qid: requireValue(params.qid, "qid"), limit: params.limit });
|
|
1522
|
+
case "provenance_changes": {
|
|
1523
|
+
const parameterName = params.parameterName ?? params.parameter;
|
|
1524
|
+
return client.getRecentChanges({ parameterNames: parameterName ? [parameterName] : undefined, withinHours: params.withinHours, limit: params.limit });
|
|
1525
|
+
}
|
|
1527
1526
|
case "provenance_lineage": return client.getProvenanceLineage(requireValue(params.entityId, "entityId"));
|
|
1528
1527
|
case "provenance_impact": return client.getProvenanceImpact(requireValue(params.entityId, "entityId"));
|
|
1529
1528
|
}
|
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.6",
|
|
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
|
@@ -76,6 +76,20 @@ Use these commands to make pi behave like a QDash-specific harness with persiste
|
|
|
76
76
|
|
|
77
77
|
Prefer the current context when the user has already selected a profile/chip/session. Tools use that context when parameters are omitted.
|
|
78
78
|
|
|
79
|
+
## Cooldown-aware investigations
|
|
80
|
+
|
|
81
|
+
Treat cooldown identity as mandatory investigation context whenever comparing calibration results, coherence metrics, drift, failures, or Forum evidence across time:
|
|
82
|
+
|
|
83
|
+
1. Call `qdash_list_cooldowns` for the chip early in the investigation and record the relevant `cooldown_id`, `started_at`, and `ended_at` boundaries.
|
|
84
|
+
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.
|
|
85
|
+
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.
|
|
86
|
+
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.
|
|
87
|
+
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.
|
|
88
|
+
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.
|
|
89
|
+
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.
|
|
90
|
+
|
|
91
|
+
Before publishing investigated evidence, verify that every date-based claim respects these rules.
|
|
92
|
+
|
|
79
93
|
## Generic timeseries comparison
|
|
80
94
|
|
|
81
95
|
Use `qdash_compare_timeseries` when the investigation needs to align multiple
|
|
@@ -116,8 +130,8 @@ If `QDASH_BASE_URL` is set and no profile is specified, the tools default to env
|
|
|
116
130
|
|
|
117
131
|
When the user wants to preserve an investigated observation in QDash forum/notes:
|
|
118
132
|
|
|
119
|
-
1. Inspect the task result, task figure, timeseries/history,
|
|
120
|
-
2. Summarize the observation as evidence, not as an automatic calibration decision.
|
|
133
|
+
1. Inspect the task result, task figure, timeseries/history, related Forum context, and cooldown membership first.
|
|
134
|
+
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
135
|
3. Prefer replying to an existing target/coupling forum thread when one exists.
|
|
122
136
|
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
137
|
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.
|
|
@@ -32,7 +32,8 @@ This skill defines how pi should behave as a conservative, confirmation-gated ca
|
|
|
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.
|
|
@@ -42,6 +43,8 @@ This skill defines how pi should behave as a conservative, confirmation-gated ca
|
|
|
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
|
|
@@ -22,6 +22,7 @@ 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
|
|
|
@@ -32,6 +33,8 @@ comparison passes are expected. The JSON context accepts arbitrary QDash
|
|
|
32
33
|
series, CSV mappings, window/timezone, and transform defaults. Record:
|
|
33
34
|
|
|
34
35
|
- QDash profile and chip
|
|
36
|
+
- cooldown IDs and start/end boundaries from `qdash_list_cooldowns`
|
|
37
|
+
- any in-cooldown wiring events that overlap the window
|
|
35
38
|
- metrics and target IDs
|
|
36
39
|
- tags
|
|
37
40
|
- start/end timestamps
|
|
@@ -45,7 +48,9 @@ a timezone from the host machine.
|
|
|
45
48
|
### 2. Inspect source integrity
|
|
46
49
|
|
|
47
50
|
Before comparing, use `qdash_inspect_timeseries_csv` for local files whose
|
|
48
|
-
schema or time encoding is not already established.
|
|
51
|
+
schema or time encoding is not already established. Use `qdash_list_cooldowns`
|
|
52
|
+
to split the requested window at cooldown boundaries, and inspect cooldown
|
|
53
|
+
wiring events when hardware conditions may have changed. Then:
|
|
49
54
|
|
|
50
55
|
- verify first/last timestamps and overlap
|
|
51
56
|
- 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:
|
|
30
31
|
- `CheckCrossResonance`
|
|
31
32
|
- `CreateZX90`
|
|
32
33
|
- `CheckZX90`
|