@shinaps/skills 0.45.0 → 0.47.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 CHANGED
@@ -8,7 +8,7 @@ Claude Code と Codex で使う、開発ワークフローのスキル集です
8
8
  ## 必要なもの
9
9
 
10
10
  - Claude Code または Codex CLI
11
- - Node.js 22.13 以上の 22 系、または 24 以上(Codex への導入と、設定の検証・Managed Agents の操作・規約の機械検査に使う[配布 CLI](docs/install.md#配布-cli)に必要。機械検査の ESLint の要件に合わせている)。配布 CLI は機械検査のために ESLint・typescript-eslint・TypeScript などを依存に持ち、導入に約 50MB を使います。
11
+ - Node.js 22.13 以上の 22 系、または 24 以上(Codex への導入と、設定の検証・Managed Agents の操作・規約の機械検査に使う[配布 CLI](docs/install.md#配布-cli)に必要。機械検査の ESLint の要件に合わせている)。配布 CLI は機械検査のために ESLint・typescript-eslint・TypeScript などを依存に持ち、導入に約 65MB を使います。
12
12
  - 機能によって追加で必要なもの(Linear・Claude Managed Agents など)は、下の「機能別の資料」の各資料に書いています。
13
13
 
14
14
  ## インストール
@@ -38,6 +38,57 @@ const preferPromiseWithResolvers = {
38
38
  };
39
39
  },
40
40
  };
41
+ /**
42
+ * Vue の `:key` が v-for の index を使う書き方を報告する。index は v-for の 2 番目以降の別名
43
+ * (`(item, i) in items` の i、`(value, name, i) in object` の i) とする。オブジェクトの反復の 2 番目
44
+ * (`(value, name) in object` の name、プロパティ名) も構文では配列の index と区別できないので報告する。
45
+ * `items[i].id` のようにメンバーの計算プロパティとしてだけ使う参照は、index で引いた値の id なので報告しない。
46
+ * テンプレートを解析できないファイル (vue-eslint-parser 以外、HTML 以外のテンプレート) では何もしない。
47
+ */
48
+ const vueNoIndexKey = {
49
+ meta: {
50
+ type: 'problem',
51
+ docs: {
52
+ description: 'Disallow v-for keys derived from the iteration index',
53
+ },
54
+ messages: {
55
+ indexKey: "The key uses the v-for index '{{name}}'. Use a stable identifier of the item (an id or slug).",
56
+ },
57
+ schema: [],
58
+ },
59
+ create(context) {
60
+ // ESLint の parserServices は parser ごとに中身が違う。vue-eslint-parser で読んだときだけ
61
+ // defineTemplateBodyVisitor がある。
62
+ const services = context.sourceCode.parserServices;
63
+ if (!services.defineTemplateBodyVisitor)
64
+ return {};
65
+ // defineTemplateBodyVisitor の戻り値は object 型だが、実体は ESLint に渡す visitor。
66
+ return services.defineTemplateBodyVisitor({
67
+ "VAttribute[directive=true][key.name.name='bind'][key.argument.name='key']"(node) {
68
+ for (const reference of node.value?.references ?? []) {
69
+ const variable = reference.variable;
70
+ if (variable?.kind !== 'v-for')
71
+ continue;
72
+ const forExpression = variable.id.parent;
73
+ if (forExpression?.type !== 'VForExpression')
74
+ continue;
75
+ if (forExpression.left.indexOf(variable.id) < 1)
76
+ continue;
77
+ const parent = reference.id.parent;
78
+ if (parent?.type === 'MemberExpression' &&
79
+ parent.computed &&
80
+ parent.property === reference.id)
81
+ continue;
82
+ context.report({
83
+ node: reference.id,
84
+ messageId: 'indexKey',
85
+ data: { name: reference.id.name },
86
+ });
87
+ }
88
+ },
89
+ });
90
+ },
91
+ };
41
92
  function findVariable(scope, name) {
42
93
  for (let current = scope; current; current = current.upper) {
43
94
  const variable = current.set.get(name);
@@ -48,5 +99,8 @@ function findVariable(scope, name) {
48
99
  }
49
100
  export const shinapsPlugin = {
50
101
  meta: { name: 'shinaps' },
51
- rules: { 'prefer-promise-with-resolvers': preferPromiseWithResolvers },
102
+ rules: {
103
+ 'prefer-promise-with-resolvers': preferPromiseWithResolvers,
104
+ 'vue-no-index-key': vueNoIndexKey,
105
+ },
52
106
  };
package/dist/lib/lint.js CHANGED
@@ -154,18 +154,47 @@ function isActive(config, rule) {
154
154
  const severity = Array.isArray(entry) ? entry[0] : entry;
155
155
  return severity !== undefined && severity !== 0 && severity !== 'off';
156
156
  }
157
+ /**
158
+ * react-x から登録するルール。型情報を使うのに meta.docs.requiresTypeChecking を宣言しないルール
159
+ * (no-implicit-key、no-leaked-conditional-rendering など。ESLintUtils.getParserServices を呼ぶ) は、型なしの
160
+ * 実行単位に入って lintFiles を例外で止め、同じ単位の他の検査まで not-run にするので登録しない。
161
+ * 追加するときは、型を使わないことをソースで確かめる (docs/lint.md)。
162
+ */
163
+ const REACT_X_RULES = [
164
+ 'rules-of-hooks',
165
+ 'exhaustive-deps',
166
+ 'no-array-index-key',
167
+ 'no-missing-key',
168
+ 'no-nested-component-definitions',
169
+ 'no-unstable-context-value',
170
+ ];
171
+ /**
172
+ * react-x が判定の前提にする React の版。settings に版が無いと、react-x (@eslint-react/shared の
173
+ * getReactVersion) は `createRequire(process.cwd())("react")` でプロジェクトの react を読み込むため、固定して
174
+ * 呼ばせない。値は react-x が検出に失敗したときの既定と同じ。React 18 のプロジェクトでも 19 の前提で判定する
175
+ * (`<Context value>` の省略形を provider として扱うなど、報告が増える側に寄る)。
176
+ */
177
+ const REACT_X_SETTINGS = { 'react-x': { version: '19.3.0' } };
157
178
  async function loadRegistry() {
158
- const [{ builtinRules }, tseslint, vue, vueParser] = await Promise.all([
179
+ const [{ builtinRules }, tseslint, vue, vueParser, reactX, regexp] = await Promise.all([
159
180
  import('eslint/use-at-your-own-risk'),
160
181
  import('typescript-eslint'),
161
182
  import('eslint-plugin-vue'),
162
183
  import('vue-eslint-parser'),
184
+ import('eslint-plugin-react-x'),
185
+ import('eslint-plugin-regexp'),
163
186
  ]);
164
- // typescript-eslint と eslint-plugin-vue が公開する型は ESLint の Plugin・Parser・RuleModule の型と
165
- // 細部が一致しない (どちらも実行時は ESLint の API に従う)。flat config に渡すために ESLint の型にする。
187
+ // typescript-eslint・eslint-plugin-vue・eslint-plugin-react-x が公開する型は ESLint の Plugin・Parser・
188
+ // RuleModule の型と細部が一致しない (どれも実行時は ESLint の API に従う)。flat config に渡すために ESLint の型にする。
189
+ const reactXRules = reactX.default.rules;
166
190
  const plugins = {
167
191
  '@typescript-eslint': tseslint.default.plugin,
168
192
  vue: vue.default,
193
+ 'react-x': {
194
+ meta: reactX.default.meta,
195
+ rules: Object.fromEntries(REACT_X_RULES.map((name) => [name, reactXRules[name]])),
196
+ },
197
+ regexp: regexp.default,
169
198
  shinaps: shinapsPlugin,
170
199
  };
171
200
  const rules = new Map(builtinRules);
@@ -226,6 +255,7 @@ function unitConfig(registry, root, typed, rules) {
226
255
  ...rules.map((planned) => ({
227
256
  files: [...new Set(planned.bindings.flatMap((binding) => binding.check.files))],
228
257
  plugins: registry.plugins,
258
+ settings: REACT_X_SETTINGS,
229
259
  // options は JSON の配列 (unknown[]) で、ESLint の RuleEntry は要素の型を持たないので型だけを合わせる。
230
260
  rules: { [planned.rule]: ['error', ...planned.options] },
231
261
  })),
package/docs/install.md CHANGED
@@ -26,7 +26,7 @@ npx @shinaps/skills@latest recover codex
26
26
  設定の検証(`validate-linear-config`・`validate-managed-config`)、Managed Agents の操作(`managed`)、規約の機械検査(`lint`、[規約の機械検査](lint.md))には、配布 CLI `shinaps-skills` を使います。CLI は plugin に含まれないため、利用中のスキルと同じ版を導入します。
27
27
 
28
28
  ```sh
29
- npm install -g @shinaps/skills@0.45.0
29
+ npm install -g @shinaps/skills@0.47.0
30
30
  shinaps-skills --version
31
31
  ```
32
32
 
package/docs/lint.md CHANGED
@@ -4,7 +4,7 @@ Shinaps AIの規約が持つ機械検査(`checks`)を手元で実行し、
4
4
 
5
5
  ## 前提と保証
6
6
 
7
- - プロジェクトの変更は要りません。プロジェクトのlint設定(`eslint.config.*`・`.oxlintrc.json`・`bunfig.toml` など)・`package.json` のscript・`node_modules` のパッケージは読み込みません。ESLintのNode APIを `overrideConfigFile: true` で使い、パーサーとプラグインはこのパッケージの依存から渡します。読むのは対象ファイルと、型情報を使うルールのための `tsconfig.json`・型宣言だけです(実行はしません)。
7
+ - プロジェクトの変更は要りません。プロジェクトのlint設定(`eslint.config.*`・`.oxlintrc.json`・`bunfig.toml` など)・`package.json` のscript・`node_modules` のパッケージは読み込みません。ESLintのNode APIを `overrideConfigFile: true` で使い、パーサーとプラグインはこのパッケージの依存から渡します。読むのは対象ファイルと、型情報を使うルールのための `tsconfig.json`・型宣言だけです(実行はしません)。React のルール(react-x)が判定に使う React の版は、プロジェクトの `react` から検出させず `19.3.0` に固定します(React 18 のプロジェクトでも 19 の前提で判定するので、`<Context value>` の省略形を provider として扱うなど、報告が増える側に寄ります)。
8
8
  - 対象ファイルへ書き込みません(自動修正はしません)。結果はローカルのファイルに書き、サーバーへは送りません。
9
9
  - プロジェクトの `eslint-disable` コメントでは検査を抑止しません(`allowInlineConfig: false`)。プロジェクトの都合の例外は、指摘を確認する側で扱います。
10
10
  - 組をAI照合から外してよいのは、coverage が `full` の検査が、ESLintの判定でそのファイルに適用され、検査の実行単位が完了し、そのファイルに致命的な報告もruleIdの無い報告も無いときだけです。それ以外の組は `not-run`(または `partial`)として返し、合格にしません。coverage は検査を登録したときの判断で、このCLIは値を読むだけです。
@@ -44,7 +44,9 @@ shinaps-skills lint --checks <checks.json> --root <project> --out <result.json>
44
44
 
45
45
  ## 実行の仕組み
46
46
 
47
- 1. 各検査のルールを、ESLint core・`@typescript-eslint`・`vue`・同梱の `shinaps` から引きます。この版に無いルールの検査は `not-run` になり、他の検査は止まりません。
47
+ 1. 各検査のルールを、ESLint core・`@typescript-eslint`・`vue`・`react-x`(下の6ルールだけ)・`regexp`・同梱の `shinaps` から引きます。この版に無いルールの検査は `not-run` になり、他の検査は止まりません。
48
+ - `react-x`(eslint-plugin-react-x): `rules-of-hooks`・`exhaustive-deps`・`no-array-index-key`・`no-missing-key`・`no-nested-component-definitions`・`no-unstable-context-value`。react-x には型情報を使うのに `meta.docs.requiresTypeChecking` を宣言しないルールがあり、型なしの実行単位に入ると単位の全ての検査を止めるため、型を使わないことをソースで確かめたルールだけを登録します(`lib/lint.ts` の `REACT_X_RULES`)。他の外部プラグインでも、型を使うのに宣言しないルールは登録しません。
49
+ - `regexp`(eslint-plugin-regexp): 全てのルール。型情報は有無を確かめてから使います。
48
50
  2. 検査ごとに、その検査の設定だけを入れたESLintで `calculateConfigForFile` を呼び、ルールが有効なファイルを適用先にします。globの解釈はESLintだけが行います。ESLintが設定を拒否した検査(不正なoptionsなど)は、ここで `not-run` になります。
49
51
  3. 同じルール・同じoptionsの検査は1つの設定にまとめ、同じルールでoptionsが違うものだけを別の実行単位にします。型情報を使うルール(`meta.docs.requiresTypeChecking`)は `projectService` を使う単位に分けます。この単位は全てのファイルを typescript-eslint で読み、型の得られないファイル(`tsconfig.json` に含まれないTS・JS、Vue)はそのファイルだけが `not-run` になります。型なしの検査と、他のファイルの型付きの検査は影響を受けません。型情報を使うルールはVueのファイルでは実行できません。
50
52
  4. 実行単位ごとに `lintFiles` を1回呼び、組を分類します。指摘は、ESLintがそのファイルに適用すると判定した検査の規約にだけ付けます。
@@ -54,6 +56,7 @@ shinaps-skills lint --checks <checks.json> --root <project> --out <result.json>
54
56
  | ルールID | 内容 | 型情報 |
55
57
  | --- | --- | --- |
56
58
  | `shinaps/prefer-promise-with-resolvers` | Promiseのexecutorが受け取る `resolve`・`reject` を、executorの外で使うために変数・プロパティへ代入する書き方(deferred promise)を報告する。`Promise.withResolvers()` で書ける。包んだ関数の代入や、値として渡す呼び出しは報告しない | 不要 |
59
+ | `shinaps/vue-no-index-key` | Vueの `:key` が v-for の2番目以降の別名(配列の index)を参照する書き方を報告する。オブジェクトの反復の2番目(プロパティ名)も構文では区別できないので報告する。`items[i].id` のようにメンバーの計算プロパティとしてだけ使う参照は報告しない。HTML以外のテンプレート(`lang="pug"` など)は解析しないので何も報告しない | 不要 |
57
60
 
58
61
  ### 同梱ルールの追加
59
62
 
@@ -68,4 +71,4 @@ shinaps-skills lint --checks <checks.json> --root <project> --out <result.json>
68
71
 
69
72
  ## 依存
70
73
 
71
- ESLint・typescript-eslint・TypeScript・vue-eslint-parser・eslint-plugin-vue を完全一致の版で依存に持ちます(パッケージの導入が約50MB増えます)。typescript-eslint は TypeScript 7 に対応していないため、TypeScript は6系です(開発用の `tsc` も同じ版を使います)。
74
+ ESLint・typescript-eslint・TypeScript・vue-eslint-parser・eslint-plugin-vue・eslint-plugin-react-x・eslint-plugin-regexp を完全一致の版で依存に持ちます(パッケージの導入は約65MBになります)。外部プラグインの版を上げるときは、そのルールを使う公式規約の checks の coverage がルールの挙動を前提にしているので、規約の Good・Bad と見逃しの境界の例を同じ版で実行し直して確かめます。typescript-eslint は TypeScript 7 に対応していないため、TypeScript は6系です(開発用の `tsc` も同じ版を使います)。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shinaps/skills",
3
- "version": "0.45.0",
3
+ "version": "0.47.0",
4
4
  "description": "Install Shinaps AI workflows and custom agents for Codex",
5
5
  "type": "module",
6
6
  "bin": {
@@ -41,6 +41,8 @@
41
41
  "dependencies": {
42
42
  "ajv": "^8.20.0",
43
43
  "eslint": "10.14.0",
44
+ "eslint-plugin-react-x": "5.28.8",
45
+ "eslint-plugin-regexp": "3.3.2",
44
46
  "eslint-plugin-vue": "10.12.0",
45
47
  "typescript": "6.0.3",
46
48
  "typescript-eslint": "8.72.1",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "shinaps",
3
3
  "description": "Shinaps AIの開発ワークフロー。プロジェクトの指示から条件を読み、調査・設計・実装・簡素化・レビュー・コミット・PR・リリースとLinearでの開発進行を支援する。",
4
- "version": "0.45.0",
4
+ "version": "0.47.0",
5
5
  "author": {
6
6
  "name": "shinaps"
7
7
  },
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## 検証CLIと契約版
6
6
 
7
- 利用中のskillとCLIの版を確認し、0.45.0のskillには同じ版のnpm CLIを導入する(`npm install -g @shinaps/skills@0.45.0`)。pluginだけにはCLIは含まれない。導入・更新が必要ならその権限を確認し、検証のたびに `npx latest` を取得しない。
7
+ 利用中のskillとCLIの版を確認し、0.47.0のskillには同じ版のnpm CLIを導入する(`npm install -g @shinaps/skills@0.47.0`)。pluginだけにはCLIは含まれない。導入・更新が必要ならその権限を確認し、検証のたびに `npx latest` を取得しない。
8
8
 
9
9
  0.35.0から通常設定の `review_flow.mode` に `ask` を受理する。`config_version` は2のままで、既存のauto・manualの設定は変更不要。0.33.0〜0.34.xのCLIと `$schema` のURLは `ask` を拒否するため、`ask` を使う設定では `$schema` も0.35.0以降のURLにする。
10
10
 
@@ -28,7 +28,7 @@ Shinaps AIの規約は、機械検査(`checks`)を持てる。検査は配
28
28
 
29
29
  [Shinaps規約の書き方](rule-writing.md)で書き込む規約に、検査を付けられるかを判断する。
30
30
 
31
- - **使えるルール**: ESLint core、`@typescript-eslint/*`(型情報を使うものを含む)、`vue/*`、同梱の `shinaps/*`(`docs/lint.md` の一覧)。版によって違うので、同じ版のCLIで確かめる。使えるルールが無い規約には検査を付けない(AI照合のまま)。同梱ルールの追加は `docs/lint.md` の手順で別の作業として提案する。
32
- - **coverageの判断**: 規約の全文(scope・labelsを含み、更新では更新後の全文)と、検査の `rule`・`options`・`files` を照らす。`files` の範囲で、規約が求めることへの違反をこのルールが全て報告すると言えるときだけ `full`、見逃しが一つでもありうれば `partial`。lintが規約より広く報告する(例外も報告する)ことは `full` の妨げにならない(指摘はメインが確認する)。例で通ることは根拠にならない。
31
+ - **使えるルール**: ESLint core、`@typescript-eslint/*`(型情報を使うものを含む)、`vue/*`、`react-x/*` のうち `rules-of-hooks`・`exhaustive-deps`・`no-array-index-key`・`no-missing-key`・`no-nested-component-definitions`・`no-unstable-context-value`、`regexp/*`、同梱の `shinaps/*`(`docs/lint.md` の一覧)。版によって違うので、同じ版のCLIで確かめる。使えるルールが無い規約には検査を付けない(AI照合のまま)。同梱ルールの追加は `docs/lint.md` の手順で別の作業として提案する。
32
+ - **coverageの判断**: 規約の全文(scope・labelsを含み、更新では更新後の全文)と、検査の `rule`・`options`・`files` を照らす。`files` の範囲で、規約が求めることへの違反をこのルールが全て報告すると言えるときだけ `full`、見逃しが一つでもありうれば `partial`。lintが規約より広く報告する(例外も報告する)ことは `full` の妨げにならない(指摘はメインが確認する)。例で通ることは根拠にならない。Vueのテンプレートを見るルール(`vue/*` のテンプレート用、`shinaps/vue-no-index-key`)は、HTML以外のテンプレート(`lang="pug"` など)を解析せず報告なしで終わるので、それだけでは `.vue` を対象に `full` にできない。
33
33
  - **補助の確認**: 規約のgood・badの例を一時ディレクトリにファイルとして書き、同じ入口で実行して、badで報告され、goodで報告されないことを確かめる。対象プロジェクトのコードを写さない。
34
- - **書き込み**: `record_rule`・`update_rule` の `checks` に渡す。一括の `record_rules` は `checks` を受け取らない(付けると呼出し全体が入力エラーになる)ので、検査は登録後に `update_rule` で付ける。`update_rule` は配列ごと置換し、`[]` で外す。検査を持つ規約の内容(出典とrepoの表示名以外。適用先はscope、repo_ownerのowner、repoのrepoIdで比べる)を変える更新では、更新後の全文で検査を見直し、同じ要求で `checks` を渡す。渡さないと `CHECKS_REQUIRED` で保存されない。見直した結果が同じなら同じ配列を渡す。
34
+ - **書き込み**: `record_rule`・`update_rule` の `checks` に渡す。一括の `record_rules` は `checks` を受け取らない(付けると呼出し全体が入力エラーになる)ので、検査は登録後に `update_rule` で付ける。`update_rule` は配列ごと置換し、`[]` で外す。検査を持つ規約の内容(repoの表示名以外。適用先はscope、repo_ownerのowner、repoのrepoIdで比べる)を変える更新では、更新後の全文で検査を見直し、同じ要求で `checks` を渡す。渡さないと `CHECKS_REQUIRED` で保存されない。見直した結果が同じなら同じ配列を渡す。
@@ -20,7 +20,7 @@ Shinaps AIへ個人規約を登録・更新するときの書き方。短さそ
20
20
  1. **提示**: 同じ場面で既存の規約と両方には従えない、候補に従うと既存の規約の例外や強さが意味を持たなくなる、更新先を一つに決められない、または結果を判断できない。
21
21
  2. **書かない**: 同じ判断で範囲が候補を含む既存の規約があり、候補に加える情報が無い(言い換えは情報に数えない)。または、同じ判断で範囲が候補を含むのが公式規約だけである(補足があれば報告する)。
22
22
  3. **提示**: 取得が未完了である。「重複なし」とせず、未取得の範囲を示す。
23
- 4. **更新**: 同じ判断で範囲が候補を含む個人規約があり、候補の補足(理由・例・出典)が判断を変えず、その規約の範囲全体に当てはまる。判断・範囲・kindは変えない。
23
+ 4. **更新**: 同じ判断で範囲が候補を含む個人規約があり、候補の補足(理由・例)が判断を変えず、その規約の範囲全体に当てはまる。判断・範囲・kindは変えない。
24
24
  5. **提示**: 同じ判断の個人規約と範囲が重なるが候補を含まない、または補足がその規約の範囲の一部にしか当てはまらない。
25
25
  6. **新規**: それ以外。別の判断で既存の規約と両立するもの、公式規約より範囲が広い同じ判断を含む。
26
26
 
@@ -53,8 +53,8 @@ coding の規約は、使えるlintのルールで検査できるかを判断し
53
53
  ## 残すものと削るもの
54
54
 
55
55
  - 適用条件、例外、強制か推奨かの強さは必ず残す。短くするために意味を変えない。
56
- - 経緯、PR番号、発生日は、判断の根拠や適用範囲を理解するために必要な分だけ残す。詳細な出典は `sourceUrls` に置く。
57
- - 出典、scope、kind、labelsは、規約の内容が変わらない限り変えない。出典を足すときは既存の出典を残す。
56
+ - 経緯、PR番号、発生日は、判断の根拠や適用範囲を理解するために必要な分だけ本文に残す。判断に要る資料は本文で引用してよい(URLを含めてよい)。出典URLの一覧は保存せず、本文にも移さない。
57
+ - scope、kind、labelsは、規約の内容が変わらない限り変えない。
58
58
  - 読み手がリポジトリの既存の規約や公式の文書から分かることは繰り返さない。
59
59
  - 根拠の無いコード例・URL・規範を作らない。
60
60
 
@@ -80,16 +80,13 @@ Good/Bad サンプルコード (examples) の付け方:
80
80
  - good / bad の大きさは [Shinaps規約の書き方](../../references/rule-writing.md) の目安に従う。language は shiki の言語 id 小文字 (`typescript` / `tsx` / `python` / `go` 等)
81
81
  - good / bad / language は 3 つセットでしか登録できない (揃っていないと入力の schema 検証で拒否される)
82
82
 
83
- 出典 URL (sourceUrls) の付け方:
84
-
85
- - 根拠になったレビューコメントの HTML URL (`#discussion_r...` / `#issuecomment-...`) を優先し、特定できなければ PR URL にフォールバック。http(s) のみ。上限は MCP ツールの入力の説明に従う
86
- - **出典素材が無い rule に URL を捏造しない** (省略可 = 出典なしで保存される)
83
+ 出典 URL の一覧は保存しない (本文にも移さない)。判断の根拠や適用範囲の理解に要る経緯・PR 番号は、[Shinaps規約の書き方](../../references/rule-writing.md) に従って本文に必要な分だけ残す。
87
84
 
88
85
  投入手順:
89
86
 
90
- - 候補を確定してから、[Shinaps規約の書き方](../../references/rule-writing.md) の「書き込む前に既存の規約と比べる」で候補ごとに結果を決める。既存の規約への**更新**は下の差分確認へ進める。**提示** はブロックの終わりにまとめて利用者へ示し、残りの投入は止めない。**新規**候補だけを集めて `record_rules({ scope: 'repo', repoOwner, repoName, repoId, rules: [{ title, why, recommend?, avoid?, kind?, labels?, examples?, sourceUrls? }, ...] })` で **1 call bulk 投入** する。上限は MCP ツールの入力の説明に従う。`labels` は language / platform / framework / topic の slug 配列 (`list_search_facets` が返す公式カタログの slug のみ、language/platform/framework は 1 rule に各 1 つまで) (1 call 最大 100 件、超えたら分割。同一 title の重複は入力の schema 検証で拒否される)。
87
+ - 候補を確定してから、[Shinaps規約の書き方](../../references/rule-writing.md) の「書き込む前に既存の規約と比べる」で候補ごとに結果を決める。既存の規約への**更新**は下の差分確認へ進める。**提示** はブロックの終わりにまとめて利用者へ示し、残りの投入は止めない。**新規**候補だけを集めて `record_rules({ scope: 'repo', repoOwner, repoName, repoId, rules: [{ title, why, recommend?, avoid?, kind?, labels?, examples? }, ...] })` で **1 call bulk 投入** する。上限は MCP ツールの入力の説明に従う。`labels` は language / platform / framework / topic の slug 配列 (`list_search_facets` が返す公式カタログの slug のみ、language/platform/framework は 1 rule に各 1 つまで) (1 call 最大 100 件、超えたら分割。同一 title の重複は入力の schema 検証で拒否される)。
91
88
  - extract-rules は対象 repo の PR レビューから抽出する性質上 scope=repo (当該 repo 限定) がデフォルト。横断ルールとして残したい場合だけユーザー判断で `scope: 'user'` に格上げし、書き直した全文で比べ直す。**格上げするときは why / recommend / avoid / examples を当該 repo の固有文脈 (内部 API 名・モジュール構成・ドメイン固有の識別子) から切り離し、他プロジェクトでも適用場面を想定できる汎用的な表現・汎用サンプルに解釈し直してから登録する** (scope=repo のままなら repo 固有の具体的な記述・コード片で良い)
92
- - `RULE_TOO_LARGE` が返ったら、その呼出し分は全体として保存されていない。details の limit・actual・title を確かめ、該当候補の本文・例・出典を短くしてから同じ呼出しをやり直す。`update_rule` の `RULE_UPDATE_CONFLICT` は全文を読み直してから再試行する。
89
+ - `RULE_TOO_LARGE` が返ったら、その呼出し分は全体として保存されていない。details の limit・actual・title を確かめ、該当候補の本文・例を短くしてから同じ呼出しをやり直す。`update_rule` の `RULE_UPDATE_CONFLICT` は全文を読み直してから再試行する。
93
90
  - `RULE_LIMIT_REACHED` が返ったら投入を止める。個人ルールの保存数には上限があり、残りの枠が足りない `record_rules` はその呼出し分が全体として失敗し、一部も保存されない (件数を減らして一部だけ登録する手順へ自動では切り替えない)。それより前の呼出しで投入した分は保存されている。details の `limit` と `actual` から残りの枠を示し、投入する件数を絞るか既存ルールを整理するかのどちらにするかを利用者に確認する。以降のブロックの抽出・投入にも進まず、利用者の選択を待つ。
94
91
  - `RATE_LIMITED` (再試行可能) が返ったら、制限の時間枠が切り替わるまで待ってから、同じ呼出しを1回だけ再試行する。再び拒否されたら、連続して再試行せずに中断し、その状況を利用者に報告する。
95
92
  - 戻り値は入力の `rules` の位置と id だけ (`inserted: { index, ruleId }[]`、`skipped: { index, existingRuleId }[]`)。`skipped` は「既存と title 重複して投入されなかった候補」で、title は入力の `rules[index]` から分かる。上書きせず**提示**へ進める。
@@ -102,7 +99,7 @@ Good/Bad サンプルコード (examples) の付け方:
102
99
  > ```
103
100
  > 上書きしますか? (yes / no / skip-all)
104
101
 
105
- - 同意なら `update_rule({ id: <既存 rule の id>, why?, recommend?, avoid?, examples?, sourceUrls? })` を実行。sourceUrls は配列ごと置き換わるので、既存と新しい出典をまとめて渡す (上限を超えるなら切り詰めずに利用者へ確認する)。`skip-all` を選ばれたら以降の差分確認をスキップする
102
+ - 同意なら `update_rule({ id: <既存 rule の id>, why?, recommend?, avoid?, examples? })` を実行。`skip-all` を選ばれたら以降の差分確認をスキップする
106
103
 
107
104
  ## Step 8. 100 PR ブロック確認
108
105
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shinaps",
3
- "version": "0.45.0",
3
+ "version": "0.47.0",
4
4
  "description": "Shinaps AIのCodex向け開発ワークフロー",
5
5
  "skills": "./skills/"
6
6
  }
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## 検証CLIと契約版
6
6
 
7
- 利用中のskillとCLIの版を確認し、0.45.0のskillには同じ版のnpm CLIを導入する(`npm install -g @shinaps/skills@0.45.0`)。pluginだけにはCLIは含まれない。導入・更新が必要ならその権限を確認し、検証のたびに `npx latest` を取得しない。
7
+ 利用中のskillとCLIの版を確認し、0.47.0のskillには同じ版のnpm CLIを導入する(`npm install -g @shinaps/skills@0.47.0`)。pluginだけにはCLIは含まれない。導入・更新が必要ならその権限を確認し、検証のたびに `npx latest` を取得しない。
8
8
 
9
9
  0.35.0から通常設定の `review_flow.mode` に `ask` を受理する。`config_version` は2のままで、既存のauto・manualの設定は変更不要。0.33.0〜0.34.xのCLIと `$schema` のURLは `ask` を拒否するため、`ask` を使う設定では `$schema` も0.35.0以降のURLにする。
10
10
 
@@ -28,7 +28,7 @@ Shinaps AIの規約は、機械検査(`checks`)を持てる。検査は配
28
28
 
29
29
  [Shinaps規約の書き方](rule-writing.md)で書き込む規約に、検査を付けられるかを判断する。
30
30
 
31
- - **使えるルール**: ESLint core、`@typescript-eslint/*`(型情報を使うものを含む)、`vue/*`、同梱の `shinaps/*`(`docs/lint.md` の一覧)。版によって違うので、同じ版のCLIで確かめる。使えるルールが無い規約には検査を付けない(AI照合のまま)。同梱ルールの追加は `docs/lint.md` の手順で別の作業として提案する。
32
- - **coverageの判断**: 規約の全文(scope・labelsを含み、更新では更新後の全文)と、検査の `rule`・`options`・`files` を照らす。`files` の範囲で、規約が求めることへの違反をこのルールが全て報告すると言えるときだけ `full`、見逃しが一つでもありうれば `partial`。lintが規約より広く報告する(例外も報告する)ことは `full` の妨げにならない(指摘はメインが確認する)。例で通ることは根拠にならない。
31
+ - **使えるルール**: ESLint core、`@typescript-eslint/*`(型情報を使うものを含む)、`vue/*`、`react-x/*` のうち `rules-of-hooks`・`exhaustive-deps`・`no-array-index-key`・`no-missing-key`・`no-nested-component-definitions`・`no-unstable-context-value`、`regexp/*`、同梱の `shinaps/*`(`docs/lint.md` の一覧)。版によって違うので、同じ版のCLIで確かめる。使えるルールが無い規約には検査を付けない(AI照合のまま)。同梱ルールの追加は `docs/lint.md` の手順で別の作業として提案する。
32
+ - **coverageの判断**: 規約の全文(scope・labelsを含み、更新では更新後の全文)と、検査の `rule`・`options`・`files` を照らす。`files` の範囲で、規約が求めることへの違反をこのルールが全て報告すると言えるときだけ `full`、見逃しが一つでもありうれば `partial`。lintが規約より広く報告する(例外も報告する)ことは `full` の妨げにならない(指摘はメインが確認する)。例で通ることは根拠にならない。Vueのテンプレートを見るルール(`vue/*` のテンプレート用、`shinaps/vue-no-index-key`)は、HTML以外のテンプレート(`lang="pug"` など)を解析せず報告なしで終わるので、それだけでは `.vue` を対象に `full` にできない。
33
33
  - **補助の確認**: 規約のgood・badの例を一時ディレクトリにファイルとして書き、同じ入口で実行して、badで報告され、goodで報告されないことを確かめる。対象プロジェクトのコードを写さない。
34
- - **書き込み**: `record_rule`・`update_rule` の `checks` に渡す。一括の `record_rules` は `checks` を受け取らない(付けると呼出し全体が入力エラーになる)ので、検査は登録後に `update_rule` で付ける。`update_rule` は配列ごと置換し、`[]` で外す。検査を持つ規約の内容(出典とrepoの表示名以外。適用先はscope、repo_ownerのowner、repoのrepoIdで比べる)を変える更新では、更新後の全文で検査を見直し、同じ要求で `checks` を渡す。渡さないと `CHECKS_REQUIRED` で保存されない。見直した結果が同じなら同じ配列を渡す。
34
+ - **書き込み**: `record_rule`・`update_rule` の `checks` に渡す。一括の `record_rules` は `checks` を受け取らない(付けると呼出し全体が入力エラーになる)ので、検査は登録後に `update_rule` で付ける。`update_rule` は配列ごと置換し、`[]` で外す。検査を持つ規約の内容(repoの表示名以外。適用先はscope、repo_ownerのowner、repoのrepoIdで比べる)を変える更新では、更新後の全文で検査を見直し、同じ要求で `checks` を渡す。渡さないと `CHECKS_REQUIRED` で保存されない。見直した結果が同じなら同じ配列を渡す。
@@ -20,7 +20,7 @@ Shinaps AIへ個人規約を登録・更新するときの書き方。短さそ
20
20
  1. **提示**: 同じ場面で既存の規約と両方には従えない、候補に従うと既存の規約の例外や強さが意味を持たなくなる、更新先を一つに決められない、または結果を判断できない。
21
21
  2. **書かない**: 同じ判断で範囲が候補を含む既存の規約があり、候補に加える情報が無い(言い換えは情報に数えない)。または、同じ判断で範囲が候補を含むのが公式規約だけである(補足があれば報告する)。
22
22
  3. **提示**: 取得が未完了である。「重複なし」とせず、未取得の範囲を示す。
23
- 4. **更新**: 同じ判断で範囲が候補を含む個人規約があり、候補の補足(理由・例・出典)が判断を変えず、その規約の範囲全体に当てはまる。判断・範囲・kindは変えない。
23
+ 4. **更新**: 同じ判断で範囲が候補を含む個人規約があり、候補の補足(理由・例)が判断を変えず、その規約の範囲全体に当てはまる。判断・範囲・kindは変えない。
24
24
  5. **提示**: 同じ判断の個人規約と範囲が重なるが候補を含まない、または補足がその規約の範囲の一部にしか当てはまらない。
25
25
  6. **新規**: それ以外。別の判断で既存の規約と両立するもの、公式規約より範囲が広い同じ判断を含む。
26
26
 
@@ -53,8 +53,8 @@ coding の規約は、使えるlintのルールで検査できるかを判断し
53
53
  ## 残すものと削るもの
54
54
 
55
55
  - 適用条件、例外、強制か推奨かの強さは必ず残す。短くするために意味を変えない。
56
- - 経緯、PR番号、発生日は、判断の根拠や適用範囲を理解するために必要な分だけ残す。詳細な出典は `sourceUrls` に置く。
57
- - 出典、scope、kind、labelsは、規約の内容が変わらない限り変えない。出典を足すときは既存の出典を残す。
56
+ - 経緯、PR番号、発生日は、判断の根拠や適用範囲を理解するために必要な分だけ本文に残す。判断に要る資料は本文で引用してよい(URLを含めてよい)。出典URLの一覧は保存せず、本文にも移さない。
57
+ - scope、kind、labelsは、規約の内容が変わらない限り変えない。
58
58
  - 読み手がリポジトリの既存の規約や公式の文書から分かることは繰り返さない。
59
59
  - 根拠の無いコード例・URL・規範を作らない。
60
60
 
@@ -9,7 +9,7 @@ description: GitHubの過去PRレビューから繰り返し適用できる規
9
9
 
10
10
  1. `gh`で期間内のマージ済みPRを取得する。ページングし、並び順と日付フィルターの関係を守る。更新日時順の一覧で古いマージ日時を一件見つけても、それ以降の取得を打ち切らない。
11
11
  2. PRのreview本文・inline comment・conversation commentを取得する。PR descriptionはレビュー指摘として扱わない。APIのBot種別は除外し、判断が必要な投稿者は確認する。認証情報やリポジトリ全体をサービスへ送信しない。
12
- 3. 複数のレビューで繰り返され、適用条件とWHYが説明できる規約を候補にする。根拠のない例・URLを作らず、レビューコメントの出典を付ける。
12
+ 3. 複数のレビューで繰り返され、適用条件とWHYが説明できる規約を候補にする。根拠のない例・URLを作らない。出典URLの一覧は保存しない(本文にも移さない)。
13
13
  4. 候補を[Shinaps規約の書き方](../../references/rule-writing.md)に従って書き、同じ文書の「書き込む前に既存の規約と比べる」で候補ごとに結果を決める。提示の候補はまとまりの終わりに示し、残りの投入は止めない。新規の候補だけを対象repoのスコープへ、実際のMCPツールのスキーマに従って登録する。対象repoは[Shinaps規約の取得](../../references/rules.md)の「リポジトリを特定する」でrepositoryの`id`を得て指定し、得られなければrepoのスコープでは登録せず利用者に確認する。応答は入力の位置とidだけなので、重複して投入されなかった候補は入力からtitleを得て、上書きせず提示へ進める。全プロジェクト共通へ広げる場合は利用者の判断を確認し、書き直した全文で比べ直す。既存の規約への更新の候補は差分を提示して許可を得る。`RULE_TOO_LARGE`はその呼出し分が全体として保存されなかったことを示すので、details の limit・actual・titleを確かめ、該当候補を短くしてやり直す。更新の`RULE_UPDATE_CONFLICT`は全文を読み直して再試行する。`RULE_LIMIT_REACHED`は残りの枠が足りずその呼出し分が全体として保存されなかったことを示すので、一部だけを登録する手順へ切り替えずに止め、details の limit・actualを示して、件数を絞るか既存ルールを整理するかを利用者に確認する。それより前の呼出しで投入した分は保存されている。以降のまとまりの抽出・投入にも進まず、利用者の選択を待つ。
14
14
  5. 大量処理は100 PR程度のまとまりで結果を報告し、継続範囲を確認する。結果が不明な保存失敗では再投入の前に読み戻し、重複を避ける。`RATE_LIMITED`は制限の時間枠が切り替わるまで待ってから1回だけ再試行し、続けて拒否されたら中断して報告する。
15
15