universal-dev-standards 6.14.0-beta.2 → 6.14.0-beta.4
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/bundled/ai/standards/ai-response-navigation.ai.yaml +43 -3
- package/bundled/ai/standards/checkin-standards.ai.yaml +25 -6
- package/bundled/ai/standards/open-work-tracking.ai.yaml +4 -1
- package/bundled/ai/standards/pipeline-security-gates.ai.yaml +5 -1
- package/bundled/core/ai-response-navigation.md +128 -12
- package/bundled/core/open-work-tracking.md +1 -1
- package/bundled/extensions/frameworks/fat-free-patterns.md +937 -0
- package/bundled/extensions/languages/csharp-style.md +464 -0
- package/bundled/extensions/languages/php/fat-free-patterns.md +915 -0
- package/bundled/extensions/languages/php/php-style.md +693 -0
- package/bundled/extensions/languages/php-style.md +700 -0
- package/bundled/extensions/locales/zh-cn.md +717 -0
- package/bundled/extensions/locales/zh-tw.md +717 -0
- package/bundled/locales/COVERAGE.md +5 -4
- package/bundled/locales/zh-CN/CHANGELOG.md +44 -3
- package/bundled/locales/zh-CN/README.md +2 -2
- package/bundled/locales/zh-CN/SECURITY.md +1 -1
- package/bundled/locales/zh-CN/core/ai-response-navigation.md +110 -12
- package/bundled/locales/zh-CN/skills/README.md +1 -0
- package/bundled/locales/zh-CN/skills/comprehension-ladder/SKILL.md +289 -0
- package/bundled/locales/zh-CN/skills/comprehension-ladder/eval-cases.md +261 -0
- package/bundled/locales/zh-TW/CHANGELOG.md +44 -3
- package/bundled/locales/zh-TW/README.md +2 -2
- package/bundled/locales/zh-TW/SECURITY.md +1 -1
- package/bundled/locales/zh-TW/core/ai-response-navigation.md +110 -12
- package/bundled/locales/zh-TW/core/open-work-tracking.md +3 -3
- package/bundled/locales/zh-TW/skills/README.md +1 -0
- package/bundled/locales/zh-TW/skills/comprehension-ladder/SKILL.md +289 -0
- package/bundled/locales/zh-TW/skills/comprehension-ladder/eval-cases.md +261 -0
- package/bundled/skills/README.md +1 -0
- package/bundled/skills/comprehension-ladder/SKILL.md +283 -0
- package/bundled/skills/comprehension-ladder/eval-cases.md +255 -0
- package/package.json +2 -2
- package/src/commands/check.js +9 -0
- package/src/commands/init.js +100 -27
- package/src/commands/uninstall.js +144 -30
- package/src/commands/update.js +62 -3
- package/src/core/install-records.js +191 -0
- package/src/i18n/messages.js +39 -6
- package/src/installers/hooks-installer.js +61 -30
- package/src/installers/integration-installer.js +5 -1
- package/src/installers/standards-installer.js +16 -23
- package/src/reconciler/plan-executor.js +10 -11
- package/src/uninstallers/hook-uninstaller.js +219 -33
- package/src/uninstallers/integration-uninstaller.js +35 -5
- package/src/utils/copier.js +57 -0
- package/src/utils/git-hooks.js +139 -7
- package/src/utils/hasher.js +36 -0
- package/src/utils/integration-generator.js +16 -6
- package/src/utils/legacy-hook-migration.js +112 -0
- package/src/utils/locale.js +19 -0
- package/src/utils/open-work-tracking.mjs +124 -23
- package/standards-registry.json +21 -7
|
@@ -44,6 +44,19 @@
|
|
|
44
44
|
* could not apply (command, test
|
|
45
45
|
* name, identifier)
|
|
46
46
|
* unnamed VIOLATION — the only failure
|
|
47
|
+
* A field is read in three shapes, all through the one
|
|
48
|
+
* VOCAB.nextAction list: a heading section, an inline
|
|
49
|
+
* "Next action: ..." label, and EVERY ROW of a table column whose
|
|
50
|
+
* header is in that list (each report carries the line and the
|
|
51
|
+
* row's first cell, so it can be found).
|
|
52
|
+
* Not evaluated, counted: an empty cell, `-`, `—`, `n/a`, `none`,
|
|
53
|
+
* `done`. OWT-019 is NOT violated by them: it judges a next action
|
|
54
|
+
* that was written; "no next action written" is another failure
|
|
55
|
+
* this check does not decide (a finished item has none either).
|
|
56
|
+
* Undecidable, listed: a table row whose cell count differs from its
|
|
57
|
+
* header (a stray or missing `|`). It is neither judged nor read as
|
|
58
|
+
* empty. A violation elsewhere still exits 1; otherwise the exit is 2,
|
|
59
|
+
* because "no violation found" would then cover only part of the field.
|
|
47
60
|
* revision OWT-018 the acceptance/goal/constraint sections changed
|
|
48
61
|
* between two versions of a carrier; a NEW revision
|
|
49
62
|
* record (change, approver, reason) must exist. No
|
|
@@ -75,8 +88,8 @@
|
|
|
75
88
|
* (--id-pattern) and read the heading vocabulary as a starting point.
|
|
76
89
|
*
|
|
77
90
|
* Exit codes: 0 no violation · 1 violation · 2 cannot decide (no structure
|
|
78
|
-
* found,
|
|
79
|
-
* pass.
|
|
91
|
+
* found, a next-action table row could not be read, git failed, or this
|
|
92
|
+
* script's own self-test arms failed). 2 is NOT a pass.
|
|
80
93
|
*
|
|
81
94
|
* Usage (`uds` from the npm package, or the repo shim; same arguments):
|
|
82
95
|
* uds open-work next-action <file...> [--root DIR] [--id-pattern RE]
|
|
@@ -97,7 +110,16 @@ import { fileURLToPath } from 'node:url';
|
|
|
97
110
|
|
|
98
111
|
export const VOCAB = {
|
|
99
112
|
revision: /revision|change[\s-]?log|amendment|history|修訂|變更紀錄|變更記錄|修改紀錄|修改記錄|異動/i,
|
|
100
|
-
|
|
113
|
+
// ONE list of "next action" words. It is read three ways and there is no second copy:
|
|
114
|
+
// a heading (classifyHeading), a table column header (extractNextActions) and an inline
|
|
115
|
+
// label ("Next action: ...", built from .source below). Keep it free of capture groups:
|
|
116
|
+
// the label regex embeds it and reads its own group 1.
|
|
117
|
+
// 回來要做什麼 ("what to do when you come back") is the header the dev-platform worklog's
|
|
118
|
+
// main table actually uses (DEC-122 H2 baseline carrier); that file describes the column as
|
|
119
|
+
// 下一動 in prose but the header text drifted. Added because a header outside this list is
|
|
120
|
+
// invisible to the check, which is the failure DEC-122 measured. Adopter-specific and
|
|
121
|
+
// UNCALIBRATED (OWT-016); an adopter whose header differs adds its own word here.
|
|
122
|
+
nextAction: /next[\s-]?(?:action|step)s?|下一步|下一動|回來要做什麼/i,
|
|
101
123
|
progress: /\bprogress\b|\bstate\b|\bblockers?\b|\bblocked\b|進度|現況|卡在/i,
|
|
102
124
|
intent: /acceptance|criteria|\brequirements?\b|\bgoals?\b|objectives?|constraints?|驗收|需求|目標|限制/i,
|
|
103
125
|
// revision-table columns / labelled list fields
|
|
@@ -198,14 +220,58 @@ function innermost(stack) {
|
|
|
198
220
|
|
|
199
221
|
const norm = (s) => s.replace(/\s+/g, ' ').trim();
|
|
200
222
|
|
|
223
|
+
/** A table line may sit inside a Markdown blockquote ("> | a | b |"): drop the quote marker. */
|
|
224
|
+
const unquote = (line) => line.replace(/^\s*(?:>\s?)+/, '');
|
|
225
|
+
|
|
226
|
+
/** Index of the closing backtick run of exactly `n` backticks at or after `from`, or -1. */
|
|
227
|
+
function closingRun(t, from, n) {
|
|
228
|
+
let j = from;
|
|
229
|
+
while (j < t.length) {
|
|
230
|
+
if (t[j] !== '`') { j++; continue; }
|
|
231
|
+
let m = 0;
|
|
232
|
+
while (t[j + m] === '`') m++;
|
|
233
|
+
if (m === n) return j;
|
|
234
|
+
j += m;
|
|
235
|
+
}
|
|
236
|
+
return -1;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Split one table row into cells. A `|` does NOT split a cell when it is escaped (`\|`) or
|
|
241
|
+
* sits inside a code span that closes on the same line. The second rule is deliberately
|
|
242
|
+
* looser than GFM (which splits inside code unless escaped): a hand-written note such as
|
|
243
|
+
* `tar -tzf \| grep` or `a|b` in backticks means one cell, and splitting it would shift
|
|
244
|
+
* every later column and misread the next-action cell. An unclosed backtick is literal.
|
|
245
|
+
*/
|
|
201
246
|
function splitRow(line) {
|
|
202
|
-
let t = line.trim();
|
|
247
|
+
let t = unquote(line).trim();
|
|
203
248
|
if (t.startsWith('|')) t = t.slice(1);
|
|
204
|
-
|
|
205
|
-
|
|
249
|
+
const cells = [];
|
|
250
|
+
let cur = '';
|
|
251
|
+
let lastDelim = false;
|
|
252
|
+
let i = 0;
|
|
253
|
+
while (i < t.length) {
|
|
254
|
+
const ch = t[i];
|
|
255
|
+
lastDelim = false;
|
|
256
|
+
if (ch === '\\' && t[i + 1] === '|') { cur += '|'; i += 2; continue; }
|
|
257
|
+
if (ch === '`') {
|
|
258
|
+
let n = 0;
|
|
259
|
+
while (t[i + n] === '`') n++;
|
|
260
|
+
const close = closingRun(t, i + n, n);
|
|
261
|
+
if (close !== -1) { cur += t.slice(i, close + n).replace(/\\\|/g, '|'); i = close + n; continue; }
|
|
262
|
+
cur += '`'.repeat(n);
|
|
263
|
+
i += n;
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
if (ch === '|') { cells.push(cur); cur = ''; lastDelim = true; i++; continue; }
|
|
267
|
+
cur += ch;
|
|
268
|
+
i++;
|
|
269
|
+
}
|
|
270
|
+
if (!lastDelim) cells.push(cur); // a trailing unescaped `|` closes the row; it opens no cell
|
|
271
|
+
return cells.map(norm);
|
|
206
272
|
}
|
|
207
273
|
|
|
208
|
-
const isSepRow = (line) => /^\s*\|?[\s:|-]+\|?\s*$/.test(line) && /-/.test(line);
|
|
274
|
+
const isSepRow = (line) => /^\s*\|?[\s:|-]+\|?\s*$/.test(unquote(line)) && /-/.test(line);
|
|
209
275
|
|
|
210
276
|
/** Tables among annotated lines: [{header, rows:[{cells, idx}]}] */
|
|
211
277
|
function findTables(lines) {
|
|
@@ -213,12 +279,12 @@ function findTables(lines) {
|
|
|
213
279
|
let k = 0;
|
|
214
280
|
while (k < lines.length) {
|
|
215
281
|
const l = lines[k];
|
|
216
|
-
if (!l.inFence && !l.fence && !l.front && l.text.trim().startsWith('|') && k + 1 < lines.length
|
|
217
|
-
&& isSepRow(lines[k + 1].text) && lines[k + 1].text.trim().startsWith('|')) {
|
|
282
|
+
if (!l.inFence && !l.fence && !l.front && unquote(l.text).trim().startsWith('|') && k + 1 < lines.length
|
|
283
|
+
&& isSepRow(lines[k + 1].text) && unquote(lines[k + 1].text).trim().startsWith('|')) {
|
|
218
284
|
const header = splitRow(l.text);
|
|
219
285
|
const rows = [];
|
|
220
286
|
let j = k + 2;
|
|
221
|
-
while (j < lines.length && lines[j].text.trim().startsWith('|')) {
|
|
287
|
+
while (j < lines.length && unquote(lines[j].text).trim().startsWith('|')) {
|
|
222
288
|
rows.push({ cells: splitRow(lines[j].text), idx: j });
|
|
223
289
|
j++;
|
|
224
290
|
}
|
|
@@ -456,24 +522,45 @@ export function classifyNextAction(text, opts = {}) {
|
|
|
456
522
|
};
|
|
457
523
|
}
|
|
458
524
|
|
|
459
|
-
|
|
525
|
+
const clip = (s, n) => (s.length > n ? `${s.slice(0, n)}…` : s);
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Find "next action" fields in a carrier. Three shapes are read, all through the ONE
|
|
529
|
+
* vocabulary VOCAB.nextAction: a heading section, an inline label, and a table column whose
|
|
530
|
+
* HEADER is in that vocabulary (every row of that column is one field).
|
|
531
|
+
*
|
|
532
|
+
* A table row whose cell count differs from the header's is returned in `ragged`, not in
|
|
533
|
+
* `items`: after a stray or missing `|` the next-action cell cannot be told from its
|
|
534
|
+
* neighbour, and reading an absent cell as "empty" would turn a broken row into a quiet
|
|
535
|
+
* "no next action written". It is neither judged nor dropped: the caller counts and lists it.
|
|
536
|
+
* @returns {{fields:number, items:{text:string,where:string}[], ragged:{where:string,cells:number,expected:number}[]}}
|
|
537
|
+
*/
|
|
460
538
|
export function extractNextActions(md) {
|
|
461
539
|
const lines = parseDoc(md);
|
|
462
540
|
const items = [];
|
|
541
|
+
const ragged = [];
|
|
463
542
|
let fields = 0;
|
|
464
543
|
const tableIdx = new Set();
|
|
465
544
|
const headerIdx = new Set();
|
|
466
545
|
const tables = findTables(lines);
|
|
467
546
|
|
|
468
547
|
for (const t of tables) {
|
|
469
|
-
|
|
470
|
-
const
|
|
548
|
+
// every header cell in the shared vocabulary is a next-action column (usually exactly one)
|
|
549
|
+
const cols = t.header.map((c, n) => (VOCAB.nextAction.test(c) ? n : -1)).filter((n) => n >= 0); // [mutation-anchor:table-header]
|
|
550
|
+
const hasCol = cols.length > 0;
|
|
471
551
|
tableIdx.add(t.headerIdx); tableIdx.add(t.headerIdx + 1); headerIdx.add(t.headerIdx);
|
|
472
552
|
t.rows.forEach((r) => tableIdx.add(r.idx));
|
|
473
553
|
if (hasCol) {
|
|
474
554
|
for (const r of t.rows) {
|
|
475
|
-
|
|
476
|
-
|
|
555
|
+
const who = `row "${clip(r.cells[0].replace(/\*\*|__/g, ''), 40)}"`;
|
|
556
|
+
if (r.cells.length !== t.header.length) {
|
|
557
|
+
ragged.push({ idx: r.idx, where: `table row (line ${r.idx + 1}, ${who})`, cells: r.cells.length, expected: t.header.length });
|
|
558
|
+
continue;
|
|
559
|
+
}
|
|
560
|
+
for (const col of cols) {
|
|
561
|
+
fields++;
|
|
562
|
+
items.push({ text: r.cells[col], where: `table column "${t.header[col]}" (line ${r.idx + 1}, ${who})` });
|
|
563
|
+
}
|
|
477
564
|
}
|
|
478
565
|
}
|
|
479
566
|
// rows inside a nextAction-class section are handled by the section walk below
|
|
@@ -481,12 +568,16 @@ export function extractNextActions(md) {
|
|
|
481
568
|
}
|
|
482
569
|
|
|
483
570
|
// inline labelled "**Next action**: ..." (outside tables that have their own column)
|
|
484
|
-
const labelRe =
|
|
571
|
+
const labelRe = new RegExp(`(?:\\*\\*|__)?(?:${VOCAB.nextAction.source})(?:\\*\\*|__)?\\s*[::]\\s*(.+)$`, 'i');
|
|
485
572
|
const colTableRows = new Set();
|
|
486
|
-
|
|
573
|
+
// Only rows read through the column are exempt from the label scan. A ragged row was not
|
|
574
|
+
// read, so an inline "Next action: ..." inside it must still be seen (else it goes dark).
|
|
575
|
+
const raggedIdx = new Set(ragged.map((g) => g.idx));
|
|
576
|
+
for (const t of tables) if (t.hasNextActionColumn) t.rows.forEach((r) => { if (!raggedIdx.has(r.idx)) colTableRows.add(r.idx); });
|
|
487
577
|
lines.forEach((l, idx) => {
|
|
488
578
|
if (l.front || l.fence || l.inFence || l.heading || l.cls === 'nextAction' || colTableRows.has(idx)) return;
|
|
489
|
-
|
|
579
|
+
// a label inside a table row reads to the end of the row, not into its closing pipe
|
|
580
|
+
const m = labelRe.exec(unquote(l.text).trim().startsWith('|') ? l.text.replace(/\s*\|\s*$/, '') : l.text);
|
|
490
581
|
if (m && !/^\s*$/.test(m[1])) { fields++; items.push({ text: m[1], where: `label (line ${idx + 1})` }); }
|
|
491
582
|
});
|
|
492
583
|
|
|
@@ -522,14 +613,15 @@ export function extractNextActions(md) {
|
|
|
522
613
|
if (sec.length === 0) items.push({ text: '', where: `section "${owner.heading}" (empty)` });
|
|
523
614
|
for (const s of sec) items.push({ text: s, where: `section "${owner.heading}"` });
|
|
524
615
|
}
|
|
525
|
-
return { fields, items };
|
|
616
|
+
return { fields, items, ragged };
|
|
526
617
|
}
|
|
527
618
|
|
|
528
619
|
export function checkNextActions(carriers, opts = {}) {
|
|
529
|
-
const res = { walked: 0, empty: 0, counts: { 'named-resolved': 0, 'named-unresolved': 0, unnamed: 0 }, violations: [], detail: [], noFieldCarriers: [] };
|
|
620
|
+
const res = { walked: 0, empty: 0, counts: { 'named-resolved': 0, 'named-unresolved': 0, unnamed: 0 }, violations: [], detail: [], noFieldCarriers: [], undecidable: [] };
|
|
530
621
|
for (const c of carriers) {
|
|
531
|
-
const { fields, items } = extractNextActions(c.content);
|
|
532
|
-
|
|
622
|
+
const { fields, items, ragged } = extractNextActions(c.content);
|
|
623
|
+
for (const g of ragged) res.undecidable.push({ path: c.path, ...g });
|
|
624
|
+
if (fields === 0 && ragged.length === 0) { res.noFieldCarriers.push(c.path); continue; }
|
|
533
625
|
for (const it of items) {
|
|
534
626
|
const text = it.text.replace(/\*\*|__/g, '').trim();
|
|
535
627
|
if (EMPTY_FIELD.test(text)) { res.empty++; continue; }
|
|
@@ -557,6 +649,11 @@ export function runSelfTest() {
|
|
|
557
649
|
expect('D2 clean: identifier', classifyNextAction('finish XSPEC-436 R1', {}).status !== 'unnamed');
|
|
558
650
|
expect('D2 clean: test name', classifyNextAction('make the test "a next action that names nothing is reported" pass', {}).status !== 'unnamed');
|
|
559
651
|
|
|
652
|
+
// OWT-019, table columns: the header decides which column is read, never the position
|
|
653
|
+
const tbl = extractNextActions('| item | state | Next action |\n|---|---|---|\n| a | open | keep going |\n');
|
|
654
|
+
expect('D2 clean: only the header-named column is a next-action field', tbl.fields === 1 && tbl.items[0].text === 'keep going');
|
|
655
|
+
expect('D2 clean: a table without such a header has no next-action field', extractNextActions('| item | state |\n|---|---|\n| a | open |\n').fields === 0);
|
|
656
|
+
|
|
560
657
|
// OWT-018
|
|
561
658
|
const spec = (ac, rev) => `# S\n\n## Acceptance criteria\n\n${ac}\n\n## Revisions\n\n${rev}\n`;
|
|
562
659
|
const table = (rows) => `| Change | Approver | Reason |\n|---|---|---|\n${rows}`;
|
|
@@ -639,12 +736,16 @@ export function main(argv, io = { log: console.log, err: console.error }) {
|
|
|
639
736
|
if (!files.length) { say('[owt] next-action: no files given'); return finish(2); }
|
|
640
737
|
const res = checkNextActions(files.map(readCarrier), { root, idPattern });
|
|
641
738
|
say(`[owt] OWT-019 walked ${res.walked} next-action field(s) in ${files.length} carrier(s); ${res.empty} empty/done field(s) not evaluated; ${res.noFieldCarriers.length} carrier(s) had no next-action field`);
|
|
642
|
-
say(`[owt] named-resolved=${res.counts['named-resolved']} named-unresolved=${res.counts['named-unresolved']} unnamed=${res.counts.unnamed}`);
|
|
739
|
+
say(`[owt] named-resolved=${res.counts['named-resolved']} named-unresolved=${res.counts['named-unresolved']} unnamed=${res.counts.unnamed} undecidable-table-rows=${res.undecidable.length}`);
|
|
643
740
|
for (const d of res.detail) say(`[owt] ${d.status.padEnd(16)} ${d.path} ${d.where}: ${d.text.slice(0, 80)}${d.kinds.length ? ' <- ' + d.kinds.map((k) => `${k.kind}:${k.value}`).join(', ') : ''}`);
|
|
644
741
|
for (const v of res.violations) say(`[owt] VIOLATION OWT-019: ${v.path} ${v.where} names no file path, test name, command or requirement identifier: "${v.text.slice(0, 80)}"`);
|
|
742
|
+
for (const u of res.undecidable) say(`[owt] UNDECIDABLE: ${u.path} ${u.where} has ${u.cells} cell(s) but its header has ${u.expected}; the next-action cell cannot be located, so the row is neither judged nor counted as empty`);
|
|
645
743
|
say(`[owt] ${COVERAGE_NOTE}`);
|
|
646
744
|
say(`[owt] ${UNCALIBRATED_NOTE}`);
|
|
647
745
|
if (res.walked + res.empty === 0) { say('[owt] CANNOT DECIDE: no next-action field found in any carrier (walked 0). Exit 2 is not a pass.'); return finish(2); }
|
|
746
|
+
// A violation is a definite answer whatever else is unreadable. Absent one, a row we could
|
|
747
|
+
// not read means "no violation found" is not "no violation": exit 2, never a green 0.
|
|
748
|
+
if (!res.violations.length && res.undecidable.length) { say(`[owt] CANNOT DECIDE: ${res.undecidable.length} table row(s) could not be read (see UNDECIDABLE above), so a clean result would cover only part of the field. Exit 2 is not a pass.`); return finish(2); }
|
|
648
749
|
return finish(res.violations.length ? 1 : 0);
|
|
649
750
|
}
|
|
650
751
|
if (cmd === 'revision') {
|
package/standards-registry.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"version": "6.14.0-beta.
|
|
3
|
+
"version": "6.14.0-beta.4",
|
|
4
4
|
"lastUpdated": "2026-05-13",
|
|
5
5
|
"description": "Standards registry for universal-dev-standards with integrated skills and AI-optimized formats",
|
|
6
6
|
"formats": {
|
|
@@ -58,14 +58,14 @@
|
|
|
58
58
|
"standards": {
|
|
59
59
|
"name": "universal-dev-standards",
|
|
60
60
|
"url": "https://github.com/AsiaOstrich/universal-dev-standards",
|
|
61
|
-
"version": "6.14.0-beta.
|
|
61
|
+
"version": "6.14.0-beta.4"
|
|
62
62
|
},
|
|
63
63
|
"skills": {
|
|
64
64
|
"name": "universal-dev-standards",
|
|
65
65
|
"url": "https://github.com/AsiaOstrich/universal-dev-standards",
|
|
66
66
|
"localPath": "skills",
|
|
67
67
|
"rawUrl": "https://raw.githubusercontent.com/AsiaOstrich/universal-dev-standards/main/skills",
|
|
68
|
-
"version": "6.14.0-beta.
|
|
68
|
+
"version": "6.14.0-beta.4",
|
|
69
69
|
"note": "Skills are now included in the main repository under skills/"
|
|
70
70
|
}
|
|
71
71
|
},
|
|
@@ -382,6 +382,10 @@
|
|
|
382
382
|
"skills/brainstorm-assistant/SKILL.md",
|
|
383
383
|
"skills/brainstorm-assistant/guide.md"
|
|
384
384
|
],
|
|
385
|
+
"comprehension-ladder": [
|
|
386
|
+
"skills/comprehension-ladder/SKILL.md",
|
|
387
|
+
"skills/comprehension-ladder/eval-cases.md"
|
|
388
|
+
],
|
|
385
389
|
"bdd-assistant": [
|
|
386
390
|
"skills/bdd-assistant/SKILL.md",
|
|
387
391
|
"skills/bdd-assistant/guide.md",
|
|
@@ -1536,6 +1540,16 @@
|
|
|
1536
1540
|
"description": "Traditional Chinese (Taiwan) localization for all standards",
|
|
1537
1541
|
"applicability": "Traditional Chinese speaking teams"
|
|
1538
1542
|
},
|
|
1543
|
+
{
|
|
1544
|
+
"id": "zh-cn-locale",
|
|
1545
|
+
"name": "Simplified Chinese Locale",
|
|
1546
|
+
"nameZh": "简体中文本地化",
|
|
1547
|
+
"source": "extensions/locales/zh-cn.md",
|
|
1548
|
+
"category": "extension",
|
|
1549
|
+
"skillName": null,
|
|
1550
|
+
"description": "Simplified Chinese (Mainland China) localization for all standards",
|
|
1551
|
+
"applicability": "Simplified Chinese speaking teams"
|
|
1552
|
+
},
|
|
1539
1553
|
{
|
|
1540
1554
|
"id": "copilot-integration",
|
|
1541
1555
|
"name": "GitHub Copilot Instructions",
|
|
@@ -2295,7 +2309,7 @@
|
|
|
2295
2309
|
"id": "license-compliance",
|
|
2296
2310
|
"name": "License Compliance Standards",
|
|
2297
2311
|
"nameZh": "授權合規標準",
|
|
2298
|
-
"version": "6.14.0-beta.
|
|
2312
|
+
"version": "6.14.0-beta.4",
|
|
2299
2313
|
"source": {
|
|
2300
2314
|
"human": "core/license-compliance.md",
|
|
2301
2315
|
"ai": "ai/standards/license-compliance.ai.yaml"
|
|
@@ -2307,7 +2321,7 @@
|
|
|
2307
2321
|
"id": "verification-oracle",
|
|
2308
2322
|
"name": "Verification Oracle Standards",
|
|
2309
2323
|
"nameZh": "驗證 Oracle 標準",
|
|
2310
|
-
"version": "6.14.0-beta.
|
|
2324
|
+
"version": "6.14.0-beta.4",
|
|
2311
2325
|
"source": {
|
|
2312
2326
|
"human": "core/verification-oracle.md",
|
|
2313
2327
|
"ai": "ai/standards/verification-oracle.ai.yaml"
|
|
@@ -2319,7 +2333,7 @@
|
|
|
2319
2333
|
"id": "model-provenance",
|
|
2320
2334
|
"name": "Model Provenance Policy Standards",
|
|
2321
2335
|
"nameZh": "模型來源政策標準",
|
|
2322
|
-
"version": "6.14.0-beta.
|
|
2336
|
+
"version": "6.14.0-beta.4",
|
|
2323
2337
|
"source": {
|
|
2324
2338
|
"human": "core/model-provenance.md",
|
|
2325
2339
|
"ai": "ai/standards/model-provenance.ai.yaml"
|
|
@@ -2331,7 +2345,7 @@
|
|
|
2331
2345
|
"id": "resource-cost-boundary",
|
|
2332
2346
|
"name": "Resource / Cost Boundary Declaration Standards",
|
|
2333
2347
|
"nameZh": "資源/成本邊界宣告標準",
|
|
2334
|
-
"version": "6.14.0-beta.
|
|
2348
|
+
"version": "6.14.0-beta.4",
|
|
2335
2349
|
"source": {
|
|
2336
2350
|
"human": "core/resource-cost-boundary.md",
|
|
2337
2351
|
"ai": "ai/standards/resource-cost-boundary.ai.yaml"
|