From 0dbccee979c7998539d91bf6e7d76aced8889c2a Mon Sep 17 00:00:00 2001 From: Adnan Zahir Date: Sat, 29 Aug 2026 20:04:47 +0700 Subject: [PATCH] Activate Taiga tracking only for infra ops work --- .../.claude-plugin/plugin.json | 4 +- .../taiga-auto-sync/.codex-plugin/plugin.json | 10 ++-- .../hooks/claude-codex-hooks.json | 7 ++- .../taiga-auto-sync/hooks/taiga-reminder.sh | 8 --- .../hooks/taiga-write-guard.py | 58 +++++++++++++++++++ .../skills/taiga-operations/SKILL.md | 15 +++++ 6 files changed, 85 insertions(+), 17 deletions(-) delete mode 100755 plugins/taiga-auto-sync/hooks/taiga-reminder.sh create mode 100644 plugins/taiga-auto-sync/hooks/taiga-write-guard.py create mode 100644 plugins/taiga-auto-sync/skills/taiga-operations/SKILL.md diff --git a/plugins/taiga-auto-sync/.claude-plugin/plugin.json b/plugins/taiga-auto-sync/.claude-plugin/plugin.json index ed17ebd..a333612 100644 --- a/plugins/taiga-auto-sync/.claude-plugin/plugin.json +++ b/plugins/taiga-auto-sync/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "taiga-auto-sync", - "version": "0.1.0", - "description": "Injects IT Infra & Ops Taiga tracking rules on every Claude prompt.", + "version": "0.1.0+codex.20260829130430", + "description": "Automatically tracks material IT Infra & Ops work and guards Taiga writes.", "author": { "name": "Senkensha" }, "hooks": "./hooks/claude-codex-hooks.json" } diff --git a/plugins/taiga-auto-sync/.codex-plugin/plugin.json b/plugins/taiga-auto-sync/.codex-plugin/plugin.json index 71b4af7..2d91421 100644 --- a/plugins/taiga-auto-sync/.codex-plugin/plugin.json +++ b/plugins/taiga-auto-sync/.codex-plugin/plugin.json @@ -1,18 +1,20 @@ { "name": "taiga-auto-sync", - "version": "0.1.0+codex.20260829123342", - "description": "Injects mandatory sprint, owner, and tag guards on every Codex prompt.", + "version": "0.1.0+codex.20260829130430", + "description": "Automatically tracks material IT Infra & Ops work and guards Taiga writes.", "author": { "name": "Local developer" }, "hooks": "./hooks/claude-codex-hooks.json", + "skills": "./skills/", "interface": { "displayName": "Taiga Auto Sync", - "shortDescription": "Taiga governance guard.", - "longDescription": "Guards active IT Infra & Ops work with a current sprint, owner, and required tags.", + "shortDescription": "Automatic Infra/Ops Taiga tracking.", + "longDescription": "Tracks material IT Infra & Ops work by context and validates Taiga writes.", "developerName": "Local developer", "category": "Productivity", "capabilities": [ + "Skills", "Lifecycle hooks" ], "defaultPrompt": "Help me use Taiga Auto Sync." diff --git a/plugins/taiga-auto-sync/hooks/claude-codex-hooks.json b/plugins/taiga-auto-sync/hooks/claude-codex-hooks.json index c8d4003..376afa4 100644 --- a/plugins/taiga-auto-sync/hooks/claude-codex-hooks.json +++ b/plugins/taiga-auto-sync/hooks/claude-codex-hooks.json @@ -1,11 +1,12 @@ { "hooks": { - "UserPromptSubmit": [{ + "PreToolUse": [{ + "matcher": "^mcp__taiga__(user_story|task|issue)_create$", "hooks": [{ "type": "command", - "command": "sh \"${CLAUDE_PLUGIN_ROOT}/hooks/taiga-reminder.sh\"", + "command": "python3 \"${CLAUDE_PLUGIN_ROOT}/hooks/taiga-write-guard.py\"", "timeout": 3, - "statusMessage": "Checking Taiga tracking..." + "statusMessage": "Checking Taiga item metadata..." }] }] } diff --git a/plugins/taiga-auto-sync/hooks/taiga-reminder.sh b/plugins/taiga-auto-sync/hooks/taiga-reminder.sh deleted file mode 100755 index 938d812..0000000 --- a/plugins/taiga-auto-sync/hooks/taiga-reminder.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -cat <<'EOF' -TAIGA AUTO-SYNC GUARD: For material IT Infra & Ops work, use Taiga before implementation; do not track read-only/no-op work. - -Before creating or activating any User Story, Task, or Issue, resolve the sprint containing today in WIB. If none exists, create the Monday–Sunday `YYYY-WNN Operations` sprint first. Never leave an active item without its current sprint, an accountable owner, and one area, `source:`, and `system:` or `repo:` tag. - -Classify one standalone daily activity as an Issue; use a User Story only for one outcome with two or more related Tasks, and create Tasks beneath that Story. A new User Story must use the Wiki description template. Use the corresponding Wiki template for Task or Issue descriptions. Preserve per-item local state for progress, blocked, and verified done updates; do not put secrets in it. -EOF diff --git a/plugins/taiga-auto-sync/hooks/taiga-write-guard.py b/plugins/taiga-auto-sync/hooks/taiga-write-guard.py new file mode 100644 index 0000000..f56756e --- /dev/null +++ b/plugins/taiga-auto-sync/hooks/taiga-write-guard.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +"""Reject Taiga item creation without the active-item metadata contract.""" +import json +import sys + +AREAS = { + "infra", "network", "cloud", "security", "backup", "monitoring", + "access", "automation", "support", "vendor", +} + + +def missing_fields(payload): + item = payload.get("tool_input", {}) + tags = set(item.get("tags") or []) + missing = [] + if not item.get("assigned_to"): + missing.append("owner") + if not item.get("milestone"): + missing.append("current sprint") + if not tags.intersection(AREAS): + missing.append("area tag") + if not any(tag.startswith("source:") for tag in tags): + missing.append("source tag") + if not any(tag.startswith(("repo:", "system:")) for tag in tags): + missing.append("target tag") + return missing + + +def result(payload): + missing = missing_fields(payload) + if not missing: + return None + return { + "hookSpecificOutput": { + "hookEventName": "PreToolUse", + "permissionDecision": "deny", + "permissionDecisionReason": ( + "Taiga item creation requires " + ", ".join(missing) + + ". Resolve or create the current WIB sprint first." + ), + } + } + + +def main(): + if sys.argv[1:] == ["--self-check"]: + assert result({"tool_input": {"assigned_to": 1, "milestone": 1, + "tags": ["infra", "source:codex", "repo:brain"]}}) is None + assert result({"tool_input": {"tags": []}}) + print("self-check: ok") + return + output = result(json.load(sys.stdin)) + if output: + print(json.dumps(output)) + + +if __name__ == "__main__": + main() diff --git a/plugins/taiga-auto-sync/skills/taiga-operations/SKILL.md b/plugins/taiga-auto-sync/skills/taiga-operations/SKILL.md new file mode 100644 index 0000000..8e36939 --- /dev/null +++ b/plugins/taiga-auto-sync/skills/taiga-operations/SKILL.md @@ -0,0 +1,15 @@ +--- +name: taiga-operations +description: Automatically track material IT Infrastructure & Operations implementation in Taiga, including deploys, incidents, maintenance, access, backup, monitoring, and infrastructure changes. Do not use for read-only questions, exploration, status explanations, or unrelated product work. +--- + +# Taiga Operations + +Use this workflow automatically when the prompt requests material IT Infra & Ops work. The user does not need to ask for a Taiga update. + +1. Do not create or update Taiga for reading, investigation without a change, planning only, no-op work, or secrets. +2. Before creating or activating an item, find the sprint that covers today in WIB. If none exists, create the Monday–Sunday `YYYY-WNN Operations` sprint, then use it. +3. Find an existing matching open item before creating a new one. Reuse its local state reference when available. +4. Classify a standalone daily operation as an Issue. Use one User Story only for one outcome with two or more related Tasks; create those Tasks beneath it. +5. Every active User Story, Task, and Issue needs an owner, current sprint, one area tag, one `source:` tag, and one `repo:` or `system:` tag. +6. Use the Wiki template for the selected item type. Record only material `start`, `progress`, `blocked`, and verified `done` events. Never put credentials or sensitive evidence in Taiga or local state.