i-repo 2.7.0 → 2.9.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.
@@ -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
- if (Array.isArray(row.platforms)) {
107
- row.platforms = row.platforms.join(", ");
108
- }
109
- if (Array.isArray(row.input)) {
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 が解決した事実 —
@@ -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 ["name", "version", "description", "phases", "params", "platforms", "subcommands", "input"].some((k) => k in row);
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
- 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"],"params":[{"name":"--dry-run","type":"boolean","label":"Dry run","description":"Validate without writing"}]}\\n'
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: "0.1.0",
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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i-repo",
3
- "version": "2.7.0",
3
+ "version": "2.9.0",
4
4
  "description": "Modern CLI for ConMas i-Reporter - Built for humans and AI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -17,12 +17,19 @@
17
17
  "generate:fixtures": "node scripts/generate-fixtures.mjs",
18
18
  "test": "vitest run",
19
19
  "test:watch": "vitest",
20
+ "check:adc": "node scripts/check-adc.mjs",
21
+ "gen:agents": "node scripts/gen-agents-md.mjs",
20
22
  "audit": "npm audit --omit=dev --audit-level=high",
21
23
  "prepublishOnly": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && npm run build"
22
24
  },
23
25
  "files": [
24
26
  "dist",
25
- "README.md"
27
+ "README.md",
28
+ "spec/gemba-adc",
29
+ "plugins",
30
+ "scripts/irepo-mcp.mjs",
31
+ "scripts/gen-agents-md.mjs",
32
+ "scripts/check-adc.mjs"
26
33
  ],
27
34
  "keywords": [
28
35
  "ireporter",
@@ -0,0 +1,58 @@
1
+ # plugins/ — i-Repo GEMBA OS 同梱プラグイン
2
+
3
+ i-Repo GEMBA OS(旧称 i-Repo Data Connector)が利用する i-repo CLI プラグインの**正本**です。
4
+ 従来は `~/.i-repo/plugins/` にしか存在せず版管理外でしたが、ここをリポジトリ内の
5
+ single source of truth とし、インストーラで各環境へ配置します。
6
+
7
+ > 構成: 各プラグインは単一ファイル実行体 + 共有ライブラリ `lib/gemba-read.js`
8
+ > (読み返し `query` の共通エンジン: envelope / 時刻3形式パース / keysetカーソル。
9
+ > ADC-1 仕様 `docs/仕様/` 参照)。インストーラが `lib/` ごと配布し、プラグインは
10
+ > `./lib/gemba-read.js` を相対 require する(write 経路は lib 非依存)。
11
+ > **プラグインを更新したら必ずインストーラを再実行すること** — アプリ/CLI が呼ぶのは
12
+ > `~/.i-repo/plugins/` のインストール済み実体であり、リポジトリ正本ではない。
13
+
14
+ ## 同梱プラグイン
15
+
16
+ | ファイル | 役割 | 由来 |
17
+ |---|---|---|
18
+ | `i-repo-archive` | 帳票スナップショット+S3 push。`--with-detail` 対応 | **i-repo CLI公式 archive のパッチ版**(`--with-detail` を追加) |
19
+ | `i-repo-mongo` | MongoDBへupsert | このプロジェクトで作成 |
20
+ | `i-repo-sqlite` | ローカルSQLiteへ蓄積 | このプロジェクトで作成 |
21
+ | `i-repo-elastic` | Elasticsearchへindex | このプロジェクトで作成 |
22
+ | `i-repo-parquet` | Parquet / Apache Iceberg へ書き出し | このプロジェクトで作成 |
23
+
24
+ > `i-repo-s3` と `i-repo-hello` は i-repo CLI 同梱のサンプルのため含めていません。
25
+ > 使い方は [../docs/プラグイン使い方集/](../docs/プラグイン使い方集/) を参照。
26
+
27
+ > ⚠️ `i-repo-archive` はCLI公式プラグインに `--with-detail`(クラスター値・objectKeyの
28
+ > manifest埋め込み)を加えたパッチ版です。CLI本体のアップデートで上書きされる可能性があるため、
29
+ > このリポジトリ版を正本とし、インストーラで配置します。本来はCLIチームへの取り込み依頼が筋
30
+ > ([../docs/CLI要望書/](../docs/CLI要望書/) 参照)。
31
+
32
+ ## インストール
33
+
34
+ ```bash
35
+ # macOS / Linux
36
+ ./plugins/install.sh
37
+
38
+ # Windows (PowerShell) — Node製プラグインの .cmd shim も生成する
39
+ powershell -ExecutionPolicy Bypass -File .\plugins\install.ps1
40
+ ```
41
+
42
+ 配置先は既定で `~/.i-repo/plugins/`(環境変数 `IREPO_PLUGIN_DIR` で変更可)。
43
+
44
+ 確認:
45
+ ```bash
46
+ i-repo plugin list # archive/mongo/sqlite/elastic/parquet が見えること
47
+ i-repo plugin verify mongo # 契約適合チェック
48
+ ```
49
+
50
+ ## 前提
51
+
52
+ - **Node.js**: mongo/sqlite/elastic/parquet/archive は Node 製。
53
+ - sqlite は `node:sqlite`(Node 22.5+)、elastic は内蔵 fetch(Node 18+)を使用。
54
+ - 各プラグインの追加依存(任意・使う配信先に応じて):
55
+ - mongo → `mongosh`
56
+ - parquet → `duckdb`(Iceberg書き込みは DuckDB 1.4+)
57
+ - archive push-s3 / s3 → `aws` CLI
58
+ - 充足状況は Connector アプリの「プラグイン」タブ、または `i-repo <plugin> --plugin-healthcheck` で確認できる。