@shinaps/skills 0.45.0 → 0.46.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.46.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.46.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.46.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.46.0のskillには同じ版のnpm CLIを導入する(`npm install -g @shinaps/skills@0.46.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
34
  - **書き込み**: `record_rule`・`update_rule` の `checks` に渡す。一括の `record_rules` は `checks` を受け取らない(付けると呼出し全体が入力エラーになる)ので、検査は登録後に `update_rule` で付ける。`update_rule` は配列ごと置換し、`[]` で外す。検査を持つ規約の内容(出典とrepoの表示名以外。適用先はscope、repo_ownerのowner、repoのrepoIdで比べる)を変える更新では、更新後の全文で検査を見直し、同じ要求で `checks` を渡す。渡さないと `CHECKS_REQUIRED` で保存されない。見直した結果が同じなら同じ配列を渡す。
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shinaps",
3
- "version": "0.45.0",
3
+ "version": "0.46.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.46.0のskillには同じ版のnpm CLIを導入する(`npm install -g @shinaps/skills@0.46.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
34
  - **書き込み**: `record_rule`・`update_rule` の `checks` に渡す。一括の `record_rules` は `checks` を受け取らない(付けると呼出し全体が入力エラーになる)ので、検査は登録後に `update_rule` で付ける。`update_rule` は配列ごと置換し、`[]` で外す。検査を持つ規約の内容(出典とrepoの表示名以外。適用先はscope、repo_ownerのowner、repoのrepoIdで比べる)を変える更新では、更新後の全文で検査を見直し、同じ要求で `checks` を渡す。渡さないと `CHECKS_REQUIRED` で保存されない。見直した結果が同じなら同じ配列を渡す。