264 lines
7.8 KiB
Bash
Executable file
264 lines
7.8 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
# Shared AI ignore / permission defaults for init and sync flows.
|
|
AGENT_OPS_TASK_ARCHIVE_IGNORE_PATTERN="agent-task/archive/**"
|
|
AGENT_ROADMAP_ARCHIVE_IGNORE_PATTERN="agent-roadmap/archive/**"
|
|
AGENT_OPS_AI_IGNORE_BLOCK_BEGIN="# BEGIN Agent-Ops managed ignore"
|
|
AGENT_OPS_AI_IGNORE_BLOCK_END="# END Agent-Ops managed ignore"
|
|
AGENT_OPS_GITIGNORE_BLOCK_BEGIN="# BEGIN Agent-Ops managed gitignore"
|
|
AGENT_OPS_GITIGNORE_BLOCK_END="# END Agent-Ops managed gitignore"
|
|
AGENT_OPS_AI_IGNORE_FILES=(".geminiignore" ".aiexclude" ".cursorignore" ".clineignore")
|
|
AGENT_OPS_AI_PERMISSION_FILES=(".claude/settings.json" "opencode.json")
|
|
AGENT_OPS_AI_SYNC_FILES=(".gitignore" "${AGENT_OPS_AI_IGNORE_FILES[@]}" "${AGENT_OPS_AI_PERMISSION_FILES[@]}")
|
|
|
|
agent_ops_ensure_gitignore_task_artifact_block() {
|
|
local file="$1"
|
|
local tmp
|
|
|
|
touch "$file"
|
|
if grep -qxF "$AGENT_OPS_GITIGNORE_BLOCK_BEGIN" "$file" \
|
|
&& grep -qxF "$AGENT_OPS_GITIGNORE_BLOCK_END" "$file"; then
|
|
tmp="$(mktemp "$file.tmp.XXXXXX")"
|
|
awk \
|
|
-v begin="$AGENT_OPS_GITIGNORE_BLOCK_BEGIN" \
|
|
-v end="$AGENT_OPS_GITIGNORE_BLOCK_END" '
|
|
$0 == begin {
|
|
print begin
|
|
print "!agent-task/"
|
|
print "!agent-task/**/"
|
|
print "!agent-task/**/*.md"
|
|
print "!agent-task/**/*.log"
|
|
print end
|
|
in_block = 1
|
|
next
|
|
}
|
|
$0 == end && in_block {
|
|
in_block = 0
|
|
next
|
|
}
|
|
!in_block { print }
|
|
' "$file" > "$tmp"
|
|
mv "$tmp" "$file"
|
|
else
|
|
if [[ -s "$file" ]]; then
|
|
printf "\n" >> "$file"
|
|
fi
|
|
printf "%s\n" "$AGENT_OPS_GITIGNORE_BLOCK_BEGIN" >> "$file"
|
|
printf "%s\n" "!agent-task/" >> "$file"
|
|
printf "%s\n" "!agent-task/**/" >> "$file"
|
|
printf "%s\n" "!agent-task/**/*.md" >> "$file"
|
|
printf "%s\n" "!agent-task/**/*.log" >> "$file"
|
|
printf "%s\n" "$AGENT_OPS_GITIGNORE_BLOCK_END" >> "$file"
|
|
fi
|
|
}
|
|
|
|
agent_ops_ensure_ai_ignore_block() {
|
|
local file="$1"
|
|
local tmp
|
|
|
|
touch "$file"
|
|
if grep -qxF "$AGENT_OPS_AI_IGNORE_BLOCK_BEGIN" "$file" \
|
|
&& grep -qxF "$AGENT_OPS_AI_IGNORE_BLOCK_END" "$file"; then
|
|
tmp="$(mktemp "$file.tmp.XXXXXX")"
|
|
awk \
|
|
-v begin="$AGENT_OPS_AI_IGNORE_BLOCK_BEGIN" \
|
|
-v end="$AGENT_OPS_AI_IGNORE_BLOCK_END" \
|
|
-v task="$AGENT_OPS_TASK_ARCHIVE_IGNORE_PATTERN" \
|
|
-v roadmap="$AGENT_ROADMAP_ARCHIVE_IGNORE_PATTERN" '
|
|
$0 == begin {
|
|
print begin
|
|
print task
|
|
print roadmap
|
|
print end
|
|
in_block = 1
|
|
next
|
|
}
|
|
$0 == end && in_block {
|
|
in_block = 0
|
|
next
|
|
}
|
|
!in_block { print }
|
|
' "$file" > "$tmp"
|
|
mv "$tmp" "$file"
|
|
else
|
|
if [[ -s "$file" ]]; then
|
|
printf "\n" >> "$file"
|
|
fi
|
|
printf "%s\n" "$AGENT_OPS_AI_IGNORE_BLOCK_BEGIN" >> "$file"
|
|
printf "%s\n" "$AGENT_OPS_TASK_ARCHIVE_IGNORE_PATTERN" >> "$file"
|
|
printf "%s\n" "$AGENT_ROADMAP_ARCHIVE_IGNORE_PATTERN" >> "$file"
|
|
printf "%s\n" "$AGENT_OPS_AI_IGNORE_BLOCK_END" >> "$file"
|
|
fi
|
|
}
|
|
|
|
agent_ops_merge_json_with_jq() {
|
|
local file="$1"
|
|
local filter="$2"
|
|
local fallback_note="$3"
|
|
local tmp
|
|
|
|
if ! command -v jq >/dev/null 2>&1; then
|
|
echo "$fallback_note"
|
|
return
|
|
fi
|
|
|
|
tmp="$(mktemp "$file.tmp.XXXXXX")"
|
|
if jq "$filter" "$file" > "$tmp"; then
|
|
mv "$tmp" "$file"
|
|
else
|
|
rm -f "$tmp"
|
|
echo "$fallback_note"
|
|
fi
|
|
}
|
|
|
|
agent_ops_merge_claude_settings() {
|
|
local file="$1"
|
|
local filter='
|
|
def append_unique($item):
|
|
if index($item) then . else . + [$item] end;
|
|
def as_array:
|
|
if type == "array" then . elif . == null then [] else [.] end;
|
|
def as_object:
|
|
if type == "object" then . else {} end;
|
|
|
|
.permissions = ((.permissions // {}) | as_object)
|
|
| .permissions.deny = (
|
|
(.permissions.deny | as_array)
|
|
| map(select(. != "Read(./agent-roadmap/archive/**)"))
|
|
| append_unique("Read(./agent-task/archive/**)")
|
|
)
|
|
'
|
|
|
|
agent_ops_merge_json_with_jq \
|
|
"$file" \
|
|
"$filter" \
|
|
"Note: .claude/settings.json exists; add Read(./agent-task/archive/**) and remove Read(./agent-roadmap/archive/**) manually."
|
|
}
|
|
|
|
agent_ops_claude_settings_complete() {
|
|
local file="$1"
|
|
local filter='
|
|
def as_array:
|
|
if type == "array" then . elif . == null then [] else [.] end;
|
|
|
|
(.permissions.deny | as_array)
|
|
as $deny
|
|
| (($deny | index("Read(./agent-task/archive/**)")) != null)
|
|
and (($deny | index("Read(./agent-roadmap/archive/**)")) == null)
|
|
'
|
|
|
|
if command -v jq >/dev/null 2>&1; then
|
|
jq -e "$filter" "$file" >/dev/null 2>&1
|
|
else
|
|
grep -q "agent-task/archive" "$file"
|
|
fi
|
|
}
|
|
|
|
agent_ops_merge_opencode_config() {
|
|
local file="$1"
|
|
local filter='
|
|
def append_unique($item):
|
|
if index($item) then . else . + [$item] end;
|
|
def as_array:
|
|
if type == "array" then . elif . == null then [] else [.] end;
|
|
def as_object:
|
|
if type == "object" then . else {} end;
|
|
|
|
.permission = ((.permission // {}) | as_object)
|
|
| .permission.read = ((.permission.read // {}) | as_object)
|
|
| .permission.read["agent-task/archive/**"] = "deny"
|
|
| del(.permission.read["agent-roadmap/archive/**"])
|
|
| .permission.glob = ((.permission.glob // {}) | as_object)
|
|
| .permission.glob["agent-task/archive/**"] = "deny"
|
|
| del(.permission.glob["agent-roadmap/archive/**"])
|
|
| .watcher = ((.watcher // {}) | as_object)
|
|
| .watcher.ignore = (
|
|
(.watcher.ignore | as_array)
|
|
| append_unique("agent-task/archive/**")
|
|
| append_unique("agent-roadmap/archive/**")
|
|
)
|
|
'
|
|
|
|
agent_ops_merge_json_with_jq \
|
|
"$file" \
|
|
"$filter" \
|
|
"Note: opencode.json exists; add agent-task/archive/** read/glob deny, remove agent-roadmap/archive/** read/glob hard deny, and add agent-task/archive/** plus agent-roadmap/archive/** watcher ignore manually."
|
|
}
|
|
|
|
agent_ops_opencode_config_complete() {
|
|
local file="$1"
|
|
local filter='
|
|
def as_array:
|
|
if type == "array" then . elif . == null then [] else [.] end;
|
|
|
|
(.permission.read["agent-task/archive/**"] == "deny")
|
|
and (.permission.glob["agent-task/archive/**"] == "deny")
|
|
and (.permission.read["agent-roadmap/archive/**"] != "deny")
|
|
and (.permission.glob["agent-roadmap/archive/**"] != "deny")
|
|
and ((.watcher.ignore | as_array) as $ignore | (($ignore | index("agent-task/archive/**")) != null) and (($ignore | index("agent-roadmap/archive/**")) != null))
|
|
'
|
|
|
|
if command -v jq >/dev/null 2>&1; then
|
|
jq -e "$filter" "$file" >/dev/null 2>&1
|
|
else
|
|
grep -q "agent-task/archive" "$file" && grep -q "agent-roadmap/archive" "$file"
|
|
fi
|
|
}
|
|
|
|
ensure_agent_ops_ai_ignore_config() {
|
|
local target_dir="$1"
|
|
local ignore_file
|
|
|
|
if [[ -f "$target_dir/.agent-ops-source" ]]; then
|
|
echo " AI ignore 보강 건너뜀: .agent-ops-source repo"
|
|
return
|
|
fi
|
|
|
|
agent_ops_ensure_gitignore_task_artifact_block "$target_dir/.gitignore"
|
|
|
|
for ignore_file in "${AGENT_OPS_AI_IGNORE_FILES[@]}"; do
|
|
agent_ops_ensure_ai_ignore_block "$target_dir/$ignore_file"
|
|
done
|
|
|
|
mkdir -p "$target_dir/.claude"
|
|
if [[ ! -f "$target_dir/.claude/settings.json" ]]; then
|
|
cat > "$target_dir/.claude/settings.json" <<'EOF'
|
|
{
|
|
"$schema": "https://json.schemastore.org/claude-code-settings.json",
|
|
"permissions": {
|
|
"deny": [
|
|
"Read(./agent-task/archive/**)"
|
|
]
|
|
}
|
|
}
|
|
EOF
|
|
elif ! agent_ops_claude_settings_complete "$target_dir/.claude/settings.json"; then
|
|
agent_ops_merge_claude_settings "$target_dir/.claude/settings.json"
|
|
fi
|
|
|
|
if [[ ! -f "$target_dir/opencode.json" ]]; then
|
|
cat > "$target_dir/opencode.json" <<'EOF'
|
|
{
|
|
"$schema": "https://opencode.ai/config.json",
|
|
"permission": {
|
|
"read": {
|
|
"agent-task/archive/**": "deny"
|
|
},
|
|
"glob": {
|
|
"agent-task/archive/**": "deny"
|
|
}
|
|
},
|
|
"watcher": {
|
|
"ignore": [
|
|
"agent-task/archive/**",
|
|
"agent-roadmap/archive/**"
|
|
]
|
|
}
|
|
}
|
|
EOF
|
|
elif ! agent_ops_opencode_config_complete "$target_dir/opencode.json"; then
|
|
agent_ops_merge_opencode_config "$target_dir/opencode.json"
|
|
fi
|
|
|
|
echo " AI permission 표준 적용: roadmap archive hard deny 제거"
|
|
}
|