i-repo 2.7.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/commands/plugin.js
CHANGED
|
@@ -98,24 +98,25 @@ pluginCommand
|
|
|
98
98
|
.map((p) => {
|
|
99
99
|
const choices = Array.isArray(p.choices) ? `:${p.choices.join("|")}` : "";
|
|
100
100
|
const markers = `${p.required ? " (required)" : ""}${p.secret ? " (secret)" : ""}` +
|
|
101
|
+
`${p.destructive ? " (destructive)" : ""}` +
|
|
101
102
|
`${typeof p.subcommand === "string" ? ` [${p.subcommand}]` : ""}`;
|
|
102
103
|
return `${String(p.name)} <${String(p.type)}${choices}>${markers}`;
|
|
103
104
|
})
|
|
104
105
|
.join(", ");
|
|
105
106
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
row.input = row.input.join(", ");
|
|
107
|
+
for (const key of ["platforms", "input", "roles", "capabilities", "useCases"]) {
|
|
108
|
+
if (Array.isArray(row[key])) {
|
|
109
|
+
row[key] = row[key].join(", ");
|
|
110
|
+
}
|
|
111
111
|
}
|
|
112
112
|
if (Array.isArray(row.subcommands)) {
|
|
113
113
|
row.subcommands = row.subcommands
|
|
114
114
|
.map((s) => {
|
|
115
115
|
const intake = Array.isArray(s.input) ? ` [${s.input.join("/")}]` : "";
|
|
116
|
+
const destructive = s.destructive ? " (destructive)" : "";
|
|
116
117
|
return s.description
|
|
117
|
-
? `${String(s.name)}${intake} (${String(s.description)})`
|
|
118
|
-
: `${String(s.name)}${intake}`;
|
|
118
|
+
? `${String(s.name)}${intake}${destructive} (${String(s.description)})`
|
|
119
|
+
: `${String(s.name)}${intake}${destructive}`;
|
|
119
120
|
})
|
|
120
121
|
.join(", ");
|
|
121
122
|
}
|
|
@@ -30,6 +30,22 @@ export declare function platformKeywordFor(p: NodeJS.Platform): PluginPlatform |
|
|
|
30
30
|
*/
|
|
31
31
|
export declare const KNOWN_INPUTS: readonly ["stdin-ndjson", "files", "dir", "none"];
|
|
32
32
|
export type PluginInput = (typeof KNOWN_INPUTS)[number];
|
|
33
|
+
/**
|
|
34
|
+
* roles (プラグインが担う価値軸) の閉じた語彙 (要望書v3)。
|
|
35
|
+
* 「このプラグインは何をする向きか」を機械可読にする — エージェント/GUI が
|
|
36
|
+
* store 名から推測せず宣言を読むための土台。CLI 本体はこれでゲートしない
|
|
37
|
+
* (input/platforms と同じく宣言した意図を伝えるヒント)。閉じた語彙なので
|
|
38
|
+
* 綴り誤り (`sinks`/`reader` 等) は describe-shape の契約違反として検出される。
|
|
39
|
+
* source = 外部システムから取り出す入口
|
|
40
|
+
* sink = 抽出済みデータを保存先へ書き込む
|
|
41
|
+
* read = 着地済みを読み返す (read-only)
|
|
42
|
+
* search = 全文検索・ファセットに向く
|
|
43
|
+
* analyze = 集計・DWH・Lakehouse に向く
|
|
44
|
+
* keep = 成果物・証跡を束ねて残す
|
|
45
|
+
* 予約 (将来追加): lifecycle / derive / subscribe — 現時点では未採用。
|
|
46
|
+
*/
|
|
47
|
+
export declare const KNOWN_ROLES: readonly ["source", "sink", "read", "search", "analyze", "keep"];
|
|
48
|
+
export type PluginRole = (typeof KNOWN_ROLES)[number];
|
|
33
49
|
/** params の1エントリ。GUI/ink がフォーム部品へ写像できる最小集合に絞る */
|
|
34
50
|
export interface PluginParam {
|
|
35
51
|
/** フラグ名 (例: "--bucket") */
|
|
@@ -48,6 +64,12 @@ export interface PluginParam {
|
|
|
48
64
|
placeholder?: string;
|
|
49
65
|
/** 属するサブコマンド (subcommands のいずれかの name)。未設定 = 全サブコマンド共通 */
|
|
50
66
|
subcommand?: string;
|
|
67
|
+
/**
|
|
68
|
+
* このフラグを渡すと不可逆な破壊 (削除等) を起こす申告 (要望書v3)。例: --cleanup。
|
|
69
|
+
* CLI 本体は実行可否を変えない (input と同じヒント) — 自動拒否は宣言を読む側
|
|
70
|
+
* (ADC/エージェント) の役割。GUI 無し面でのエージェント安全策の土台。
|
|
71
|
+
*/
|
|
72
|
+
destructive?: boolean;
|
|
51
73
|
}
|
|
52
74
|
/** サブコマンドの宣言 (要望5)。params[].subcommand がここの name を参照する */
|
|
53
75
|
export interface PluginSubcommand {
|
|
@@ -55,6 +77,8 @@ export interface PluginSubcommand {
|
|
|
55
77
|
description?: string;
|
|
56
78
|
/** このサブコマンドの intake。プラグインレベルの input を上書きする (要望書v2 §3.2) */
|
|
57
79
|
input?: PluginInput[];
|
|
80
|
+
/** このサブコマンド全体が不可逆な破壊を起こす申告 (要望書v3)。params[].destructive と同じ哲学 */
|
|
81
|
+
destructive?: boolean;
|
|
58
82
|
}
|
|
59
83
|
/** --plugin-schema 応答の全体形 (基本 + 拡張。未知フィールドは無視) */
|
|
60
84
|
export interface PluginDescribe {
|
|
@@ -75,6 +99,18 @@ export interface PluginDescribe {
|
|
|
75
99
|
* 渡し方を推測しない)。subcommands[].input がある場合はそちらが優先。
|
|
76
100
|
*/
|
|
77
101
|
input?: PluginInput[];
|
|
102
|
+
/**
|
|
103
|
+
* roles = プラグインが担う価値軸の宣言 (要望書v3)。閉じた語彙 (KNOWN_ROLES)。
|
|
104
|
+
* 未宣言 = 不明 (連携側は推測しない)。
|
|
105
|
+
*/
|
|
106
|
+
roles?: PluginRole[];
|
|
107
|
+
/**
|
|
108
|
+
* capabilities = 細粒度の能力タグ (要望書v3)。開いた語彙 (例 "cluster-filter") —
|
|
109
|
+
* verify は型 (string[]) のみ検証し、メンバーシップは検証しない (綴り誤りは検出しない)。
|
|
110
|
+
*/
|
|
111
|
+
capabilities?: string[];
|
|
112
|
+
/** useCases = 用途タグ (要望書v3)。capabilities と同じく開いた語彙・型のみ検証 */
|
|
113
|
+
useCases?: string[];
|
|
78
114
|
}
|
|
79
115
|
/**
|
|
80
116
|
* plugin describe の表示行を組む。plugin/path は CLI が解決した事実 —
|
package/dist/plugins/describe.js
CHANGED
|
@@ -39,6 +39,21 @@ export function platformKeywordFor(p) {
|
|
|
39
39
|
* あくまで receipt の verified)。
|
|
40
40
|
*/
|
|
41
41
|
export const KNOWN_INPUTS = ["stdin-ndjson", "files", "dir", "none"];
|
|
42
|
+
/**
|
|
43
|
+
* roles (プラグインが担う価値軸) の閉じた語彙 (要望書v3)。
|
|
44
|
+
* 「このプラグインは何をする向きか」を機械可読にする — エージェント/GUI が
|
|
45
|
+
* store 名から推測せず宣言を読むための土台。CLI 本体はこれでゲートしない
|
|
46
|
+
* (input/platforms と同じく宣言した意図を伝えるヒント)。閉じた語彙なので
|
|
47
|
+
* 綴り誤り (`sinks`/`reader` 等) は describe-shape の契約違反として検出される。
|
|
48
|
+
* source = 外部システムから取り出す入口
|
|
49
|
+
* sink = 抽出済みデータを保存先へ書き込む
|
|
50
|
+
* read = 着地済みを読み返す (read-only)
|
|
51
|
+
* search = 全文検索・ファセットに向く
|
|
52
|
+
* analyze = 集計・DWH・Lakehouse に向く
|
|
53
|
+
* keep = 成果物・証跡を束ねて残す
|
|
54
|
+
* 予約 (将来追加): lifecycle / derive / subscribe — 現時点では未採用。
|
|
55
|
+
*/
|
|
56
|
+
export const KNOWN_ROLES = ["source", "sink", "read", "search", "analyze", "keep"];
|
|
42
57
|
const PARAM_TYPES = new Set(["string", "number", "boolean", "select"]);
|
|
43
58
|
/**
|
|
44
59
|
* plugin describe の表示行を組む。plugin/path は CLI が解決した事実 —
|
|
@@ -120,7 +135,10 @@ export async function probePlatforms(bin, timeoutMs = 1500) {
|
|
|
120
135
|
}
|
|
121
136
|
/** 拡張フィールドのいずれかを宣言しているか */
|
|
122
137
|
export function hasDescribeFields(row) {
|
|
123
|
-
return [
|
|
138
|
+
return [
|
|
139
|
+
"name", "version", "description", "phases", "params", "platforms",
|
|
140
|
+
"subcommands", "input", "roles", "capabilities", "useCases",
|
|
141
|
+
].some((k) => k in row);
|
|
124
142
|
}
|
|
125
143
|
/**
|
|
126
144
|
* input (intake) 宣言の検査。閉じた語彙の非空配列であること。
|
|
@@ -171,6 +189,27 @@ export function validateDescribe(row) {
|
|
|
171
189
|
if (problem)
|
|
172
190
|
problems.push(problem);
|
|
173
191
|
}
|
|
192
|
+
if ("roles" in row) {
|
|
193
|
+
// 閉じた語彙を強制する: typo (`sinks`/`reader` 等) を受理すると、宣言したのに
|
|
194
|
+
// エージェント/GUI のどの判定にもマッチしない沈黙の失敗になる。空配列は
|
|
195
|
+
// 「役割なし」= 宣言ミス扱い (未宣言と区別する意味がない)。
|
|
196
|
+
const r = row.roles;
|
|
197
|
+
if (!Array.isArray(r) ||
|
|
198
|
+
r.length === 0 ||
|
|
199
|
+
!r.every((v) => typeof v === "string" && KNOWN_ROLES.includes(v))) {
|
|
200
|
+
problems.push(`roles must be a non-empty array of ${KNOWN_ROLES.map((k) => `"${k}"`).join(" | ")}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// capabilities / useCases は開いた語彙 — 型 (string[]) だけ検証し、値は検証しない
|
|
204
|
+
// (phases と同じ扱い)。未知の能力タグを宣言できるようにするのが要望の主旨。
|
|
205
|
+
for (const key of ["capabilities", "useCases"]) {
|
|
206
|
+
if (key in row) {
|
|
207
|
+
const v = row[key];
|
|
208
|
+
if (!Array.isArray(v) || !v.every((x) => typeof x === "string")) {
|
|
209
|
+
problems.push(`${key} must be an array of strings`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
174
213
|
let declaredSubs = null;
|
|
175
214
|
if ("subcommands" in row) {
|
|
176
215
|
const subs = row.subcommands;
|
|
@@ -202,6 +241,9 @@ export function validateDescribe(row) {
|
|
|
202
241
|
if (problem)
|
|
203
242
|
problems.push(problem);
|
|
204
243
|
}
|
|
244
|
+
if ("destructive" in s && typeof s.destructive !== "boolean") {
|
|
245
|
+
problems.push(`subcommands[${i}].destructive must be a boolean`);
|
|
246
|
+
}
|
|
205
247
|
});
|
|
206
248
|
}
|
|
207
249
|
}
|
|
@@ -261,6 +303,9 @@ export function validateDescribe(row) {
|
|
|
261
303
|
if ("secret" in p && typeof p.secret !== "boolean") {
|
|
262
304
|
problems.push(`params[${i}].secret must be a boolean`);
|
|
263
305
|
}
|
|
306
|
+
if ("destructive" in p && typeof p.destructive !== "boolean") {
|
|
307
|
+
problems.push(`params[${i}].destructive must be a boolean`);
|
|
308
|
+
}
|
|
264
309
|
for (const key of ["label", "placeholder"]) {
|
|
265
310
|
if (key in p && typeof p[key] !== "string") {
|
|
266
311
|
problems.push(`params[${i}].${key} must be a string`);
|
|
@@ -24,8 +24,10 @@ case "\${1:-}" in
|
|
|
24
24
|
printf '{"ok":true,"checks":[{"name":"ready","ok":true,"severity":"required","hint":"TODO: how to fix when this fails"}]}\\n'
|
|
25
25
|
exit 0 ;;
|
|
26
26
|
--plugin-schema)
|
|
27
|
-
# 自己記述 (PLUGINS.md §3)。params は GUI/ink
|
|
28
|
-
|
|
27
|
+
# 自己記述 (PLUGINS.md §3)。params は GUI/ink のフォーム生成に使われる。
|
|
28
|
+
# roles: 担う価値軸 (閉じた語彙 source|sink|read|search|analyze|keep)。sink が既定。
|
|
29
|
+
# 破壊的フラグ (削除等) があれば params に "destructive":true を付ける (要望書v3)。
|
|
30
|
+
printf '{"pluginApi":["1"],"schemaVersions":["1.0"],"recordTypes":["*"],"name":"i-repo-${name}","version":"0.1.0","description":"TODO: what this plugin does","phases":["write","verify"],"platforms":["macos","linux"],"input":["stdin-ndjson"],"roles":["sink"],"params":[{"name":"--dry-run","type":"boolean","label":"Dry run","description":"Validate without writing"}]}\\n'
|
|
29
31
|
exit 0 ;;
|
|
30
32
|
esac
|
|
31
33
|
|
|
@@ -41,8 +43,9 @@ dryrun=false
|
|
|
41
43
|
jobId="${name}-\$(date +%Y%m%dT%H%M%S)-\$\$"
|
|
42
44
|
|
|
43
45
|
# $1=phase $2=count $3=failedCount $4=verified (SCHEMA.md §6)
|
|
46
|
+
# producedBy = 来歴 (どのプラグインの何版が作ったか。版ズレ検知用・要望書v3)
|
|
44
47
|
emit_receipt() {
|
|
45
|
-
printf '{"schemaVersion":"1.0","recordType":"receipt","plugin":"i-repo-${name}","phase":"%s","jobId":"%s","count":%s,"failedCount":%s,"verified":%s}\\n' \\
|
|
48
|
+
printf '{"schemaVersion":"1.0","recordType":"receipt","plugin":"i-repo-${name}","phase":"%s","jobId":"%s","count":%s,"failedCount":%s,"verified":%s,"producedBy":{"plugin":"i-repo-${name}","version":"0.1.0"}}\\n' \\
|
|
46
49
|
"\$1" "\$jobId" "\$2" "\$3" "\$4"
|
|
47
50
|
}
|
|
48
51
|
|
|
@@ -107,15 +110,19 @@ if (arg0 === "--plugin-healthcheck") {
|
|
|
107
110
|
}));
|
|
108
111
|
process.exit(0);
|
|
109
112
|
}
|
|
113
|
+
const VERSION = "0.1.0";
|
|
110
114
|
if (arg0 === "--plugin-schema") {
|
|
111
|
-
// 自己記述 (PLUGINS.md §3)。params は GUI/ink
|
|
115
|
+
// 自己記述 (PLUGINS.md §3)。params は GUI/ink のフォーム生成に使われる。
|
|
116
|
+
// roles: 担う価値軸 (閉じた語彙 source|sink|read|search|analyze|keep)。sink が既定。
|
|
117
|
+
// 破壊的フラグ (削除等) があれば該当 param に destructive: true を付ける (要望書v3)。
|
|
112
118
|
console.log(JSON.stringify({
|
|
113
119
|
pluginApi: ["1"], schemaVersions: ["1.0"], recordTypes: ["*"],
|
|
114
|
-
name: PLUGIN, version:
|
|
120
|
+
name: PLUGIN, version: VERSION,
|
|
115
121
|
description: "TODO: what this plugin does",
|
|
116
122
|
phases: ["write", "verify"],
|
|
117
123
|
platforms: ["macos", "linux", "windows"],
|
|
118
124
|
input: ["stdin-ndjson"],
|
|
125
|
+
roles: ["sink"],
|
|
119
126
|
params: [
|
|
120
127
|
{ name: "--dry-run", type: "boolean", label: "Dry run", description: "Validate without writing" },
|
|
121
128
|
],
|
|
@@ -133,11 +140,12 @@ if (api && api !== "1") {
|
|
|
133
140
|
const dryRun = arg0 === "--dry-run";
|
|
134
141
|
const jobId = \`${name}-\${new Date().toISOString().replace(/[-:.TZ]/g, "")}-\${process.pid}\`;
|
|
135
142
|
|
|
136
|
-
/** Emit a receipt line (SCHEMA.md §6). */
|
|
143
|
+
/** Emit a receipt line (SCHEMA.md §6). producedBy = 来歴 (版ズレ検知用・要望書v3). */
|
|
137
144
|
function receipt(phase, count, failedCount, verified) {
|
|
138
145
|
console.log(JSON.stringify({
|
|
139
146
|
schemaVersion: "1.0", recordType: "receipt", plugin: PLUGIN,
|
|
140
147
|
phase, jobId, count, failedCount, verified,
|
|
148
|
+
producedBy: { plugin: PLUGIN, version: VERSION },
|
|
141
149
|
}));
|
|
142
150
|
}
|
|
143
151
|
|