trackops 2.0.6 → 2.2.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/README.md +307 -701
- package/bin/trackops.js +24 -16
- package/lib/config.js +265 -58
- package/lib/control.js +830 -292
- package/lib/init.js +46 -16
- package/lib/opera-bootstrap.js +85 -45
- package/lib/opera-phase-dod.js +485 -0
- package/lib/opera.js +8 -5
- package/lib/plans.js +1329 -0
- package/lib/quality-assert.js +49 -0
- package/lib/quality.js +1759 -0
- package/lib/release.js +18 -11
- package/lib/server.js +504 -192
- package/lib/skills.js +94 -41
- package/locales/en.json +249 -15
- package/locales/es.json +249 -15
- package/package.json +3 -2
- package/scripts/quality-unit-tests.js +130 -0
- package/scripts/skills-marketplace-smoke.js +156 -124
- package/scripts/smoke-tests.js +378 -71
- package/scripts/sync-skill-version.js +29 -19
- package/scripts/validate-skill.js +188 -103
- package/skills/trackops/SKILL.md +25 -7
- package/skills/trackops/locales/en/SKILL.md +25 -7
- package/skills/trackops/locales/en/references/activation.md +3 -3
- package/skills/trackops/locales/en/references/workflow.md +5 -4
- package/skills/trackops/references/activation.md +3 -3
- package/skills/trackops/references/workflow.md +5 -4
- package/skills/trackops/skill.json +29 -29
- package/skills/trackops-quality-guard/SKILL.md +78 -0
- package/skills/trackops-quality-guard/agents/openai.yaml +7 -0
- package/skills/trackops-quality-guard/locales/en/SKILL.md +78 -0
- package/skills/trackops-quality-guard/locales/en/references/commands.md +36 -0
- package/skills/trackops-quality-guard/locales/en/references/decision-policy.md +16 -0
- package/skills/trackops-quality-guard/locales/en/references/output-format.md +24 -0
- package/skills/trackops-quality-guard/references/commands.md +36 -0
- package/skills/trackops-quality-guard/references/decision-policy.md +16 -0
- package/skills/trackops-quality-guard/references/output-format.md +24 -0
- package/skills/trackops-quality-guard/skill.json +28 -0
- package/templates/skills/opera-skill/SKILL.md +12 -0
- package/templates/skills/opera-skill/locales/en/SKILL.md +12 -0
- package/templates/skills/trackops-quality-guard/SKILL.md +72 -0
- package/templates/skills/trackops-quality-guard/locales/en/SKILL.md +72 -0
- package/templates/skills/trackops-quality-guard/locales/en/references/commands.md +30 -0
- package/templates/skills/trackops-quality-guard/locales/en/references/decision-policy.md +14 -0
- package/templates/skills/trackops-quality-guard/locales/en/references/output-format.md +21 -0
- package/templates/skills/trackops-quality-guard/references/commands.md +30 -0
- package/templates/skills/trackops-quality-guard/references/decision-policy.md +14 -0
- package/templates/skills/trackops-quality-guard/references/output-format.md +21 -0
- package/ui/js/api.js +93 -26
- package/ui/js/app.js +13 -7
- package/ui/js/filters.js +49 -29
- package/ui/js/time-tracker.js +41 -28
- package/ui/js/views/board.js +22 -14
- package/ui/js/views/dashboard.js +206 -49
- package/ui/js/views/execution.js +7 -3
- package/ui/js/views/plans.js +284 -0
- package/ui/js/views/scrum.js +25 -13
- package/ui/js/views/sidebar.js +9 -8
- package/ui/js/views/tasks.js +238 -134
package/lib/skills.js
CHANGED
|
@@ -8,15 +8,16 @@ const { t, setLocale } = require("./i18n");
|
|
|
8
8
|
const { resolveSkillFile } = require("./resources");
|
|
9
9
|
const fmt = require("./cli-format");
|
|
10
10
|
|
|
11
|
-
const SKILLS_TEMPLATES_DIR = path.join(__dirname, "..", "templates", "skills");
|
|
12
|
-
const INSTALLED_SKILL_PRIORITY = [
|
|
13
|
-
"opera-skill",
|
|
14
|
-
"project-starter-skill",
|
|
15
|
-
"
|
|
16
|
-
"opera-
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
|
|
11
|
+
const SKILLS_TEMPLATES_DIR = path.join(__dirname, "..", "templates", "skills");
|
|
12
|
+
const INSTALLED_SKILL_PRIORITY = [
|
|
13
|
+
"opera-skill",
|
|
14
|
+
"project-starter-skill",
|
|
15
|
+
"trackops-quality-guard",
|
|
16
|
+
"opera-contract-auditor",
|
|
17
|
+
"opera-policy-guard",
|
|
18
|
+
"commiter",
|
|
19
|
+
"changelog-updater",
|
|
20
|
+
];
|
|
20
21
|
|
|
21
22
|
function copyDirRecursive(src, dest) {
|
|
22
23
|
fs.mkdirSync(dest, { recursive: true });
|
|
@@ -31,20 +32,62 @@ function copyDirRecursive(src, dest) {
|
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
function
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
35
|
+
function stripFrontmatterValue(value) {
|
|
36
|
+
return String(value || "").trim().replace(/^["']|["']$/g, "");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function parseFrontmatter(content) {
|
|
40
|
+
const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
41
|
+
if (!match) return {};
|
|
42
|
+
const lines = match[1].split("\n");
|
|
43
|
+
const root = {};
|
|
44
|
+
const stack = [{ indent: -1, container: root }];
|
|
45
|
+
|
|
46
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
47
|
+
const line = lines[index].replace(/\t/g, " ");
|
|
48
|
+
const trimmed = line.trim();
|
|
49
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
50
|
+
const indent = line.match(/^ */)[0].length;
|
|
51
|
+
|
|
52
|
+
while (stack.length > 1 && indent <= stack[stack.length - 1].indent) {
|
|
53
|
+
stack.pop();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const current = stack[stack.length - 1].container;
|
|
57
|
+
if (trimmed.startsWith("- ")) {
|
|
58
|
+
if (Array.isArray(current)) {
|
|
59
|
+
current.push(stripFrontmatterValue(trimmed.slice(2)));
|
|
60
|
+
}
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const sep = trimmed.indexOf(":");
|
|
65
|
+
if (sep <= 0 || Array.isArray(current)) continue;
|
|
66
|
+
|
|
67
|
+
const key = stripFrontmatterValue(trimmed.slice(0, sep));
|
|
68
|
+
const rawValue = trimmed.slice(sep + 1).trim();
|
|
69
|
+
if (rawValue) {
|
|
70
|
+
current[key] = stripFrontmatterValue(rawValue);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let child = {};
|
|
75
|
+
for (let peekIndex = index + 1; peekIndex < lines.length; peekIndex += 1) {
|
|
76
|
+
const peekLine = lines[peekIndex].replace(/\t/g, " ");
|
|
77
|
+
const peekTrimmed = peekLine.trim();
|
|
78
|
+
if (!peekTrimmed || peekTrimmed.startsWith("#")) continue;
|
|
79
|
+
const peekIndent = peekLine.match(/^ */)[0].length;
|
|
80
|
+
if (peekIndent <= indent) break;
|
|
81
|
+
child = peekTrimmed.startsWith("- ") ? [] : {};
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
current[key] = child;
|
|
86
|
+
stack.push({ indent, container: child });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return root;
|
|
90
|
+
}
|
|
48
91
|
|
|
49
92
|
function getSkillsDir(root) {
|
|
50
93
|
return config.ensureContext(root).paths.skillsDir;
|
|
@@ -54,29 +97,39 @@ function getRegistryPath(root) {
|
|
|
54
97
|
return config.ensureContext(root).paths.registryPath;
|
|
55
98
|
}
|
|
56
99
|
|
|
57
|
-
function catalogSkills() {
|
|
58
|
-
if (!fs.existsSync(SKILLS_TEMPLATES_DIR)) return [];
|
|
59
|
-
return fs.readdirSync(SKILLS_TEMPLATES_DIR, { withFileTypes: true })
|
|
60
|
-
.filter((e) => e.isDirectory())
|
|
61
|
-
.map((e) => {
|
|
62
|
-
const skillMd = path.join(SKILLS_TEMPLATES_DIR, e.name, "SKILL.md");
|
|
63
|
-
if (!fs.existsSync(skillMd)) return null;
|
|
64
|
-
const fm = parseFrontmatter(fs.readFileSync(skillMd, "utf8"));
|
|
65
|
-
return {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
100
|
+
function catalogSkills() {
|
|
101
|
+
if (!fs.existsSync(SKILLS_TEMPLATES_DIR)) return [];
|
|
102
|
+
return fs.readdirSync(SKILLS_TEMPLATES_DIR, { withFileTypes: true })
|
|
103
|
+
.filter((e) => e.isDirectory())
|
|
104
|
+
.map((e) => {
|
|
105
|
+
const skillMd = path.join(SKILLS_TEMPLATES_DIR, e.name, "SKILL.md");
|
|
106
|
+
if (!fs.existsSync(skillMd)) return null;
|
|
107
|
+
const fm = parseFrontmatter(fs.readFileSync(skillMd, "utf8"));
|
|
108
|
+
return {
|
|
109
|
+
name: e.name,
|
|
110
|
+
description: fm.description || "",
|
|
111
|
+
version: fm.metadata?.version || fm.version || "1.0",
|
|
112
|
+
triggers: Array.isArray(fm.metadata?.triggers) ? fm.metadata.triggers : [],
|
|
113
|
+
};
|
|
114
|
+
})
|
|
115
|
+
.filter(Boolean)
|
|
116
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
117
|
+
}
|
|
69
118
|
|
|
70
119
|
function installedSkills(root) {
|
|
71
120
|
const skillsDir = getSkillsDir(root);
|
|
72
121
|
if (!fs.existsSync(skillsDir)) return [];
|
|
73
122
|
const skills = fs.readdirSync(skillsDir, { withFileTypes: true })
|
|
74
|
-
.filter((e) => e.isDirectory() && fs.existsSync(path.join(skillsDir, e.name, "SKILL.md")))
|
|
75
|
-
.map((e) => {
|
|
76
|
-
const fm = parseFrontmatter(fs.readFileSync(path.join(skillsDir, e.name, "SKILL.md"), "utf8"));
|
|
77
|
-
return {
|
|
78
|
-
|
|
79
|
-
|
|
123
|
+
.filter((e) => e.isDirectory() && fs.existsSync(path.join(skillsDir, e.name, "SKILL.md")))
|
|
124
|
+
.map((e) => {
|
|
125
|
+
const fm = parseFrontmatter(fs.readFileSync(path.join(skillsDir, e.name, "SKILL.md"), "utf8"));
|
|
126
|
+
return {
|
|
127
|
+
name: e.name,
|
|
128
|
+
description: fm.description || "",
|
|
129
|
+
version: fm.metadata?.version || fm.version || "1.0",
|
|
130
|
+
};
|
|
131
|
+
})
|
|
132
|
+
.filter(Boolean);
|
|
80
133
|
skills.sort((a, b) => {
|
|
81
134
|
const ai = INSTALLED_SKILL_PRIORITY.indexOf(a.name);
|
|
82
135
|
const bi = INSTALLED_SKILL_PRIORITY.indexOf(b.name);
|
package/locales/en.json
CHANGED
|
@@ -42,10 +42,12 @@
|
|
|
42
42
|
"doc.label.completedTasks": "Completed",
|
|
43
43
|
"doc.label.inProgressTasks": "In progress",
|
|
44
44
|
"doc.label.inReviewTasks": "In review",
|
|
45
|
-
"doc.label.pendingTasks": "Pending",
|
|
46
|
-
"doc.label.blockedTasks": "Blocked",
|
|
47
|
-
"doc.label.
|
|
48
|
-
"doc.label.
|
|
45
|
+
"doc.label.pendingTasks": "Pending",
|
|
46
|
+
"doc.label.blockedTasks": "Blocked",
|
|
47
|
+
"doc.label.awaitingUserTasks": "Awaiting user confirmation",
|
|
48
|
+
"doc.label.agentInboxPending": "Pending agent instructions",
|
|
49
|
+
"doc.label.findingOpen": "open",
|
|
50
|
+
"doc.label.findingResolved": "resolved",
|
|
49
51
|
"doc.label.findingStatus": "Status",
|
|
50
52
|
"doc.label.findingDetail": "Detail",
|
|
51
53
|
"doc.label.findingImpact": "Impact",
|
|
@@ -60,7 +62,8 @@
|
|
|
60
62
|
"doc.label.noActiveTasks": "No tasks in progress at the moment.",
|
|
61
63
|
"doc.label.noReviewTasks": "No tasks in review.",
|
|
62
64
|
"doc.label.noActiveBlockers": "No active blockers.",
|
|
63
|
-
"doc.label.noHistory": "No recorded movements.",
|
|
65
|
+
"doc.label.noHistory": "No recorded movements.",
|
|
66
|
+
"doc.label.noAgentInbox": "No pending instructions for the agent.",
|
|
64
67
|
|
|
65
68
|
"cli.runtimeUpdated": "Runtime updated at {path}",
|
|
66
69
|
"cli.docsSynced": "Operational documentation synced.",
|
|
@@ -93,9 +96,11 @@
|
|
|
93
96
|
"cli.status.noReadyTasks": "No ready tasks; check blockers or dependencies.",
|
|
94
97
|
"cli.status.blockers": "Blockers:",
|
|
95
98
|
"cli.status.noBlockers": "No blockers.",
|
|
96
|
-
"cli.status.decisions": "External decisions:",
|
|
97
|
-
"cli.status.noDecisions": "None.",
|
|
98
|
-
"cli.status.
|
|
99
|
+
"cli.status.decisions": "External decisions:",
|
|
100
|
+
"cli.status.noDecisions": "None.",
|
|
101
|
+
"cli.status.agentInbox": "Agent inbox:",
|
|
102
|
+
"cli.status.noAgentInbox": "No pending instructions.",
|
|
103
|
+
"cli.status.repo": "Repository:",
|
|
99
104
|
"cli.status.branch": "Branch: {branch} | Tree: {treeStatus}",
|
|
100
105
|
"cli.status.treeClean": "clean",
|
|
101
106
|
"cli.status.treeDirty": "dirty ({staged} staged, {unstaged} unstaged, {untracked} untracked)",
|
|
@@ -122,6 +127,8 @@
|
|
|
122
127
|
"cli.next.priority": "priority",
|
|
123
128
|
"cli.next.stream": "stream",
|
|
124
129
|
"cli.next.summary": "summary",
|
|
130
|
+
"cli.next.activeTasks": "Active work:",
|
|
131
|
+
"cli.next.readyQueue": "Next ready tasks in queue:",
|
|
125
132
|
"cli.sync.dryRunWouldUpdate": "Would update: {files}",
|
|
126
133
|
"cli.sync.dryRunInSync": "All docs are already in sync.",
|
|
127
134
|
|
|
@@ -200,11 +207,22 @@
|
|
|
200
207
|
"server.invalidJson": "Invalid JSON.",
|
|
201
208
|
"server.sessionNotFound": "Session not found.",
|
|
202
209
|
"server.noActiveSession": "No active session to start stream.",
|
|
203
|
-
"server.commandRequired": "A command is required.",
|
|
204
|
-
"server.projectNotResolved": "Could not resolve project.",
|
|
205
|
-
"server.invalidLocale": "Invalid locale: {value}.",
|
|
206
|
-
|
|
207
|
-
"
|
|
210
|
+
"server.commandRequired": "A command is required.",
|
|
211
|
+
"server.projectNotResolved": "Could not resolve project.",
|
|
212
|
+
"server.invalidLocale": "Invalid locale: {value}.",
|
|
213
|
+
"server.timeTaskRequired": "You must specify a task before starting the timer.",
|
|
214
|
+
"server.timeTaskNotFound": "Task '{taskId}' not found.",
|
|
215
|
+
"server.timeParentTask": "You can only track time on leaf tasks. Break the work down and start the timer on an actionable child task.",
|
|
216
|
+
"server.timeStartedNote": "Timer started from the dashboard.",
|
|
217
|
+
"server.timeEntryNotFound": "Time entry not found.",
|
|
218
|
+
"server.agentExecutionStarted": "Agent execution started from the command console.",
|
|
219
|
+
|
|
220
|
+
"agentInbox.awaitUser.message": "Task '{title}' ({taskId}) is now {status} from {source}. The agent must wait for the user confirmation and continue once there is a real outcome.",
|
|
221
|
+
"agentInbox.awaitUser.resolved": "The pending user confirmation has been resolved.",
|
|
222
|
+
"agentInbox.verify.message": "The user moved task '{title}' ({taskId}) to {status} from {source}. The agent must verify the real state before continuing.",
|
|
223
|
+
"agentInbox.verify.resolved": "The real-state verification has already been handled.",
|
|
224
|
+
|
|
225
|
+
"init.welcome": "Project initialized with trackops.",
|
|
208
226
|
"init.opsExists": "Ops is already installed in this project.",
|
|
209
227
|
"init.created": "Created {file}",
|
|
210
228
|
"init.updated": "Updated {file}",
|
|
@@ -572,5 +590,221 @@
|
|
|
572
590
|
"handoff.instruction.closure": "When you finish writing the files, tell the user exactly this: 'The files are ready. Go back to the terminal and run: trackops opera bootstrap --resume'. Do not offer scaffolding, folder creation, or any additional steps. Your job ends with the bootstrap files.",
|
|
573
591
|
"handoff.label.knownIntention": "Known project intention",
|
|
574
592
|
"handoff.section.intakeSchema": "Required intake.json schema",
|
|
575
|
-
"handoff.instruction.intakeRequired": "The file `ops/bootstrap/intake.json` MUST include ALL of these fields. Missing fields will block the bootstrap. Use null only if genuinely unknown after discovery."
|
|
576
|
-
|
|
593
|
+
"handoff.instruction.intakeRequired": "The file `ops/bootstrap/intake.json` MUST include ALL of these fields. Missing fields will block the bootstrap. Use null only if genuinely unknown after discovery.",
|
|
594
|
+
|
|
595
|
+
"cli.help.plan.desc": "Import external implementation plans into project control with preview-first reconciliation.",
|
|
596
|
+
"cli.help.quality.desc": "Continuous quality inspection, verification evidence, and release/promotion readiness gates.",
|
|
597
|
+
|
|
598
|
+
"quality.status.pass": "pass",
|
|
599
|
+
"quality.status.fail": "fail",
|
|
600
|
+
"quality.status.warn": "attention",
|
|
601
|
+
"quality.status.skip": "skip",
|
|
602
|
+
"quality.status.passed": "passed",
|
|
603
|
+
"quality.status.failed": "failed",
|
|
604
|
+
"quality.status.skipped": "skipped",
|
|
605
|
+
"quality.status.not_configured": "not configured",
|
|
606
|
+
"quality.status.ready": "ready",
|
|
607
|
+
"quality.status.blocked": "blocked",
|
|
608
|
+
"quality.status.attention": "attention",
|
|
609
|
+
"quality.status.unknown": "unknown",
|
|
610
|
+
"quality.scope.test": "test",
|
|
611
|
+
"quality.scope.build": "build",
|
|
612
|
+
"quality.scope.smoke": "smoke",
|
|
613
|
+
"quality.scope.review": "review",
|
|
614
|
+
"quality.scope.all": "all",
|
|
615
|
+
"quality.value.unknown": "unknown",
|
|
616
|
+
"quality.value.missing": "missing",
|
|
617
|
+
"quality.source.intake": "intake.json",
|
|
618
|
+
"quality.source.bootstrap": "bootstrap",
|
|
619
|
+
"quality.source.inferred": "inference",
|
|
620
|
+
"quality.source.unknown": "unknown",
|
|
621
|
+
"quality.message.ok": "{subject}: OK.",
|
|
622
|
+
"quality.message.notApplicable": "{subject}: not applicable.",
|
|
623
|
+
"quality.message.failDetail": "{subject}: {detail}.",
|
|
624
|
+
"quality.message.fileMissing": "{subject}: missing {path}.",
|
|
625
|
+
"quality.message.missingItems": "{subject}: missing {items}.",
|
|
626
|
+
"quality.message.outOfSync": "{subject}: out of sync ({detail}).",
|
|
627
|
+
"quality.message.bridgeMissing": "{subject}: app bridge file is missing.",
|
|
628
|
+
"quality.message.bridgeMismatch": "{subject}: mismatched keys ({items}).",
|
|
629
|
+
"quality.message.dirtyTree": "{subject}: working tree has uncommitted changes.",
|
|
630
|
+
"quality.message.behindRemote": "{subject}: local branch is behind remote by {count} commit(s).",
|
|
631
|
+
"quality.message.countFail": "{subject}: {count} issue(s).",
|
|
632
|
+
"quality.message.staleTasks": "{subject}: {count} task(s) without recent activity.",
|
|
633
|
+
"quality.message.recordedFrom": "{subject}: recorded from {source}.",
|
|
634
|
+
"quality.verification.blocker.missing": "Missing recent verification evidence for {scope}.",
|
|
635
|
+
"quality.verification.blocker.failed": "Latest {scope} verification did not pass.",
|
|
636
|
+
"quality.verification.blocker.stale": "{scope} evidence is stale against the current configuration.",
|
|
637
|
+
"quality.verification.blocker.recommendation": "Run 'trackops quality verify --scope {scope}' before continuing.",
|
|
638
|
+
"quality.verify.reviewNoteRequired": "Manual review requires --note.",
|
|
639
|
+
"quality.readiness.phase": "Phase readiness ({phase})",
|
|
640
|
+
"quality.readiness.release": "Release readiness",
|
|
641
|
+
"quality.readiness.promotion": "Promotion readiness ({target})",
|
|
642
|
+
"quality.section.blockers": "Blockers:",
|
|
643
|
+
"quality.section.warnings": "Warnings:",
|
|
644
|
+
"quality.section.waived": "Waived:",
|
|
645
|
+
"quality.section.status": "Quality status",
|
|
646
|
+
"quality.section.currentPhase": "Current phase",
|
|
647
|
+
"quality.section.profiles": "Profiles",
|
|
648
|
+
"quality.section.probes": "Probes",
|
|
649
|
+
"quality.section.findings": "Findings",
|
|
650
|
+
"quality.section.verification": "Verification",
|
|
651
|
+
"quality.usage.title": "Usage:",
|
|
652
|
+
"quality.usage.status": "trackops quality status [--json] [--domain <name>] [--phase current|O|P|E|R|A]",
|
|
653
|
+
"quality.usage.verify": "trackops quality verify [--scope test|build|smoke|review|all] [--json] [--note \"...\"]",
|
|
654
|
+
"quality.usage.phaseReadiness": "trackops quality phase-readiness [--phase current|O|P|E|R|A] [--json]",
|
|
655
|
+
"quality.usage.releaseReadiness": "trackops quality release-readiness [--json]",
|
|
656
|
+
"quality.usage.promoteReadiness": "trackops quality promote-readiness --target staging|production [--json]",
|
|
657
|
+
"quality.usage.waiverList": "trackops quality waiver list [--json]",
|
|
658
|
+
"quality.usage.waiverAdd": "trackops quality waiver add <probe-id> --scope release|promotion --reason ... --approved-by ... --expires-at ...",
|
|
659
|
+
"quality.waivers.none": "No quality waivers.",
|
|
660
|
+
"quality.waivers.approvedBy": "approved by {approvedBy}",
|
|
661
|
+
"quality.waivers.created": "Waiver created: {id}",
|
|
662
|
+
"quality.error.waiverProbeRequired": "quality waiver add requires a probe id.",
|
|
663
|
+
"quality.error.waiverScope": "quality waiver scope must be 'release' or 'promotion'.",
|
|
664
|
+
"quality.error.waiverReason": "quality waiver add requires --reason.",
|
|
665
|
+
"quality.error.waiverApprovedBy": "quality waiver add requires --approved-by.",
|
|
666
|
+
"quality.error.waiverExpiry": "Promotion waivers require --expires-at.",
|
|
667
|
+
"quality.statusBlock.title": "Quality",
|
|
668
|
+
"quality.statusBlock.status": "status",
|
|
669
|
+
"quality.statusBlock.phaseReadiness": "phase readiness",
|
|
670
|
+
"quality.statusBlock.releaseReadiness": "release readiness",
|
|
671
|
+
"quality.statusBlock.blocker": "blocker",
|
|
672
|
+
"quality.promotion.versionControlRequired": "Production promotion requires version control metadata.",
|
|
673
|
+
"quality.promotion.versionControlRecommendation": "Complete versionControl.remote/provider/developmentBranch/releaseBranch in intake.json.",
|
|
674
|
+
"quality.promotion.deploymentRequired": "Production promotion requires complete deployment metadata.",
|
|
675
|
+
"quality.promotion.deploymentRecommendation": "Complete deployment.mode/target/smokeCommand in intake.json.",
|
|
676
|
+
"quality.promotion.policyApprovalRequired": "Production promotion requires an explicit approval rule in policy.",
|
|
677
|
+
"quality.promotion.policyApprovalRecommendation": "Restore production_deploy_requires_approval=true in autonomy.json.",
|
|
678
|
+
"quality.phase.O.title": "Orchestrate",
|
|
679
|
+
"quality.phase.P.title": "Prove",
|
|
680
|
+
"quality.phase.E.title": "Establish",
|
|
681
|
+
"quality.phase.R.title": "Refine",
|
|
682
|
+
"quality.phase.A.title": "Automate",
|
|
683
|
+
"quality.phase.message.pass": "{title}: OK.",
|
|
684
|
+
"quality.phase.message.fail": "{title}: not satisfied.",
|
|
685
|
+
"quality.phase.message.failDetail": "{title}: not satisfied ({detail}).",
|
|
686
|
+
"quality.phase.message.warn": "{title}: needs attention.",
|
|
687
|
+
"quality.phase.message.warnDetail": "{title}: needs attention ({detail}).",
|
|
688
|
+
"quality.phase.message.skip": "{title}: not applicable.",
|
|
689
|
+
"quality.phase.check.bootstrapComplete.title": "Bootstrap completed",
|
|
690
|
+
"quality.phase.check.bootstrapComplete.recommendation": "Complete or resume OPERA bootstrap before closing the phase.",
|
|
691
|
+
"quality.phase.check.discoveryCore.title": "Core discovery defined",
|
|
692
|
+
"quality.phase.check.discoveryCore.recommendation": "Complete problem, user, singular outcome, and source of truth.",
|
|
693
|
+
"quality.phase.check.bootstrapArtifacts.title": "Bootstrap artifacts consistent",
|
|
694
|
+
"quality.phase.check.bootstrapArtifacts.recommendation": "Ensure intake.json, spec-dossier.md, operating-contract.json, and quality-report have no blocking gaps.",
|
|
695
|
+
"quality.phase.check.versionControl.title": "Version control metadata recorded",
|
|
696
|
+
"quality.phase.check.versionControl.recommendation": "Record remote, provider, developmentBranch, and releaseBranch.",
|
|
697
|
+
"quality.phase.check.deployment.title": "Deployment metadata recorded",
|
|
698
|
+
"quality.phase.check.deployment.recommendation": "Record mode, target, and smokeCommand.",
|
|
699
|
+
"quality.phase.check.schemas.title": "Input/output schemas defined",
|
|
700
|
+
"quality.phase.check.schemas.recommendation": "Define inputSchema and outputSchema with a minimal useful structure.",
|
|
701
|
+
"quality.phase.check.behaviorRules.title": "Behavior rules documented",
|
|
702
|
+
"quality.phase.check.behaviorRules.recommendation": "Document behaviorRules in bootstrap or contract.",
|
|
703
|
+
"quality.phase.check.taskPlanSynced.title": "task_plan synced",
|
|
704
|
+
"quality.phase.check.taskPlanSynced.recommendation": "Run 'trackops sync' and review task_plan.md.",
|
|
705
|
+
"quality.phase.check.envKeys.title": "Environment credentials verified",
|
|
706
|
+
"quality.phase.check.envKeys.recommendation": "Fill the required keys in .env and sync the bridge.",
|
|
707
|
+
"quality.phase.check.verificationEvidence.title": "Verification evidence available",
|
|
708
|
+
"quality.phase.check.verificationEvidence.recommendation": "Run tests or smoke checks to prove real technical viability.",
|
|
709
|
+
"quality.phase.check.criticalFindings.title": "No critical findings open",
|
|
710
|
+
"quality.phase.check.criticalFindings.recommendation": "Resolve or explicitly accept any critical finding.",
|
|
711
|
+
"quality.phase.check.blockedTasksDocumented.title": "Blocked tasks documented",
|
|
712
|
+
"quality.phase.check.blockedTasksDocumented.recommendation": "Add blocker reasons to all blocked tasks.",
|
|
713
|
+
"quality.phase.check.backlogIntegrity.title": "Backlog without cycles or phantom references",
|
|
714
|
+
"quality.phase.check.backlogIntegrity.recommendation": "Fix dependencies, parents, and cycles in the backlog graph.",
|
|
715
|
+
"quality.phase.check.requiredAcceptance.title": "Required tasks have acceptance",
|
|
716
|
+
"quality.phase.check.requiredAcceptance.recommendation": "Add acceptance criteria to every required leaf task.",
|
|
717
|
+
"quality.phase.check.taskTracking.title": "Work tracked in TrackOps",
|
|
718
|
+
"quality.phase.check.taskTracking.recommendation": "Start, move, and close tasks from TrackOps to keep an operational trace.",
|
|
719
|
+
"quality.phase.check.docsSynced.title": "Generated docs synced",
|
|
720
|
+
"quality.phase.check.docsSynced.recommendation": "Run 'trackops sync' and review documentation drift.",
|
|
721
|
+
"quality.phase.check.repoCommitted.title": "Changes materialized in git",
|
|
722
|
+
"quality.phase.check.repoCommitted.recommendation": "Commit relevant changes before closing the phase.",
|
|
723
|
+
"quality.phase.check.findingsHighClosed.title": "No critical/high findings open",
|
|
724
|
+
"quality.phase.check.findingsHighClosed.recommendation": "Resolve or explicitly accept high-severity findings before closing refinement.",
|
|
725
|
+
"quality.phase.check.contractConsistent.title": "Contract consistent with artifacts",
|
|
726
|
+
"quality.phase.check.contractConsistent.recommendation": "Run the auditor or fix contradictions between contract and bootstrap.",
|
|
727
|
+
"quality.phase.check.reviewEvidence.title": "Review recorded",
|
|
728
|
+
"quality.phase.check.reviewEvidence.recommendation": "Record manual review with 'trackops quality verify --scope review --note ...'.",
|
|
729
|
+
"quality.phase.check.tmpClean.title": ".tmp clean",
|
|
730
|
+
"quality.phase.check.tmpClean.recommendation": "Clean unnecessary temporary artifacts before automation or release.",
|
|
731
|
+
"quality.phase.check.deploymentReady.title": "Deployment ready",
|
|
732
|
+
"quality.phase.check.deploymentReady.recommendation": "Complete deployment metadata and destination before automating.",
|
|
733
|
+
"quality.phase.check.smokePassed.title": "Smoke test passed",
|
|
734
|
+
"quality.phase.check.smokePassed.recommendation": "Run and record a valid smoke test on the destination.",
|
|
735
|
+
"quality.phase.check.remotePushed.title": "Changes pushed to remote",
|
|
736
|
+
"quality.phase.check.remotePushed.recommendation": "Push to remote when versionControl.remote is true.",
|
|
737
|
+
"quality.phase.check.repoClean.title": "Working tree clean",
|
|
738
|
+
"quality.phase.check.repoClean.recommendation": "Leave the working tree clean before closing automation/release.",
|
|
739
|
+
"quality.probe.bootstrap.complete.title": "Bootstrap",
|
|
740
|
+
"quality.probe.bootstrap.complete.recommendation": "Complete bootstrap before trusting phase or release readiness.",
|
|
741
|
+
"quality.probe.contract.exists.title": "Operating contract",
|
|
742
|
+
"quality.probe.contract.exists.recommendation": "Generate or restore ops/contract/operating-contract.json.",
|
|
743
|
+
"quality.probe.contract.valid-json.title": "Contract JSON",
|
|
744
|
+
"quality.probe.contract.valid-json.recommendation": "Fix operating-contract.json so it parses cleanly.",
|
|
745
|
+
"quality.probe.contract.intent-complete.title": "Contract intent",
|
|
746
|
+
"quality.probe.contract.intent-complete.recommendation": "Complete the missing intent fields.",
|
|
747
|
+
"quality.probe.policy.exists.title": "Autonomy policy",
|
|
748
|
+
"quality.probe.policy.exists.recommendation": "Generate or restore ops/policy/autonomy.json.",
|
|
749
|
+
"quality.probe.policy.valid-json.title": "Policy JSON",
|
|
750
|
+
"quality.probe.policy.valid-json.recommendation": "Fix autonomy.json so it parses cleanly.",
|
|
751
|
+
"quality.probe.docs.drift.title": "Generated docs",
|
|
752
|
+
"quality.probe.docs.drift.recommendation": "Run 'trackops sync' and review generated documents.",
|
|
753
|
+
"quality.probe.docs.genesis-exists.title": "genesis.md",
|
|
754
|
+
"quality.probe.docs.genesis-exists.recommendation": "Regenerate genesis.md from the current contract and bootstrap state.",
|
|
755
|
+
"quality.probe.env.missing-keys.title": "Required environment keys",
|
|
756
|
+
"quality.probe.env.missing-keys.recommendation": "Fill the missing keys in .env.",
|
|
757
|
+
"quality.probe.env.bridge-sync.title": "App env bridge",
|
|
758
|
+
"quality.probe.env.bridge-sync.recommendation": "Run 'trackops env sync' to refresh the bridge.",
|
|
759
|
+
"quality.probe.repo.clean.title": "Working tree",
|
|
760
|
+
"quality.probe.repo.clean.recommendation": "Commit, stash, or clean unrelated changes before release.",
|
|
761
|
+
"quality.probe.repo.behind-remote.title": "Remote sync",
|
|
762
|
+
"quality.probe.repo.behind-remote.recommendation": "Pull the latest remote changes before releasing or promoting.",
|
|
763
|
+
"quality.probe.tasks.circular-deps.title": "Circular dependencies",
|
|
764
|
+
"quality.probe.tasks.circular-deps.recommendation": "Break the circular dependency chain.",
|
|
765
|
+
"quality.probe.tasks.phantom-deps.title": "Phantom dependencies",
|
|
766
|
+
"quality.probe.tasks.phantom-deps.recommendation": "Fix references to tasks that do not exist.",
|
|
767
|
+
"quality.probe.tasks.phantom-parents.title": "Phantom parents",
|
|
768
|
+
"quality.probe.tasks.phantom-parents.recommendation": "Reassign or clear parentId values pointing to missing tasks.",
|
|
769
|
+
"quality.probe.tasks.hierarchy-cycles.title": "Hierarchy cycles",
|
|
770
|
+
"quality.probe.tasks.hierarchy-cycles.recommendation": "Break parent-child cycles in the task tree.",
|
|
771
|
+
"quality.probe.tasks.stale-in-progress.title": "Stale in-progress tasks",
|
|
772
|
+
"quality.probe.tasks.stale-in-progress.recommendation": "Update, block, or complete tasks without recent activity.",
|
|
773
|
+
"quality.probe.tasks.blocked-without-note.title": "Blocked tasks without note",
|
|
774
|
+
"quality.probe.tasks.blocked-without-note.recommendation": "Document the blocker reason for every blocked task.",
|
|
775
|
+
"quality.probe.tasks.required-without-acceptance.title": "Missing acceptance",
|
|
776
|
+
"quality.probe.tasks.required-without-acceptance.recommendation": "Add acceptance criteria to all required tasks.",
|
|
777
|
+
"quality.probe.findings.open-critical.title": "Open critical findings",
|
|
778
|
+
"quality.probe.findings.open-critical.recommendation": "Resolve or explicitly waive critical findings before release.",
|
|
779
|
+
"quality.probe.findings.open-high.title": "Open high findings",
|
|
780
|
+
"quality.probe.findings.open-high.recommendation": "Resolve or explicitly track high findings before closing refinement.",
|
|
781
|
+
"quality.probe.bootstrap.version-control.title": "Bootstrap version control metadata",
|
|
782
|
+
"quality.probe.bootstrap.version-control.recommendation": "Capture versionControl.remote/provider/developmentBranch/releaseBranch in intake.json.",
|
|
783
|
+
"quality.probe.bootstrap.deployment.title": "Bootstrap deployment metadata",
|
|
784
|
+
"quality.probe.bootstrap.deployment.recommendation": "Capture deployment.mode/target/smokeCommand in intake.json.",
|
|
785
|
+
"quality.probe.verification.configured.title": "Verification configuration",
|
|
786
|
+
"quality.probe.verification.configured.recommendation": "Declare explicit commands in meta.quality.verification if defaults are not enough.",
|
|
787
|
+
"ui.dashboard.tabQuality": "Quality",
|
|
788
|
+
"ui.dashboard.quality.kpiQuality": "Quality",
|
|
789
|
+
"ui.dashboard.quality.failingProbes": "{count} failing probes",
|
|
790
|
+
"ui.dashboard.quality.kpiPhase": "Phase readiness",
|
|
791
|
+
"ui.dashboard.quality.blockerCount": "{count} blockers",
|
|
792
|
+
"ui.dashboard.quality.kpiRelease": "Release readiness",
|
|
793
|
+
"ui.dashboard.quality.kpiPromotion": "Production promotion",
|
|
794
|
+
"ui.dashboard.quality.domainStatus": "Domain status",
|
|
795
|
+
"ui.dashboard.quality.domainCounts": "pass {pass} · fail {fail} · skip {skip}",
|
|
796
|
+
"ui.dashboard.quality.noDomainData": "No domain data.",
|
|
797
|
+
"ui.dashboard.quality.latestVerification": "Latest verification",
|
|
798
|
+
"ui.dashboard.quality.noVerificationRuns": "No verification runs recorded.",
|
|
799
|
+
"ui.dashboard.quality.topBlockers": "Top blockers",
|
|
800
|
+
"ui.dashboard.quality.noFailingProbes": "No failing probes.",
|
|
801
|
+
"ui.dashboard.quality.readinessDetail": "Readiness detail",
|
|
802
|
+
"ui.dashboard.quality.kind.phase": "phase",
|
|
803
|
+
"ui.dashboard.quality.kind.release": "release",
|
|
804
|
+
"ui.dashboard.quality.kind.promotion": "promotion",
|
|
805
|
+
"ui.dashboard.quality.kind.readiness": "readiness",
|
|
806
|
+
"ui.dashboard.quality.noBlockers": "No blockers",
|
|
807
|
+
"ui.dashboard.quality.activeWaivers": "Active waivers",
|
|
808
|
+
"ui.dashboard.quality.waiverSummary": "{scope} · approved by {approvedBy}",
|
|
809
|
+
"ui.dashboard.quality.noWaivers": "No active waivers."
|
|
810
|
+
}
|