Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .agent_harness/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# .agent_harness

## English

This package contains the shared command-guard core used by the Codex and Claude hooks.
The goal is to keep shell search restrictions and `cdidx.dll` block rules in one place.

## 日本語

このパッケージには、Codex と Claude のフックで使う共通コマンドガードの本体を置きます。
シェル検索制限と `cdidx.dll` のブロック規則を 1 か所にまとめるのが目的です。
5 changes: 5 additions & 0 deletions .agent_harness/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""Shared agent harness helpers."""

from .command_guard_core import CommandGuardDecision, guard_command_text, guard_argv

__all__ = ["CommandGuardDecision", "guard_command_text", "guard_argv"]
63 changes: 63 additions & 0 deletions .agent_harness/command_guard_core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from __future__ import annotations

from dataclasses import dataclass
from shlex import split as shlex_split
from typing import Sequence


DISALLOWED_SEARCH_COMMANDS = (
"grep",
"rg",
"find",
"fd",
"locate",
"git grep",
"ls -R",
"Get-ChildItem -Recurse",
"Select-String",
)

DISALLOWED_CDEXECUTABLES = (
"dotnet ./src/CodeIndex/bin/Debug/net8.0/cdidx.dll",
"dotnet path/to/cdidx.dll",
)


@dataclass(frozen=True)
class CommandGuardDecision:
allowed: bool
reason: str = ""


def guard_command_text(command_text: str) -> CommandGuardDecision:
normalized = " ".join(command_text.strip().split())
if not normalized:
return CommandGuardDecision(False, "empty command")

for blocked in DISALLOWED_CDEXECUTABLES:
if normalized.startswith(blocked):
return CommandGuardDecision(False, "repository-local cdidx.dll execution is blocked")

if normalized.startswith("dotnet ") and "cdidx.dll" in normalized:
return CommandGuardDecision(False, "repository-local cdidx.dll execution is blocked")

if _contains_blocked_search(normalized):
return CommandGuardDecision(False, "shell search and discovery commands are blocked")

return CommandGuardDecision(True)


def guard_argv(argv: Sequence[str]) -> CommandGuardDecision:
if not argv:
return CommandGuardDecision(False, "empty argv")

command_text = " ".join(argv)
return guard_command_text(command_text)


def parse_command_line(command_line: str) -> CommandGuardDecision:
return guard_argv(shlex_split(command_line))


def _contains_blocked_search(command_text: str) -> bool:
return any(blocked in command_text for blocked in DISALLOWED_SEARCH_COMMANDS)
34 changes: 34 additions & 0 deletions .agent_harness/tests/test_command_guard_core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import sys
import unittest
from pathlib import Path


ROOT = Path(__file__).resolve().parents[2]
HARNES_DIR = ROOT / ".agent_harness"
if str(HARNES_DIR) not in sys.path:
sys.path.insert(0, str(HARNES_DIR))

from command_guard_core import guard_argv, guard_command_text


class CommandGuardCoreTests(unittest.TestCase):
def test_guard_command_text_allows_cdidx(self) -> None:
decision = guard_command_text("cdidx search foo")
self.assertTrue(decision.allowed)

def test_guard_command_text_blocks_shell_search(self) -> None:
decision = guard_command_text("grep foo README.md")
self.assertFalse(decision.allowed)
self.assertIn("blocked", decision.reason)

def test_guard_command_text_blocks_repo_local_cdidx(self) -> None:
decision = guard_command_text("dotnet ./src/CodeIndex/bin/Debug/net8.0/cdidx.dll search foo")
self.assertFalse(decision.allowed)

def test_guard_argv_blocks_ls_r(self) -> None:
decision = guard_argv(["ls", "-R"])
self.assertFalse(decision.allowed)


if __name__ == "__main__":
unittest.main()
26 changes: 26 additions & 0 deletions .claude/hooks/bash-guard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env python3
from __future__ import annotations

import sys
from pathlib import Path


ROOT = Path(__file__).resolve().parents[2]
HARNES_DIR = ROOT / ".agent_harness"
if str(HARNES_DIR) not in sys.path:
sys.path.insert(0, str(HARNES_DIR))

from command_guard_core import guard_command_text


def main() -> int:
command_text = " ".join(sys.argv[1:]).strip()
decision = guard_command_text(command_text)
if decision.allowed:
return 0
sys.stderr.write(decision.reason + "\n")
return 1


if __name__ == "__main__":
raise SystemExit(main())
2 changes: 1 addition & 1 deletion .codex/config.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# Repository-local Codex config
project_doc_fallback_filenames = ["CLAUDE.md"]
project_doc_fallback_filenames = ["AGENT_GUIDE.md", "CLAUDE.md"]
26 changes: 26 additions & 0 deletions .codex/hooks/bash_guard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env python3
from __future__ import annotations

import sys
from pathlib import Path


ROOT = Path(__file__).resolve().parents[2]
HARNES_DIR = ROOT / ".agent_harness"
if str(HARNES_DIR) not in sys.path:
sys.path.insert(0, str(HARNES_DIR))

from command_guard_core import guard_command_text


def main() -> int:
command_text = " ".join(sys.argv[1:]).strip()
decision = guard_command_text(command_text)
if decision.allowed:
return 0
sys.stderr.write(decision.reason + "\n")
return 1


if __name__ == "__main__":
raise SystemExit(main())
26 changes: 26 additions & 0 deletions .codex/hooks/permission_request_guard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env python3
from __future__ import annotations

import sys
from pathlib import Path


ROOT = Path(__file__).resolve().parents[2]
HARNES_DIR = ROOT / ".agent_harness"
if str(HARNES_DIR) not in sys.path:
sys.path.insert(0, str(HARNES_DIR))

from command_guard_core import guard_command_text


def main() -> int:
command_text = " ".join(sys.argv[1:]).strip()
decision = guard_command_text(command_text)
if decision.allowed:
return 0
sys.stderr.write(decision.reason + "\n")
return 1


if __name__ == "__main__":
raise SystemExit(main())
21 changes: 21 additions & 0 deletions .codex/workflows/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# .codex/workflows/README.md

## English

Shared agent rules live in `AGENT_GUIDE.md`.
Task procedures live in `.codex/workflows/`.
`AGENTS.md` is the thin Codex entry point and `CLAUDE.md` is the thin Claude entry point.
Do not duplicate the full guide in those entry files.

When README visuals would help, ask the maintainer for the exact PNG or GIF during the task.
Do not create a screenshot guide document.

## 日本語

共通ルールは `AGENT_GUIDE.md` に置きます。
タスク固有の手順は `.codex/workflows/` に置きます。
`AGENTS.md` は Codex 用の薄い入口、`CLAUDE.md` は Claude 用の薄い入口です。
入口ファイルに長い指示を重複させないでください。

README の画像が必要な場合は、作業中にメンテナーへ PNG / GIF を依頼してください。
スクリーンショット用のガイド文書は作らないでください。
15 changes: 15 additions & 0 deletions .codex/workflows/adversarial-review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# adversarial-review.md

## English

Review `origin/main..HEAD` for blocking or actionable issues.
Focus on correctness, security, regressions, broken docs, broken samples, release risks, inconsistent bilingual updates, and broken image links.
Avoid nitpicks.
Use `cdidx` for code lookup.

## 日本語

`origin/main..HEAD` を見て、ブロック要因や実行可能な問題を洗い出す。
正しさ、セキュリティ、回帰、壊れたドキュメント、壊れたサンプル、リリースリスク、英日不整合、壊れた画像リンクを重視する。
細かい指摘は避ける。
コード参照には `cdidx` を使う。
17 changes: 17 additions & 0 deletions .codex/workflows/docs-update.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# docs-update.md

## English

1. Keep English and Japanese sections together.
2. Do not mix the languages on one long line with ` / ` separators.
3. Update README, developer docs, testing docs, troubleshooting docs, samples, and API docs when affected.
4. Do not add broken screenshot or GIF links.
5. If README visuals are needed, ask the maintainer for the exact PNG or GIF using the hands-on protocol in `AGENT_GUIDE.md`.

## 日本語

1. 英語版と日本語版をそろえて更新する。
2. ` / ` で 1 行に英日を混在させない。
3. 影響がある場合は README、開発者向け文書、テスト文書、トラブルシューティング、サンプル、API ドキュメントを更新する。
4. 壊れたスクリーンショットや GIF のリンクは追加しない。
5. README の画像が必要な場合は、`AGENT_GUIDE.md` の手順に従ってメンテナーへ正確な PNG / GIF を依頼する。
23 changes: 23 additions & 0 deletions .codex/workflows/issue-fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# issue-fix.md

## English

1. Read `AGENT_GUIDE.md`.
2. Refresh `cdidx`.
3. Understand the issue scope.
4. Search with global `cdidx` only.
5. Make the smallest correct change.
6. Update tests, docs, and changelog when behavior changes.
7. Run focused tests, then Release configuration tests when feasible.
8. Do not create tags or publish packages.

## 日本語

1. `AGENT_GUIDE.md` を読む。
2. `cdidx` を更新する。
3. 問題の範囲を把握する。
4. グローバル `cdidx` だけで検索する。
5. 最小限で正しい変更を入れる。
6. 挙動が変わるならテスト、ドキュメント、CHANGELOG を更新する。
7. まず絞り込んだテストを実行し、可能なら Release 構成のテストも走らせる。
8. タグ作成やパッケージ公開はしない。
21 changes: 21 additions & 0 deletions .codex/workflows/pr-finalize.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# pr-finalize.md

## English

1. Summarize changed files.
2. Summarize validation commands and results.
3. Mention skipped validation honestly.
4. Include a mapping back to the six OSS review fixes.
5. If screenshots or GIFs were not provided, state exactly which asset files are still needed and include the capture instructions in the final summary, not as a repository guide file.
6. Bound CI watching; do not loop indefinitely.
7. Do not merge PRs, create tags, or publish packages unless explicitly requested.

## 日本語

1. 変更したファイルを要約する。
2. 実行した検証コマンドと結果を要約する。
3. 実行できなかった検証は正直に書く。
4. 6 つの OSS 修正項目に対応づけて説明する。
5. スクリーンショットや GIF が未提供なら、必要なファイル名を明示し、撮影手順はリポジトリ文書ではなく最終要約に書く。
6. CI の待機は必要最小限にし、無限ループしない。
7. 明示的な依頼がない限り、PR のマージ、タグ作成、パッケージ公開はしない。
21 changes: 21 additions & 0 deletions .codex/workflows/precommit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# precommit.md

## English

1. Check `git status --short`.
2. Use `cdidx` for final searches.
3. Run the relevant tests.
4. Run `dotnet test FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj --configuration Release --nologo` when possible.
5. Verify docs, changelog, and sample updates.
6. Do not use `git add .` or `git add -A`; add explicit files only.
7. Do not commit secrets.

## 日本語

1. `git status --short` を確認する。
2. 最終検索は `cdidx` を使う。
3. 関連するテストを実行する。
4. 可能なら `dotnet test FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj --configuration Release --nologo` を走らせる。
5. ドキュメント、CHANGELOG、サンプル更新を確認する。
6. `git add .` や `git add -A` は使わず、明示的にファイルを追加する。
7. シークレットをコミットしない。
49 changes: 49 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Bug report / バグ報告
description: Report a reproducible problem with nildiff / nildiff の再現可能な不具合を報告する
labels: [bug]
body:
- type: markdown
attributes:
value: |
Please avoid private paths, customer data, proprietary binaries, tokens, and exploit details in public issues.
公開 issue には private なパス、顧客データ、プロプライエタリなバイナリ、トークン、攻撃詳細を書かないでください。
- type: input
id: summary
attributes:
label: Summary / 要約
placeholder: Short, specific description / 短く具体的に
validations:
required: true
- type: textarea
id: repro
attributes:
label: Reproduction steps / 再現手順
placeholder: Exact `nildiff` command, sanitized input paths, and steps / 実行コマンド、匿名化した入力パス、手順
validations:
required: true
- type: input
id: version
attributes:
label: Version / バージョン
placeholder: `nildiff --version` output / `nildiff --version` の出力
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected / 期待値
validations:
required: true
- type: textarea
id: actual
attributes:
label: Actual / 実際
validations:
required: true
- type: checkboxes
id: privacy
attributes:
label: Privacy check / プライバシー確認
options:
- label: I have removed private paths, customer data, proprietary binaries, tokens, and exploit details. / private なパス、顧客データ、プロプライエタリなバイナリ、トークン、攻撃詳細を削除しました。
required: true
Loading
Loading