i-repo 2.6.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 +12 -3
- package/dist/plugins/describe.d.ts +52 -0
- package/dist/plugins/describe.js +80 -1
- package/dist/plugins/templates.js +15 -6
- package/package.json +1 -1
package/dist/commands/plugin.js
CHANGED
|
@@ -98,17 +98,26 @@ 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
|
-
|
|
107
|
+
for (const key of ["platforms", "input", "roles", "capabilities", "useCases"]) {
|
|
108
|
+
if (Array.isArray(row[key])) {
|
|
109
|
+
row[key] = row[key].join(", ");
|
|
110
|
+
}
|
|
108
111
|
}
|
|
109
112
|
if (Array.isArray(row.subcommands)) {
|
|
110
113
|
row.subcommands = row.subcommands
|
|
111
|
-
.map((s) =>
|
|
114
|
+
.map((s) => {
|
|
115
|
+
const intake = Array.isArray(s.input) ? ` [${s.input.join("/")}]` : "";
|
|
116
|
+
const destructive = s.destructive ? " (destructive)" : "";
|
|
117
|
+
return s.description
|
|
118
|
+
? `${String(s.name)}${intake}${destructive} (${String(s.description)})`
|
|
119
|
+
: `${String(s.name)}${intake}${destructive}`;
|
|
120
|
+
})
|
|
112
121
|
.join(", ");
|
|
113
122
|
}
|
|
114
123
|
}
|
|
@@ -21,6 +21,31 @@ export declare const KNOWN_PLATFORMS: readonly ["macos", "linux", "windows"];
|
|
|
21
21
|
export type PluginPlatform = (typeof KNOWN_PLATFORMS)[number];
|
|
22
22
|
/** process.platform → platforms 語彙。未知の OS は null (= ゲート対象外) */
|
|
23
23
|
export declare function platformKeywordFor(p: NodeJS.Platform): PluginPlatform | null;
|
|
24
|
+
/**
|
|
25
|
+
* input (intake = データの受け取り方) の閉じた語彙 (要望書v2)。
|
|
26
|
+
* 「どう渡すか」を実行前に機械可読にする — sink にディレクトリを渡す等の
|
|
27
|
+
* 取り違えを連携側 (GUI/Connector) が起動前に検出できるようにする。
|
|
28
|
+
* CLI 本体はこれでゲートしない (宣言した意図を伝えるヒント。成否の判定は
|
|
29
|
+
* あくまで receipt の verified)。
|
|
30
|
+
*/
|
|
31
|
+
export declare const KNOWN_INPUTS: readonly ["stdin-ndjson", "files", "dir", "none"];
|
|
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];
|
|
24
49
|
/** params の1エントリ。GUI/ink がフォーム部品へ写像できる最小集合に絞る */
|
|
25
50
|
export interface PluginParam {
|
|
26
51
|
/** フラグ名 (例: "--bucket") */
|
|
@@ -39,11 +64,21 @@ export interface PluginParam {
|
|
|
39
64
|
placeholder?: string;
|
|
40
65
|
/** 属するサブコマンド (subcommands のいずれかの name)。未設定 = 全サブコマンド共通 */
|
|
41
66
|
subcommand?: string;
|
|
67
|
+
/**
|
|
68
|
+
* このフラグを渡すと不可逆な破壊 (削除等) を起こす申告 (要望書v3)。例: --cleanup。
|
|
69
|
+
* CLI 本体は実行可否を変えない (input と同じヒント) — 自動拒否は宣言を読む側
|
|
70
|
+
* (ADC/エージェント) の役割。GUI 無し面でのエージェント安全策の土台。
|
|
71
|
+
*/
|
|
72
|
+
destructive?: boolean;
|
|
42
73
|
}
|
|
43
74
|
/** サブコマンドの宣言 (要望5)。params[].subcommand がここの name を参照する */
|
|
44
75
|
export interface PluginSubcommand {
|
|
45
76
|
name: string;
|
|
46
77
|
description?: string;
|
|
78
|
+
/** このサブコマンドの intake。プラグインレベルの input を上書きする (要望書v2 §3.2) */
|
|
79
|
+
input?: PluginInput[];
|
|
80
|
+
/** このサブコマンド全体が不可逆な破壊を起こす申告 (要望書v3)。params[].destructive と同じ哲学 */
|
|
81
|
+
destructive?: boolean;
|
|
47
82
|
}
|
|
48
83
|
/** --plugin-schema 応答の全体形 (基本 + 拡張。未知フィールドは無視) */
|
|
49
84
|
export interface PluginDescribe {
|
|
@@ -59,6 +94,23 @@ export interface PluginDescribe {
|
|
|
59
94
|
/** 対応 OS。未宣言 = 制限なし。宣言があり現在の OS が含まれない場合、dispatch は実行を拒否する */
|
|
60
95
|
platforms?: PluginPlatform[];
|
|
61
96
|
subcommands?: PluginSubcommand[];
|
|
97
|
+
/**
|
|
98
|
+
* intake = データの受け取り方 (要望書v2)。未宣言 = 不明 (連携側は安全側 =
|
|
99
|
+
* 渡し方を推測しない)。subcommands[].input がある場合はそちらが優先。
|
|
100
|
+
*/
|
|
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[];
|
|
62
114
|
}
|
|
63
115
|
/**
|
|
64
116
|
* plugin describe の表示行を組む。plugin/path は CLI が解決した事実 —
|
package/dist/plugins/describe.js
CHANGED
|
@@ -31,6 +31,29 @@ export function platformKeywordFor(p) {
|
|
|
31
31
|
return "linux";
|
|
32
32
|
return null;
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* input (intake = データの受け取り方) の閉じた語彙 (要望書v2)。
|
|
36
|
+
* 「どう渡すか」を実行前に機械可読にする — sink にディレクトリを渡す等の
|
|
37
|
+
* 取り違えを連携側 (GUI/Connector) が起動前に検出できるようにする。
|
|
38
|
+
* CLI 本体はこれでゲートしない (宣言した意図を伝えるヒント。成否の判定は
|
|
39
|
+
* あくまで receipt の verified)。
|
|
40
|
+
*/
|
|
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"];
|
|
34
57
|
const PARAM_TYPES = new Set(["string", "number", "boolean", "select"]);
|
|
35
58
|
/**
|
|
36
59
|
* plugin describe の表示行を組む。plugin/path は CLI が解決した事実 —
|
|
@@ -112,7 +135,26 @@ export async function probePlatforms(bin, timeoutMs = 1500) {
|
|
|
112
135
|
}
|
|
113
136
|
/** 拡張フィールドのいずれかを宣言しているか */
|
|
114
137
|
export function hasDescribeFields(row) {
|
|
115
|
-
return [
|
|
138
|
+
return [
|
|
139
|
+
"name", "version", "description", "phases", "params", "platforms",
|
|
140
|
+
"subcommands", "input", "roles", "capabilities", "useCases",
|
|
141
|
+
].some((k) => k in row);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* input (intake) 宣言の検査。閉じた語彙の非空配列であること。
|
|
145
|
+
* "none" は「データ入力なし」なので他の値との併記は矛盾 — 受理すると
|
|
146
|
+
* 連携側が「渡さなくてよいのか stdin で渡すのか」を判断できない。
|
|
147
|
+
*/
|
|
148
|
+
function validateInputList(value, field) {
|
|
149
|
+
if (!Array.isArray(value) ||
|
|
150
|
+
value.length === 0 ||
|
|
151
|
+
!value.every((v) => typeof v === "string" && KNOWN_INPUTS.includes(v))) {
|
|
152
|
+
return `${field} must be a non-empty array of ${KNOWN_INPUTS.map((k) => `"${k}"`).join(" | ")}`;
|
|
153
|
+
}
|
|
154
|
+
if (value.includes("none") && value.length > 1) {
|
|
155
|
+
return `${field} must not combine "none" with other intake values`;
|
|
156
|
+
}
|
|
157
|
+
return null;
|
|
116
158
|
}
|
|
117
159
|
/**
|
|
118
160
|
* 宣言の形式検査。問題の説明文を返す (空配列 = 適合)。
|
|
@@ -142,6 +184,32 @@ export function validateDescribe(row) {
|
|
|
142
184
|
problems.push(`platforms must be a non-empty array of ${KNOWN_PLATFORMS.map((k) => `"${k}"`).join(" | ")}`);
|
|
143
185
|
}
|
|
144
186
|
}
|
|
187
|
+
if ("input" in row) {
|
|
188
|
+
const problem = validateInputList(row.input, "input");
|
|
189
|
+
if (problem)
|
|
190
|
+
problems.push(problem);
|
|
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
|
+
}
|
|
145
213
|
let declaredSubs = null;
|
|
146
214
|
if ("subcommands" in row) {
|
|
147
215
|
const subs = row.subcommands;
|
|
@@ -168,6 +236,14 @@ export function validateDescribe(row) {
|
|
|
168
236
|
if ("description" in s && typeof s.description !== "string") {
|
|
169
237
|
problems.push(`subcommands[${i}].description must be a string`);
|
|
170
238
|
}
|
|
239
|
+
if ("input" in s) {
|
|
240
|
+
const problem = validateInputList(s.input, `subcommands[${i}].input`);
|
|
241
|
+
if (problem)
|
|
242
|
+
problems.push(problem);
|
|
243
|
+
}
|
|
244
|
+
if ("destructive" in s && typeof s.destructive !== "boolean") {
|
|
245
|
+
problems.push(`subcommands[${i}].destructive must be a boolean`);
|
|
246
|
+
}
|
|
171
247
|
});
|
|
172
248
|
}
|
|
173
249
|
}
|
|
@@ -227,6 +303,9 @@ export function validateDescribe(row) {
|
|
|
227
303
|
if ("secret" in p && typeof p.secret !== "boolean") {
|
|
228
304
|
problems.push(`params[${i}].secret must be a boolean`);
|
|
229
305
|
}
|
|
306
|
+
if ("destructive" in p && typeof p.destructive !== "boolean") {
|
|
307
|
+
problems.push(`params[${i}].destructive must be a boolean`);
|
|
308
|
+
}
|
|
230
309
|
for (const key of ["label", "placeholder"]) {
|
|
231
310
|
if (key in p && typeof p[key] !== "string") {
|
|
232
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,14 +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"],
|
|
124
|
+
input: ["stdin-ndjson"],
|
|
125
|
+
roles: ["sink"],
|
|
118
126
|
params: [
|
|
119
127
|
{ name: "--dry-run", type: "boolean", label: "Dry run", description: "Validate without writing" },
|
|
120
128
|
],
|
|
@@ -132,11 +140,12 @@ if (api && api !== "1") {
|
|
|
132
140
|
const dryRun = arg0 === "--dry-run";
|
|
133
141
|
const jobId = \`${name}-\${new Date().toISOString().replace(/[-:.TZ]/g, "")}-\${process.pid}\`;
|
|
134
142
|
|
|
135
|
-
/** Emit a receipt line (SCHEMA.md §6). */
|
|
143
|
+
/** Emit a receipt line (SCHEMA.md §6). producedBy = 来歴 (版ズレ検知用・要望書v3). */
|
|
136
144
|
function receipt(phase, count, failedCount, verified) {
|
|
137
145
|
console.log(JSON.stringify({
|
|
138
146
|
schemaVersion: "1.0", recordType: "receipt", plugin: PLUGIN,
|
|
139
147
|
phase, jobId, count, failedCount, verified,
|
|
148
|
+
producedBy: { plugin: PLUGIN, version: VERSION },
|
|
140
149
|
}));
|
|
141
150
|
}
|
|
142
151
|
|