claudecode-omc 5.6.8 → 5.9.1
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/.local/skills/prompt-optimizer/SKILL.md +262 -19
- package/.omc-curation/ecc-selection.json +80 -0
- package/.omc-curation/governance.json +113 -0
- package/.omc-curation/sources.lock.json +25 -0
- package/README.md +69 -4
- package/bundled/manifest.json +5 -5
- package/bundled/upstream/anthropic-skills/.omc-source/bundle.json +18 -0
- package/bundled/upstream/anthropic-skills/.omc-source/provenance.json +399 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/SKILL.md +18 -17
- package/bundled/upstream/anthropic-skills/skills/claude-api/curl/examples.md +9 -9
- package/bundled/upstream/anthropic-skills/skills/claude-api/curl/managed-agents.md +4 -4
- package/bundled/upstream/anthropic-skills/skills/claude-api/go/managed-agents/README.md +2 -2
- package/bundled/upstream/anthropic-skills/skills/claude-api/java/claude-api.md +2 -2
- package/bundled/upstream/anthropic-skills/skills/claude-api/java/managed-agents/README.md +2 -2
- package/bundled/upstream/anthropic-skills/skills/claude-api/php/claude-api.md +10 -10
- package/bundled/upstream/anthropic-skills/skills/claude-api/php/managed-agents/README.md +2 -2
- package/bundled/upstream/anthropic-skills/skills/claude-api/python/claude-api/README.md +16 -16
- package/bundled/upstream/anthropic-skills/skills/claude-api/python/claude-api/batches.md +3 -3
- package/bundled/upstream/anthropic-skills/skills/claude-api/python/claude-api/files-api.md +3 -3
- package/bundled/upstream/anthropic-skills/skills/claude-api/python/claude-api/streaming.md +7 -7
- package/bundled/upstream/anthropic-skills/skills/claude-api/python/claude-api/tool-use.md +19 -19
- package/bundled/upstream/anthropic-skills/skills/claude-api/python/managed-agents/README.md +3 -3
- package/bundled/upstream/anthropic-skills/skills/claude-api/ruby/claude-api.md +4 -4
- package/bundled/upstream/anthropic-skills/skills/claude-api/ruby/managed-agents/README.md +2 -2
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/error-codes.md +5 -5
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/live-sources.md +3 -1
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-api-reference.md +10 -4
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-core.md +19 -1
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-environments.md +6 -2
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-multiagent.md +1 -1
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-onboarding.md +3 -3
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-overview.md +3 -2
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-self-hosted-sandboxes.md +173 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-tools.md +10 -4
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/model-migration.md +113 -13
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/models.md +14 -11
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/prompt-caching.md +2 -2
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/tool-use-concepts.md +4 -4
- package/bundled/upstream/anthropic-skills/skills/claude-api/typescript/claude-api/README.md +15 -15
- package/bundled/upstream/anthropic-skills/skills/claude-api/typescript/claude-api/batches.md +2 -2
- package/bundled/upstream/anthropic-skills/skills/claude-api/typescript/claude-api/files-api.md +1 -1
- package/bundled/upstream/anthropic-skills/skills/claude-api/typescript/claude-api/streaming.md +5 -5
- package/bundled/upstream/anthropic-skills/skills/claude-api/typescript/claude-api/tool-use.md +15 -15
- package/bundled/upstream/anthropic-skills/skills/claude-api/typescript/managed-agents/README.md +3 -3
- package/bundled/upstream/ecc/.omc-source/bundle.json +2 -1
- package/bundled/upstream/ecc/.omc-source/last-plan-apply.json +108 -24
- package/bundled/upstream/ecc/.omc-source/manifests/.claude-plugin/marketplace.json +3 -3
- package/bundled/upstream/ecc/.omc-source/provenance.json +563 -0
- package/bundled/upstream/ecc/agents/marketing-agent.md +159 -0
- package/bundled/upstream/ecc/agents/react-build-resolver.md +215 -0
- package/bundled/upstream/ecc/agents/react-reviewer.md +167 -0
- package/bundled/upstream/ecc/agents/typescript-reviewer.md +3 -0
- package/bundled/upstream/ecc/commands/harness-audit.md +17 -10
- package/bundled/upstream/ecc/commands/marketing-campaign.md +129 -0
- package/bundled/upstream/ecc/commands/react-build.md +187 -0
- package/bundled/upstream/ecc/commands/react-review.md +170 -0
- package/bundled/upstream/ecc/commands/react-test.md +265 -0
- package/bundled/upstream/ecc/skills/benchmark-optimization-loop/SKILL.md +69 -0
- package/bundled/upstream/ecc/skills/blender-motion-state-inspection/SKILL.md +164 -0
- package/bundled/upstream/ecc/skills/canary-watch/SKILL.md +9 -1
- package/bundled/upstream/ecc/skills/continuous-learning-v2/hooks/observe.sh +31 -9
- package/bundled/upstream/ecc/skills/continuous-learning-v2/scripts/detect-project.sh +38 -4
- package/bundled/upstream/ecc/skills/continuous-learning-v2/scripts/instinct-cli.py +319 -12
- package/bundled/upstream/ecc/skills/data-throughput-accelerator/SKILL.md +72 -0
- package/bundled/upstream/ecc/skills/dynamic-workflow-mode/SKILL.md +123 -0
- package/bundled/upstream/ecc/skills/frontend-a11y/SKILL.md +446 -0
- package/bundled/upstream/ecc/skills/ito-basket-compare/SKILL.md +63 -0
- package/bundled/upstream/ecc/skills/ito-data-atlas-agent/SKILL.md +63 -0
- package/bundled/upstream/ecc/skills/ito-market-intelligence/SKILL.md +60 -0
- package/bundled/upstream/ecc/skills/ito-trade-planner/SKILL.md +67 -0
- package/bundled/upstream/ecc/skills/latency-critical-systems/SKILL.md +73 -0
- package/bundled/upstream/ecc/skills/marketing-campaign/SKILL.md +113 -0
- package/bundled/upstream/ecc/skills/nextjs-turbopack/SKILL.md +13 -0
- package/bundled/upstream/ecc/skills/parallel-execution-optimizer/SKILL.md +72 -0
- package/bundled/upstream/ecc/skills/prediction-market-oracle-research/SKILL.md +63 -0
- package/bundled/upstream/ecc/skills/prediction-market-risk-review/SKILL.md +60 -0
- package/bundled/upstream/ecc/skills/react-patterns/SKILL.md +341 -0
- package/bundled/upstream/ecc/skills/react-performance/SKILL.md +574 -0
- package/bundled/upstream/ecc/skills/react-testing/SKILL.md +423 -0
- package/bundled/upstream/ecc/skills/recsys-pipeline-architect/SKILL.md +114 -0
- package/bundled/upstream/ecc/skills/recursive-decision-ledger/SKILL.md +79 -0
- package/bundled/upstream/ecc/skills/social-publisher/SKILL.md +115 -0
- package/bundled/upstream/ecc/skills/team-agent-orchestration/SKILL.md +110 -0
- package/bundled/upstream/ecc/skills/uncloud/SKILL.md +343 -0
- package/bundled/upstream/ecc/skills/windows-desktop-e2e/SKILL.md +99 -0
- package/bundled/upstream/oh-my-claudecode/.omc-source/bundle.json +2 -1
- package/bundled/upstream/oh-my-claudecode/.omc-source/provenance.json +116 -0
- package/bundled/upstream/oh-my-claudecode/skills/autopilot/SKILL.md +7 -0
- package/bundled/upstream/oh-my-claudecode/skills/cancel/SKILL.md +1 -0
- package/bundled/upstream/oh-my-claudecode/skills/deep-interview/SKILL.md +39 -5
- package/bundled/upstream/oh-my-claudecode/skills/hud/SKILL.md +1 -0
- package/bundled/upstream/oh-my-claudecode/skills/local-build-reminder/SKILL.md +78 -0
- package/bundled/upstream/oh-my-claudecode/skills/omc-doctor/SKILL.md +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/omc-setup/SKILL.md +26 -10
- package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/01-install-claude-md.md +3 -3
- package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/02-configure.md +6 -4
- package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/03-integrations.md +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/04-welcome.md +2 -2
- package/bundled/upstream/oh-my-claudecode/skills/omc-teams/SKILL.md +6 -6
- package/bundled/upstream/oh-my-claudecode/skills/plan/SKILL.md +44 -32
- package/bundled/upstream/oh-my-claudecode/skills/ralph/SKILL.md +45 -21
- package/bundled/upstream/oh-my-claudecode/skills/ralplan/SKILL.md +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/self-improve/SKILL.md +7 -0
- package/bundled/upstream/oh-my-claudecode/skills/self-improve/scripts/resolve-paths.mjs +39 -15
- package/bundled/upstream/oh-my-claudecode/skills/team/SKILL.md +132 -90
- package/bundled/upstream/oh-my-claudecode/skills/ultragoal/SKILL.md +93 -0
- package/bundled/upstream/oh-my-claudecode/skills/ultraqa/SKILL.md +28 -13
- package/bundled/upstream/oh-my-claudecode/skills/ultrawork/SKILL.md +7 -0
- package/bundled/upstream/superpowers/.omc-source/bundle.json +2 -1
- package/bundled/upstream/superpowers/.omc-source/provenance.json +63 -0
- package/package.json +2 -1
- package/src/catalog/source-catalog.js +10 -4
- package/src/cli/index.js +4 -0
- package/src/cli/plan.js +14 -2
- package/src/cli/setup.js +52 -13
- package/src/cli/skill.js +1 -1
- package/src/cli/source.js +265 -14
- package/src/config/sources.js +67 -1
- package/src/merge/content-patch.js +84 -0
- package/templates/merge-config.json +1 -8
- package/bundled/upstream/ecc/skills/strategic-compact/suggest-compact.sh +0 -54
|
@@ -75,16 +75,42 @@ _clv2_normalize_remote_url() {
|
|
|
75
75
|
fi
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
_clv2_main_worktree_root() {
|
|
79
|
+
local root="$1"
|
|
80
|
+
[ -z "$root" ] && return 0
|
|
81
|
+
command -v git >/dev/null 2>&1 || return 0
|
|
82
|
+
|
|
83
|
+
git -C "$root" worktree list --porcelain 2>/dev/null | while IFS= read -r line; do
|
|
84
|
+
case "$line" in
|
|
85
|
+
worktree\ *)
|
|
86
|
+
printf '%s\n' "${line#worktree }"
|
|
87
|
+
break
|
|
88
|
+
;;
|
|
89
|
+
esac
|
|
90
|
+
done
|
|
91
|
+
}
|
|
92
|
+
|
|
78
93
|
_clv2_detect_project() {
|
|
79
94
|
local project_root=""
|
|
80
95
|
local project_name=""
|
|
81
96
|
local project_id=""
|
|
82
97
|
local source_hint=""
|
|
83
98
|
|
|
99
|
+
if [ "${CLV2_NO_PROJECT:-0}" = "1" ]; then
|
|
100
|
+
_CLV2_PROJECT_ID="global"
|
|
101
|
+
_CLV2_PROJECT_NAME="global"
|
|
102
|
+
_CLV2_PROJECT_ROOT=""
|
|
103
|
+
_CLV2_PROJECT_DIR="${_CLV2_HOMUNCULUS_DIR}"
|
|
104
|
+
mkdir -p "$_CLV2_PROJECT_DIR"
|
|
105
|
+
return 0
|
|
106
|
+
fi
|
|
107
|
+
|
|
84
108
|
# 1. Try CLAUDE_PROJECT_DIR env var
|
|
85
|
-
if [ -n "$CLAUDE_PROJECT_DIR" ] && [ -d "$CLAUDE_PROJECT_DIR" ]; then
|
|
86
|
-
project_root
|
|
87
|
-
|
|
109
|
+
if [ -n "$CLAUDE_PROJECT_DIR" ] && [ -d "$CLAUDE_PROJECT_DIR" ] && command -v git &>/dev/null; then
|
|
110
|
+
project_root=$(git -C "$CLAUDE_PROJECT_DIR" rev-parse --show-toplevel 2>/dev/null || true)
|
|
111
|
+
if [ -n "$project_root" ]; then
|
|
112
|
+
source_hint="env"
|
|
113
|
+
fi
|
|
88
114
|
fi
|
|
89
115
|
|
|
90
116
|
# 2. Try git repo root from CWD (only if git is available)
|
|
@@ -101,6 +127,7 @@ _clv2_detect_project() {
|
|
|
101
127
|
_CLV2_PROJECT_NAME="global"
|
|
102
128
|
_CLV2_PROJECT_ROOT=""
|
|
103
129
|
_CLV2_PROJECT_DIR="${_CLV2_HOMUNCULUS_DIR}"
|
|
130
|
+
mkdir -p "$_CLV2_PROJECT_DIR"
|
|
104
131
|
return 0
|
|
105
132
|
fi
|
|
106
133
|
|
|
@@ -133,7 +160,14 @@ _clv2_detect_project() {
|
|
|
133
160
|
normalized_remote=$(_clv2_normalize_remote_url "$remote_url")
|
|
134
161
|
fi
|
|
135
162
|
|
|
136
|
-
local
|
|
163
|
+
local fallback_root="$project_root"
|
|
164
|
+
if [ -z "$remote_url" ]; then
|
|
165
|
+
local main_worktree_root
|
|
166
|
+
main_worktree_root=$(_clv2_main_worktree_root "$project_root")
|
|
167
|
+
[ -n "$main_worktree_root" ] && fallback_root="$main_worktree_root"
|
|
168
|
+
fi
|
|
169
|
+
|
|
170
|
+
local hash_input="${normalized_remote:-${remote_url:-$fallback_root}}"
|
|
137
171
|
# Prefer Python for consistent SHA256 behavior across shells/platforms.
|
|
138
172
|
# Pass the value via env var and encode as UTF-8 inside Python so the hash
|
|
139
173
|
# is locale-independent (shells vary between UTF-8 / CP932 / CP1252, which
|
|
@@ -22,6 +22,7 @@ import os
|
|
|
22
22
|
import subprocess
|
|
23
23
|
import sys
|
|
24
24
|
import re
|
|
25
|
+
import shutil
|
|
25
26
|
import urllib.request
|
|
26
27
|
from pathlib import Path
|
|
27
28
|
from datetime import datetime, timedelta, timezone
|
|
@@ -194,26 +195,64 @@ def _yaml_quote(value: str) -> str:
|
|
|
194
195
|
# Project Detection (Python equivalent of detect-project.sh)
|
|
195
196
|
# ─────────────────────────────────────────────
|
|
196
197
|
|
|
198
|
+
def _git_repo_root(cwd: Optional[str] = None) -> Optional[str]:
|
|
199
|
+
args = ["git"]
|
|
200
|
+
if cwd:
|
|
201
|
+
args.extend(["-C", cwd])
|
|
202
|
+
args.extend(["rev-parse", "--show-toplevel"])
|
|
203
|
+
try:
|
|
204
|
+
result = subprocess.run(args, capture_output=True, text=True, timeout=5)
|
|
205
|
+
if result.returncode == 0:
|
|
206
|
+
return result.stdout.strip()
|
|
207
|
+
except (subprocess.TimeoutExpired, FileNotFoundError):
|
|
208
|
+
pass
|
|
209
|
+
return None
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def _main_worktree_root(project_root: str) -> str:
|
|
213
|
+
"""Return the main worktree root when project_root is a linked worktree."""
|
|
214
|
+
try:
|
|
215
|
+
result = subprocess.run(
|
|
216
|
+
["git", "-C", project_root, "worktree", "list", "--porcelain"],
|
|
217
|
+
capture_output=True, text=True, timeout=5
|
|
218
|
+
)
|
|
219
|
+
except (subprocess.TimeoutExpired, FileNotFoundError):
|
|
220
|
+
return project_root
|
|
221
|
+
|
|
222
|
+
if result.returncode != 0:
|
|
223
|
+
return project_root
|
|
224
|
+
|
|
225
|
+
for line in result.stdout.splitlines():
|
|
226
|
+
if line.startswith("worktree "):
|
|
227
|
+
main_root = line.split(" ", 1)[1].strip()
|
|
228
|
+
return main_root or project_root
|
|
229
|
+
return project_root
|
|
230
|
+
|
|
231
|
+
|
|
197
232
|
def detect_project() -> dict:
|
|
198
233
|
"""Detect current project context. Returns dict with id, name, root, project_dir."""
|
|
199
234
|
project_root = None
|
|
200
235
|
|
|
236
|
+
if os.environ.get("CLV2_NO_PROJECT") == "1":
|
|
237
|
+
return {
|
|
238
|
+
"id": "global",
|
|
239
|
+
"name": "global",
|
|
240
|
+
"root": "",
|
|
241
|
+
"project_dir": HOMUNCULUS_DIR,
|
|
242
|
+
"instincts_personal": GLOBAL_PERSONAL_DIR,
|
|
243
|
+
"instincts_inherited": GLOBAL_INHERITED_DIR,
|
|
244
|
+
"evolved_dir": GLOBAL_EVOLVED_DIR,
|
|
245
|
+
"observations_file": GLOBAL_OBSERVATIONS_FILE,
|
|
246
|
+
}
|
|
247
|
+
|
|
201
248
|
# 1. CLAUDE_PROJECT_DIR env var
|
|
202
249
|
env_dir = os.environ.get("CLAUDE_PROJECT_DIR")
|
|
203
250
|
if env_dir and os.path.isdir(env_dir):
|
|
204
|
-
project_root = env_dir
|
|
251
|
+
project_root = _git_repo_root(env_dir)
|
|
205
252
|
|
|
206
253
|
# 2. git repo root
|
|
207
254
|
if not project_root:
|
|
208
|
-
|
|
209
|
-
result = subprocess.run(
|
|
210
|
-
["git", "rev-parse", "--show-toplevel"],
|
|
211
|
-
capture_output=True, text=True, timeout=5
|
|
212
|
-
)
|
|
213
|
-
if result.returncode == 0:
|
|
214
|
-
project_root = result.stdout.strip()
|
|
215
|
-
except (subprocess.TimeoutExpired, FileNotFoundError):
|
|
216
|
-
pass
|
|
255
|
+
project_root = _git_repo_root()
|
|
217
256
|
|
|
218
257
|
# Normalize: strip trailing slashes to keep basename and hash stable
|
|
219
258
|
if project_root:
|
|
@@ -250,9 +289,10 @@ def detect_project() -> dict:
|
|
|
250
289
|
if remote_url:
|
|
251
290
|
remote_url = _strip_remote_credentials(remote_url)
|
|
252
291
|
|
|
292
|
+
fallback_root = _main_worktree_root(project_root) if not remote_url else project_root
|
|
253
293
|
legacy_hash_source = remote_url if remote_url else project_root
|
|
254
294
|
normalized_remote = _normalize_remote_url(remote_url) if remote_url else ""
|
|
255
|
-
hash_source = normalized_remote if normalized_remote else
|
|
295
|
+
hash_source = normalized_remote if normalized_remote else (remote_url if remote_url else fallback_root)
|
|
256
296
|
project_id = _project_hash(hash_source)
|
|
257
297
|
|
|
258
298
|
project_dir = PROJECTS_DIR / project_id
|
|
@@ -352,6 +392,26 @@ def load_registry() -> dict:
|
|
|
352
392
|
return {}
|
|
353
393
|
|
|
354
394
|
|
|
395
|
+
def _write_registry(registry: dict) -> None:
|
|
396
|
+
"""Write the project registry atomically."""
|
|
397
|
+
REGISTRY_FILE.parent.mkdir(parents=True, exist_ok=True)
|
|
398
|
+
tmp_file = REGISTRY_FILE.parent / f".{REGISTRY_FILE.name}.tmp.{os.getpid()}"
|
|
399
|
+
with open(tmp_file, "w", encoding="utf-8") as f:
|
|
400
|
+
json.dump(registry, f, indent=2)
|
|
401
|
+
f.write("\n")
|
|
402
|
+
f.flush()
|
|
403
|
+
os.fsync(f.fileno())
|
|
404
|
+
os.replace(tmp_file, REGISTRY_FILE)
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
def _validate_project_id(project_id: str) -> bool:
|
|
408
|
+
if not project_id or len(project_id) > 128:
|
|
409
|
+
return False
|
|
410
|
+
if "/" in project_id or "\\" in project_id or ".." in project_id:
|
|
411
|
+
return False
|
|
412
|
+
return bool(re.match(r"^[A-Za-z0-9][A-Za-z0-9._-]*$", project_id))
|
|
413
|
+
|
|
414
|
+
|
|
355
415
|
# ─────────────────────────────────────────────
|
|
356
416
|
# Instinct Parser
|
|
357
417
|
# ─────────────────────────────────────────────
|
|
@@ -436,6 +496,96 @@ def _load_instincts_from_dir(directory: Path, source_type: str, scope_label: str
|
|
|
436
496
|
return instincts
|
|
437
497
|
|
|
438
498
|
|
|
499
|
+
def _project_counts(project_id: str) -> dict:
|
|
500
|
+
project_dir = PROJECTS_DIR / project_id
|
|
501
|
+
personal_dir = project_dir / "instincts" / "personal"
|
|
502
|
+
inherited_dir = project_dir / "instincts" / "inherited"
|
|
503
|
+
observations_file = project_dir / "observations.jsonl"
|
|
504
|
+
|
|
505
|
+
personal_count = len(_load_instincts_from_dir(personal_dir, "personal", "project"))
|
|
506
|
+
inherited_count = len(_load_instincts_from_dir(inherited_dir, "inherited", "project"))
|
|
507
|
+
observations_count = 0
|
|
508
|
+
if observations_file.exists():
|
|
509
|
+
try:
|
|
510
|
+
with open(observations_file, encoding="utf-8") as f:
|
|
511
|
+
observations_count = sum(1 for _ in f)
|
|
512
|
+
except OSError:
|
|
513
|
+
observations_count = 0
|
|
514
|
+
|
|
515
|
+
return {
|
|
516
|
+
"personal": personal_count,
|
|
517
|
+
"inherited": inherited_count,
|
|
518
|
+
"observations": observations_count,
|
|
519
|
+
"total": personal_count + inherited_count + observations_count,
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
def _remove_project_storage(project_id: str) -> None:
|
|
524
|
+
project_dir = PROJECTS_DIR / project_id
|
|
525
|
+
if project_dir.exists():
|
|
526
|
+
shutil.rmtree(project_dir)
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
def _project_instinct_ids(project_dir: Path, source_type: str) -> set[str]:
|
|
530
|
+
instinct_dir = project_dir / "instincts" / source_type
|
|
531
|
+
return {
|
|
532
|
+
inst.get("id")
|
|
533
|
+
for inst in _load_instincts_from_dir(instinct_dir, source_type, "project")
|
|
534
|
+
if inst.get("id")
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
def _merge_instinct_dir(from_dir: Path, into_dir: Path, existing_ids: set[str]) -> tuple[int, int]:
|
|
539
|
+
moved = 0
|
|
540
|
+
skipped = 0
|
|
541
|
+
if not from_dir.exists():
|
|
542
|
+
return moved, skipped
|
|
543
|
+
|
|
544
|
+
into_dir.mkdir(parents=True, exist_ok=True)
|
|
545
|
+
for file_path in sorted(from_dir.iterdir()):
|
|
546
|
+
if not file_path.is_file() or file_path.suffix.lower() not in ALLOWED_INSTINCT_EXTENSIONS:
|
|
547
|
+
continue
|
|
548
|
+
try:
|
|
549
|
+
instincts = parse_instinct_file(file_path.read_text(encoding="utf-8"))
|
|
550
|
+
except (OSError, UnicodeDecodeError):
|
|
551
|
+
instincts = []
|
|
552
|
+
instinct_ids = [inst.get("id") for inst in instincts if inst.get("id")]
|
|
553
|
+
if any(instinct_id in existing_ids for instinct_id in instinct_ids):
|
|
554
|
+
skipped += 1
|
|
555
|
+
continue
|
|
556
|
+
|
|
557
|
+
target_path = into_dir / file_path.name
|
|
558
|
+
if target_path.exists():
|
|
559
|
+
target_path = into_dir / f"{file_path.stem}-{_project_hash(str(file_path))}{file_path.suffix}"
|
|
560
|
+
shutil.copy2(file_path, target_path)
|
|
561
|
+
existing_ids.update(instinct_ids)
|
|
562
|
+
moved += 1
|
|
563
|
+
|
|
564
|
+
return moved, skipped
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
def _append_observations(from_project_dir: Path, into_project_dir: Path) -> int:
|
|
568
|
+
from_file = from_project_dir / "observations.jsonl"
|
|
569
|
+
if not from_file.exists():
|
|
570
|
+
return 0
|
|
571
|
+
|
|
572
|
+
into_file = into_project_dir / "observations.jsonl"
|
|
573
|
+
into_file.parent.mkdir(parents=True, exist_ok=True)
|
|
574
|
+
try:
|
|
575
|
+
lines = from_file.read_text(encoding="utf-8").splitlines()
|
|
576
|
+
except (OSError, UnicodeDecodeError):
|
|
577
|
+
return 0
|
|
578
|
+
|
|
579
|
+
if not lines:
|
|
580
|
+
return 0
|
|
581
|
+
|
|
582
|
+
with open(into_file, "a", encoding="utf-8") as f:
|
|
583
|
+
for line in lines:
|
|
584
|
+
if line.strip():
|
|
585
|
+
f.write(line.rstrip("\n") + "\n")
|
|
586
|
+
return len([line for line in lines if line.strip()])
|
|
587
|
+
|
|
588
|
+
|
|
439
589
|
def load_all_instincts(project: dict, include_global: bool = True) -> list[dict]:
|
|
440
590
|
"""Load all instincts: project-scoped + global.
|
|
441
591
|
|
|
@@ -1180,7 +1330,14 @@ def _promote_auto(project: dict, force: bool, dry_run: bool) -> int:
|
|
|
1180
1330
|
# ─────────────────────────────────────────────
|
|
1181
1331
|
|
|
1182
1332
|
def cmd_projects(args) -> int:
|
|
1183
|
-
"""List
|
|
1333
|
+
"""List or maintain known projects and their instinct counts."""
|
|
1334
|
+
if getattr(args, "project_action", None) == "delete":
|
|
1335
|
+
return _cmd_projects_delete(args)
|
|
1336
|
+
if getattr(args, "project_action", None) == "merge":
|
|
1337
|
+
return _cmd_projects_merge(args)
|
|
1338
|
+
if getattr(args, "project_action", None) == "gc":
|
|
1339
|
+
return _cmd_projects_gc(args)
|
|
1340
|
+
|
|
1184
1341
|
registry = load_registry()
|
|
1185
1342
|
|
|
1186
1343
|
if not registry:
|
|
@@ -1225,6 +1382,143 @@ def cmd_projects(args) -> int:
|
|
|
1225
1382
|
return 0
|
|
1226
1383
|
|
|
1227
1384
|
|
|
1385
|
+
def _cmd_projects_delete(args) -> int:
|
|
1386
|
+
registry = load_registry()
|
|
1387
|
+
project_id = args.project_id
|
|
1388
|
+
|
|
1389
|
+
if not _validate_project_id(project_id):
|
|
1390
|
+
print(f"Invalid project ID: {project_id}", file=sys.stderr)
|
|
1391
|
+
return 1
|
|
1392
|
+
if project_id not in registry and not (PROJECTS_DIR / project_id).exists():
|
|
1393
|
+
print(f"Project '{project_id}' not found.", file=sys.stderr)
|
|
1394
|
+
return 1
|
|
1395
|
+
|
|
1396
|
+
counts = _project_counts(project_id)
|
|
1397
|
+
print(f"Project: {project_id}")
|
|
1398
|
+
print(f" Instincts: {counts['personal']} personal, {counts['inherited']} inherited")
|
|
1399
|
+
print(f" Observations: {counts['observations']} events")
|
|
1400
|
+
|
|
1401
|
+
if args.dry_run:
|
|
1402
|
+
print(f"\n[DRY RUN] Would delete project '{project_id}' from registry and storage.")
|
|
1403
|
+
return 0
|
|
1404
|
+
|
|
1405
|
+
if not args.force:
|
|
1406
|
+
if counts["total"] > 0:
|
|
1407
|
+
print("\nWarning: this project has instincts or observations.")
|
|
1408
|
+
response = input(f"Delete project '{project_id}'? [y/N] ")
|
|
1409
|
+
if response.lower() != "y":
|
|
1410
|
+
print("Cancelled.")
|
|
1411
|
+
return 0
|
|
1412
|
+
|
|
1413
|
+
registry.pop(project_id, None)
|
|
1414
|
+
_write_registry(registry)
|
|
1415
|
+
_remove_project_storage(project_id)
|
|
1416
|
+
print(f"\nDeleted project '{project_id}'.")
|
|
1417
|
+
return 0
|
|
1418
|
+
|
|
1419
|
+
|
|
1420
|
+
def _cmd_projects_gc(args) -> int:
|
|
1421
|
+
registry = load_registry()
|
|
1422
|
+
candidates = [
|
|
1423
|
+
project_id
|
|
1424
|
+
for project_id in sorted(registry)
|
|
1425
|
+
if _validate_project_id(project_id) and _project_counts(project_id)["total"] == 0
|
|
1426
|
+
]
|
|
1427
|
+
|
|
1428
|
+
if not candidates:
|
|
1429
|
+
print("No zero-value project entries found.")
|
|
1430
|
+
return 0
|
|
1431
|
+
|
|
1432
|
+
print(f"Zero-value project entries: {len(candidates)}")
|
|
1433
|
+
for project_id in candidates:
|
|
1434
|
+
pinfo = registry.get(project_id, {})
|
|
1435
|
+
print(f" - {pinfo.get('name', project_id)} [{project_id}]")
|
|
1436
|
+
|
|
1437
|
+
if args.dry_run:
|
|
1438
|
+
print(f"\n[DRY RUN] Would delete {len(candidates)} project entr{'y' if len(candidates) == 1 else 'ies'}.")
|
|
1439
|
+
return 0
|
|
1440
|
+
|
|
1441
|
+
if not args.force:
|
|
1442
|
+
response = input(f"\nDelete {len(candidates)} zero-value project entr{'y' if len(candidates) == 1 else 'ies'}? [y/N] ")
|
|
1443
|
+
if response.lower() != "y":
|
|
1444
|
+
print("Cancelled.")
|
|
1445
|
+
return 0
|
|
1446
|
+
|
|
1447
|
+
for project_id in candidates:
|
|
1448
|
+
registry.pop(project_id, None)
|
|
1449
|
+
_remove_project_storage(project_id)
|
|
1450
|
+
_write_registry(registry)
|
|
1451
|
+
print(f"\nDeleted {len(candidates)} zero-value project entr{'y' if len(candidates) == 1 else 'ies'}.")
|
|
1452
|
+
return 0
|
|
1453
|
+
|
|
1454
|
+
|
|
1455
|
+
def _cmd_projects_merge(args) -> int:
|
|
1456
|
+
from_id = args.from_id
|
|
1457
|
+
into_id = args.into_id
|
|
1458
|
+
|
|
1459
|
+
if not _validate_project_id(from_id) or not _validate_project_id(into_id):
|
|
1460
|
+
print("Invalid project ID.", file=sys.stderr)
|
|
1461
|
+
return 1
|
|
1462
|
+
if from_id == into_id:
|
|
1463
|
+
print("Cannot merge a project into itself.", file=sys.stderr)
|
|
1464
|
+
return 1
|
|
1465
|
+
|
|
1466
|
+
registry = load_registry()
|
|
1467
|
+
if from_id not in registry:
|
|
1468
|
+
print(f"Source project '{from_id}' not found.", file=sys.stderr)
|
|
1469
|
+
return 1
|
|
1470
|
+
if into_id not in registry:
|
|
1471
|
+
print(f"Destination project '{into_id}' not found.", file=sys.stderr)
|
|
1472
|
+
return 1
|
|
1473
|
+
|
|
1474
|
+
from_counts = _project_counts(from_id)
|
|
1475
|
+
into_counts = _project_counts(into_id)
|
|
1476
|
+
print(f"Merge: {from_id} -> {into_id}")
|
|
1477
|
+
print(f" Source: {from_counts['personal']} personal, {from_counts['inherited']} inherited, {from_counts['observations']} observations")
|
|
1478
|
+
print(f" Destination before merge: {into_counts['personal']} personal, {into_counts['inherited']} inherited, {into_counts['observations']} observations")
|
|
1479
|
+
|
|
1480
|
+
if args.dry_run:
|
|
1481
|
+
print("\n[DRY RUN] Would merge source project into destination and remove source.")
|
|
1482
|
+
return 0
|
|
1483
|
+
|
|
1484
|
+
if not args.force:
|
|
1485
|
+
response = input(f"\nMerge '{from_id}' into '{into_id}' and remove source? [y/N] ")
|
|
1486
|
+
if response.lower() != "y":
|
|
1487
|
+
print("Cancelled.")
|
|
1488
|
+
return 0
|
|
1489
|
+
|
|
1490
|
+
from_project_dir = PROJECTS_DIR / from_id
|
|
1491
|
+
into_project_dir = PROJECTS_DIR / into_id
|
|
1492
|
+
into_project_dir.mkdir(parents=True, exist_ok=True)
|
|
1493
|
+
|
|
1494
|
+
personal_existing = _project_instinct_ids(into_project_dir, "personal")
|
|
1495
|
+
inherited_existing = _project_instinct_ids(into_project_dir, "inherited")
|
|
1496
|
+
personal_moved, personal_skipped = _merge_instinct_dir(
|
|
1497
|
+
from_project_dir / "instincts" / "personal",
|
|
1498
|
+
into_project_dir / "instincts" / "personal",
|
|
1499
|
+
personal_existing,
|
|
1500
|
+
)
|
|
1501
|
+
inherited_moved, inherited_skipped = _merge_instinct_dir(
|
|
1502
|
+
from_project_dir / "instincts" / "inherited",
|
|
1503
|
+
into_project_dir / "instincts" / "inherited",
|
|
1504
|
+
inherited_existing,
|
|
1505
|
+
)
|
|
1506
|
+
observations_moved = _append_observations(from_project_dir, into_project_dir)
|
|
1507
|
+
|
|
1508
|
+
registry.pop(from_id, None)
|
|
1509
|
+
destination = registry.get(into_id, {})
|
|
1510
|
+
destination["last_seen"] = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
|
|
1511
|
+
registry[into_id] = destination
|
|
1512
|
+
_write_registry(registry)
|
|
1513
|
+
_remove_project_storage(from_id)
|
|
1514
|
+
|
|
1515
|
+
print("\nMerged project registry entry.")
|
|
1516
|
+
print(f" Moved instincts: {personal_moved + inherited_moved}")
|
|
1517
|
+
print(f" Skipped duplicate instincts: {personal_skipped + inherited_skipped}")
|
|
1518
|
+
print(f" Appended observations: {observations_moved}")
|
|
1519
|
+
return 0
|
|
1520
|
+
|
|
1521
|
+
|
|
1228
1522
|
# ─────────────────────────────────────────────
|
|
1229
1523
|
# Generate Evolved Structures
|
|
1230
1524
|
# ─────────────────────────────────────────────
|
|
@@ -1486,6 +1780,19 @@ def main() -> int:
|
|
|
1486
1780
|
|
|
1487
1781
|
# Projects (new in v2.1)
|
|
1488
1782
|
projects_parser = subparsers.add_parser('projects', help='List known projects and instinct counts')
|
|
1783
|
+
projects_subparsers = projects_parser.add_subparsers(dest='project_action')
|
|
1784
|
+
projects_delete = projects_subparsers.add_parser('delete', help='Delete a project registry entry')
|
|
1785
|
+
projects_delete.add_argument('project_id', help='Project ID to delete')
|
|
1786
|
+
projects_delete.add_argument('--dry-run', action='store_true', help='Preview without deleting')
|
|
1787
|
+
projects_delete.add_argument('--force', action='store_true', help='Skip confirmation')
|
|
1788
|
+
projects_merge = projects_subparsers.add_parser('merge', help='Merge one project registry entry into another')
|
|
1789
|
+
projects_merge.add_argument('from_id', help='Source project ID')
|
|
1790
|
+
projects_merge.add_argument('into_id', help='Destination project ID')
|
|
1791
|
+
projects_merge.add_argument('--dry-run', action='store_true', help='Preview without merging')
|
|
1792
|
+
projects_merge.add_argument('--force', action='store_true', help='Skip confirmation')
|
|
1793
|
+
projects_gc = projects_subparsers.add_parser('gc', help='Delete zero-value project registry entries')
|
|
1794
|
+
projects_gc.add_argument('--dry-run', action='store_true', help='Preview without deleting')
|
|
1795
|
+
projects_gc.add_argument('--force', action='store_true', help='Skip confirmation')
|
|
1489
1796
|
|
|
1490
1797
|
# Prune (pending instinct TTL)
|
|
1491
1798
|
prune_parser = subparsers.add_parser('prune', help='Delete pending instincts older than TTL')
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: data-throughput-accelerator
|
|
3
|
+
description: Use when large data ingestion, backfill, export, ETL, warehouse loading, manifest catch-up, or table synchronization needs to become much faster while preserving data correctness.
|
|
4
|
+
origin: ECC
|
|
5
|
+
tools: Read, Write, Edit, Bash, Grep, Glob
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Data Throughput Accelerator
|
|
9
|
+
|
|
10
|
+
Use this skill when the bottleneck is moving, transforming, or saving lots of
|
|
11
|
+
data. The goal is not just speed. The goal is faster correct data landing in the
|
|
12
|
+
right place with proof.
|
|
13
|
+
|
|
14
|
+
## First Distinction
|
|
15
|
+
|
|
16
|
+
Separate these before optimizing:
|
|
17
|
+
|
|
18
|
+
- source extraction speed;
|
|
19
|
+
- network transfer speed;
|
|
20
|
+
- warehouse/load speed;
|
|
21
|
+
- transform speed;
|
|
22
|
+
- serving-table freshness;
|
|
23
|
+
- live tail growth while the job runs.
|
|
24
|
+
|
|
25
|
+
A pipeline can be "fast" and still appear behind if new data arrives faster
|
|
26
|
+
than the final catch-up window.
|
|
27
|
+
|
|
28
|
+
## Fast Path Heuristics
|
|
29
|
+
|
|
30
|
+
- Move compute to where the data already is.
|
|
31
|
+
- Prefer warehouse-native scans, joins, and appends for large landed files.
|
|
32
|
+
- Use manifests or checkpoints so completed files/partitions are skipped.
|
|
33
|
+
- Use partitioning and clustering that match the read and append pattern.
|
|
34
|
+
- Batch small files, requests, and writes.
|
|
35
|
+
- Make writes idempotent through unique keys, manifests, or replaceable staging.
|
|
36
|
+
- Keep raw, derived, and serving tables separately accountable.
|
|
37
|
+
|
|
38
|
+
## Workflow
|
|
39
|
+
|
|
40
|
+
1. Read the current source, target, and manifest contracts.
|
|
41
|
+
2. Measure backlog: external files, manifest rows, raw rows, derived rows,
|
|
42
|
+
min/max timestamps, and unprocessed counts.
|
|
43
|
+
3. Run a safe catch-up or sample benchmark.
|
|
44
|
+
4. Compare variants: batch size, worker count, warehouse SQL, file grouping,
|
|
45
|
+
staging shape, and manifest update method.
|
|
46
|
+
5. Promote only the fastest path that keeps counts and timestamps coherent.
|
|
47
|
+
6. Codify the path as a CLI, scheduled job, workflow, or runbook.
|
|
48
|
+
7. Rerun final accounting after the codified path executes.
|
|
49
|
+
|
|
50
|
+
## Accounting Output
|
|
51
|
+
|
|
52
|
+
Use a hard accounting block:
|
|
53
|
+
|
|
54
|
+
```text
|
|
55
|
+
Data throughput result:
|
|
56
|
+
- Source files discovered: 294
|
|
57
|
+
- Files processed this run: 294
|
|
58
|
+
- Raw rows added: 9,683,598
|
|
59
|
+
- Derived rows added: 8,917,585
|
|
60
|
+
- Remaining tail: 24 files at readback time
|
|
61
|
+
- Runtime: 38.7s
|
|
62
|
+
- Correctness gate: manifest counts and table max timestamps match
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Guardrails
|
|
66
|
+
|
|
67
|
+
- Do not delete raw data to make a metric look better.
|
|
68
|
+
- Do not skip failed files silently.
|
|
69
|
+
- Do not mix historical backfill status with live-tail freshness.
|
|
70
|
+
- Do not call a pipeline complete until the target tables and manifest agree.
|
|
71
|
+
- For finance, healthcare, regulated, or customer-impacting data, preserve
|
|
72
|
+
replay evidence and approval gates.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dynamic-workflow-mode
|
|
3
|
+
description: "Design task-local harnesses, eval gates, and reusable skill extraction for Claude dynamic workflow mode and other adaptive agent harnesses."
|
|
4
|
+
origin: ECC
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Dynamic Workflow Mode
|
|
8
|
+
|
|
9
|
+
Use this skill when a coding agent can generate or adapt a task-local harness instead of only following a static command flow. The goal is to turn dynamic workflow mode into a disciplined system: temporary harnesses for one-off work, shared skill extraction for repeated work, and observable control pane checkpoints for teams.
|
|
10
|
+
|
|
11
|
+
## When To Activate
|
|
12
|
+
|
|
13
|
+
- The user mentions dynamic workflows, custom harnesses, harness-per-task, adaptive workflows, or Claude Code dynamic workflow mode.
|
|
14
|
+
- A task needs a custom loop, evaluator, crawler, fixture generator, watcher, or local dashboard.
|
|
15
|
+
- Multiple agents need the same repeatable process but the process is not yet captured as a shared skill.
|
|
16
|
+
- A workflow needs durable handoff artifacts, eval evidence, or operator approval before merge.
|
|
17
|
+
|
|
18
|
+
## Core Contract
|
|
19
|
+
|
|
20
|
+
Dynamic workflow mode should produce a task-local harness only when the harness is cheaper and safer than manually driving the same steps. The harness must have:
|
|
21
|
+
|
|
22
|
+
- **Objective**: the outcome it owns and the outcome it explicitly does not own.
|
|
23
|
+
- **Inputs**: files, URLs, prompts, data sources, credentials policy, and user-provided constraints.
|
|
24
|
+
- **Outputs**: commits, reports, screenshots, status files, or control pane snapshots.
|
|
25
|
+
- **Eval**: at least one pass/fail check tied to the task, not only "it ran".
|
|
26
|
+
- **Handoff**: a short artifact that tells the next operator what happened, what is blocked, and how to resume.
|
|
27
|
+
|
|
28
|
+
## Dynamic Harness Decision Tree
|
|
29
|
+
|
|
30
|
+
1. **One-shot task**: keep it inline. Do not invent a harness.
|
|
31
|
+
2. **Repeated task with changing inputs**: create a task-local harness and keep it under a temp or project-local working area.
|
|
32
|
+
3. **Repeated task across teammates or repos**: extract the pattern into a shared skill.
|
|
33
|
+
4. **Task with external state, queueing, or approvals**: add control pane visibility before adding more automation.
|
|
34
|
+
5. **Task with safety risk**: add an eval gate and a human merge gate before autonomous execution.
|
|
35
|
+
|
|
36
|
+
## Task-Local Harness Template
|
|
37
|
+
|
|
38
|
+
Use this structure before writing code:
|
|
39
|
+
|
|
40
|
+
```markdown
|
|
41
|
+
# Dynamic Workflow Harness
|
|
42
|
+
|
|
43
|
+
Objective:
|
|
44
|
+
- Ship:
|
|
45
|
+
- Do not ship:
|
|
46
|
+
|
|
47
|
+
Inputs:
|
|
48
|
+
- Repo or workspace:
|
|
49
|
+
- External systems:
|
|
50
|
+
- Credentials policy:
|
|
51
|
+
|
|
52
|
+
Loop:
|
|
53
|
+
1. Discover current state.
|
|
54
|
+
2. Generate or update the smallest useful artifact.
|
|
55
|
+
3. Run eval checks.
|
|
56
|
+
4. Record status and handoff.
|
|
57
|
+
5. Stop on failed gate, unclear ownership, or unsafe external action.
|
|
58
|
+
|
|
59
|
+
Eval:
|
|
60
|
+
- Command:
|
|
61
|
+
- Expected pass signal:
|
|
62
|
+
- Failure owner:
|
|
63
|
+
|
|
64
|
+
Handoff:
|
|
65
|
+
- Status:
|
|
66
|
+
- Evidence:
|
|
67
|
+
- Next action:
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Shared Skill Extraction
|
|
71
|
+
|
|
72
|
+
Promote a task-local harness into a shared skill only when at least two of these are true:
|
|
73
|
+
|
|
74
|
+
- The same workflow appears in multiple sessions, repos, teams, or launches.
|
|
75
|
+
- The workflow needs specific language, tool, or safety sequencing.
|
|
76
|
+
- Failures repeat because operators skip a gate or lose context.
|
|
77
|
+
- The workflow has a stable input/output contract.
|
|
78
|
+
- The workflow benefits from a control pane, status board, or team handoff.
|
|
79
|
+
|
|
80
|
+
When extracting, write the skill first in `skills/<name>/SKILL.md`. Add command shims only if a legacy slash-entry surface is still required.
|
|
81
|
+
|
|
82
|
+
## Control Pane Checkpoints
|
|
83
|
+
|
|
84
|
+
Dynamic workflow mode becomes team-usable when it exposes state. Record these checkpoints whenever the task spans more than one session:
|
|
85
|
+
|
|
86
|
+
- **Plan**: objective, owner, acceptance criteria, and risky external systems.
|
|
87
|
+
- **Queue**: work items, assigned agent role, branch/worktree, and dependency edges.
|
|
88
|
+
- **Run**: active harness, current loop step, recent eval result, and token/cost signal if available.
|
|
89
|
+
- **Gate**: test results, browser screenshots, security review, and merge readiness.
|
|
90
|
+
- **Handoff**: what is done, what failed, what needs a human decision.
|
|
91
|
+
|
|
92
|
+
If the repo has ECC2 state enabled, prefer adding or reading checkpoints through the ECC control pane or state-store-backed scripts instead of scattering untracked notes.
|
|
93
|
+
|
|
94
|
+
## Eval Gates
|
|
95
|
+
|
|
96
|
+
Every dynamic harness needs a task-specific eval. Pick the cheapest reliable gate:
|
|
97
|
+
|
|
98
|
+
| Work Type | Eval Gate |
|
|
99
|
+
| --- | --- |
|
|
100
|
+
| Code feature | Focused test, lint, coverage, and one integration path |
|
|
101
|
+
| UI/control pane | Browser smoke with screenshot and overflow/error checks |
|
|
102
|
+
| Agent workflow | Fixture transcript or seeded work item with expected routing |
|
|
103
|
+
| Research/content | Source-neutral brief, claim checklist, and publish-ready outline |
|
|
104
|
+
| Integration | Dry-run command, config validation, and no-secret scan |
|
|
105
|
+
|
|
106
|
+
Do not claim a dynamic workflow is reusable until the eval can be rerun by another teammate.
|
|
107
|
+
|
|
108
|
+
## Anti-Patterns
|
|
109
|
+
|
|
110
|
+
- Generating scripts that hide the real decision logic from the operator.
|
|
111
|
+
- Treating dynamic workflow mode as permission to skip tests.
|
|
112
|
+
- Creating one-off docs when a shared skill or status artifact is the real product.
|
|
113
|
+
- Running multiple agents without ownership, merge gate, or conflict policy.
|
|
114
|
+
- Letting raw private research data leak into public docs.
|
|
115
|
+
|
|
116
|
+
## Output Standard
|
|
117
|
+
|
|
118
|
+
Finish with:
|
|
119
|
+
|
|
120
|
+
- The harness or skill path.
|
|
121
|
+
- The eval commands and results.
|
|
122
|
+
- The control pane or handoff artifact path.
|
|
123
|
+
- The next reusable extraction candidate.
|