oh-my-customcode 0.51.0 → 0.51.2

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
@@ -228,7 +228,7 @@ Key rules: R010 (orchestrator never writes files), R009 (parallel execution mand
228
228
 
229
229
  ---
230
230
 
231
- ### Guides (29)
231
+ ### Guides (30)
232
232
 
233
233
  Reference documentation covering best practices, architecture decisions, and integration patterns. Located in `guides/` at project root, covering topics from agent design to CI/CD to observability.
234
234
 
@@ -281,7 +281,7 @@ your-project/
281
281
  │ ├── specs/ # Extracted canonical specs
282
282
  │ ├── contexts/ # 4 shared context files
283
283
  │ └── ontology/ # Knowledge graph for RAG
284
- └── guides/ # 29 reference documents
284
+ └── guides/ # 30 reference documents
285
285
  ```
286
286
 
287
287
  ---
package/dist/cli/index.js CHANGED
@@ -9323,7 +9323,7 @@ var init_package = __esm(() => {
9323
9323
  package_default = {
9324
9324
  name: "oh-my-customcode",
9325
9325
  workspaces: ["packages/*"],
9326
- version: "0.51.0",
9326
+ version: "0.51.2",
9327
9327
  description: "Batteries-included agent harness for Claude Code",
9328
9328
  type: "module",
9329
9329
  bin: {
package/dist/index.js CHANGED
@@ -1668,7 +1668,7 @@ import { join as join6 } from "node:path";
1668
1668
  var package_default = {
1669
1669
  name: "oh-my-customcode",
1670
1670
  workspaces: ["packages/*"],
1671
- version: "0.51.0",
1671
+ version: "0.51.2",
1672
1672
  description: "Batteries-included agent harness for Claude Code",
1673
1673
  type: "module",
1674
1674
  bin: {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "oh-my-customcode",
3
3
  "workspaces": ["packages/*"],
4
- "version": "0.51.0",
4
+ "version": "0.51.2",
5
5
  "description": "Batteries-included agent harness for Claude Code",
6
6
  "type": "module",
7
7
  "bin": {
@@ -21,6 +21,22 @@ if [ -f "$ENV_STATUS" ]; then
21
21
  fi
22
22
  fi
23
23
 
24
+ # Batch context detection: check for workflow or release-plan state
25
+ BATCH_ISSUES=0
26
+ # Use wildcard to match any workflow name: /tmp/.claude-workflow-*-${PPID}.json
27
+ WORKFLOW_FILE=$(ls /tmp/.claude-workflow-*-"${PPID}".json 2>/dev/null | head -1 || true)
28
+ if [ -n "$WORKFLOW_FILE" ] && [ -f "$WORKFLOW_FILE" ]; then
29
+ BATCH_ISSUES=$(jq -r '.issue_count // 0' "$WORKFLOW_FILE" 2>/dev/null || echo 0)
30
+ fi
31
+
32
+ # Also check release-plan context (existence only — if file exists, treat as batch)
33
+ RELEASE_PLAN="/tmp/.claude-release-plan-${PPID}"
34
+ if [ -f "$RELEASE_PLAN" ]; then
35
+ if [ "$BATCH_ISSUES" -lt 3 ]; then
36
+ BATCH_ISSUES=3
37
+ fi
38
+ fi
39
+
24
40
  # Extract task info from input
25
41
  agent_type=$(echo "$input" | jq -r '.tool_input.subagent_type // "unknown"')
26
42
  prompt_preview=$(echo "$input" | jq -r '.tool_input.description // ""' | head -c 60)
@@ -37,8 +53,14 @@ else
37
53
  fi
38
54
  echo "$COUNT" > "$COUNTER_FILE"
39
55
 
40
- # Warn from 2nd Task call onward -- Agent Teams may be more appropriate
41
- if [ "$COUNT" -ge 2 ]; then
56
+ # Warn when batch context detected (even on first call) or from 2nd call onward
57
+ if [ "$BATCH_ISSUES" -ge 3 ] && [ "$COUNT" -eq 1 ]; then
58
+ echo "" >&2
59
+ echo "--- [R018 Advisor] Batch context detected (${BATCH_ISSUES} issues) ---" >&2
60
+ echo " RECOMMENDATION: Use Agent Teams (TeamCreate) for this batch." >&2
61
+ echo " Current: Agent(${agent_type}) -- ${prompt_preview}" >&2
62
+ echo "-----------------------------------------------------------" >&2
63
+ elif [ "$COUNT" -ge 2 ]; then
42
64
  echo "" >&2
43
65
  echo "--- [R018 Advisor] Agent/Task tool call #${COUNT} in this session ---" >&2
44
66
  echo " WARNING: Multiple Task calls detected. Consider Agent Teams if:" >&2
@@ -140,7 +140,7 @@ project/
140
140
  | +-- rules/ # 전역 규칙 (R000-R021)
141
141
  | +-- hooks/ # 훅 스크립트 (보안, 검증, HUD)
142
142
  | +-- contexts/ # 컨텍스트 파일 (ecomode)
143
- +-- guides/ # 레퍼런스 문서 (29 토픽)
143
+ +-- guides/ # 레퍼런스 문서 (30 토픽)
144
144
  ```
145
145
 
146
146
  ## 오케스트레이션
@@ -0,0 +1,69 @@
1
+ # Drizzle ORM: sql Template Literal Pitfalls
2
+
3
+ ## The Bug: Column References in Subqueries
4
+
5
+ When using Drizzle ORM's `sql` template literals, `${table.column}` generates a **bare column name without the table qualifier**. This causes silent semantic errors inside aliased subqueries.
6
+
7
+ ### Symptom
8
+
9
+ ```typescript
10
+ // Code
11
+ sql`SELECT ${agentInvocations.errorSummary} as sub_es
12
+ FROM ${agentInvocations} AS ai2
13
+ WHERE ai2.agent_type = ${agentInvocations.agentType}`
14
+
15
+ // Generated SQL (WRONG)
16
+ SELECT "error_summary" as sub_es
17
+ FROM "agent_invocations" AS ai2
18
+ WHERE ai2.agent_type = "agent_type" -- "agent_type" becomes a literal string, always true!
19
+ ```
20
+
21
+ `${agentInvocations.agentType}` expands to the **quoted column name** `"agent_type"` — not the value of the column. The `WHERE` clause compares `ai2.agent_type = "agent_type"`, which SQLite treats as a string literal match — always true for rows where `agent_type` equals the string `"agent_type"`.
22
+
23
+ ### Why Reviewers Miss It
24
+
25
+ - The code *looks* correct — you see `agentInvocations.agentType` and assume it's a column reference.
26
+ - Drizzle's `${table.column}` syntax works fine in top-level queries where table context is unambiguous.
27
+ - The bug only manifests inside subqueries with table aliases (`AS ai2`) — normal queries pass.
28
+ - No compile-time error; the SQL executes but returns wrong results.
29
+
30
+ ## The Fix: Raw SQL for Subquery Internal References
31
+
32
+ Use raw SQL strings for column references *inside* aliased subqueries. Reserve `${table.column}` only for Drizzle's top-level query builder where it resolves correctly.
33
+
34
+ ```typescript
35
+ // CORRECT: raw SQL column references inside aliased subquery
36
+ sql`SELECT ai2.error_summary as sub_es
37
+ FROM ${agentInvocations} AS ai2
38
+ WHERE ai2.agent_type = ${agentInvocations}.agent_type`
39
+ ```
40
+
41
+ Note: `${agentInvocations}` (the table object itself) still correctly expands to the table name and is safe to use for the `FROM` clause. Only *column* references inside subqueries must be written as raw SQL.
42
+
43
+ ## Decision Table
44
+
45
+ | Context | Pattern | Safe? |
46
+ |---------|---------|-------|
47
+ | Top-level `FROM` clause | `${table}` | ✅ Yes |
48
+ | Top-level `WHERE` with parameterized value | `${value}` | ✅ Yes (auto-parameterized) |
49
+ | Top-level `SELECT` column | `${table.column}` | ✅ Yes |
50
+ | Inside aliased subquery `SELECT` | `${table.column}` | ❌ No — bare column name |
51
+ | Inside aliased subquery `WHERE` comparison | `${table.column}` | ❌ No — string literal, not column ref |
52
+ | Inside aliased subquery (fixed) | `alias.column_name` | ✅ Yes |
53
+
54
+ ## Verification
55
+
56
+ Use `.toSQL()` to inspect generated SQL before running:
57
+
58
+ ```typescript
59
+ const query = sql`SELECT ${agentInvocations.errorSummary} as sub_es
60
+ FROM ${agentInvocations} AS ai2
61
+ WHERE ai2.agent_type = ${agentInvocations.agentType}`
62
+
63
+ console.log(query.toSQL())
64
+ // Reveals the bare column names — catches the bug before runtime
65
+ ```
66
+
67
+ ## Key Takeaway
68
+
69
+ > **`${table.column}` in Drizzle's `sql` template generates a bare column identifier, not a qualified reference.** Inside aliased subqueries, this breaks table-qualified comparisons. Always use raw `alias.column_name` strings inside subquery bodies.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.51.0",
2
+ "version": "0.51.2",
3
3
  "lastUpdated": "2026-03-16T00:00:00.000Z",
4
4
  "components": [
5
5
  {
@@ -24,7 +24,7 @@
24
24
  "name": "guides",
25
25
  "path": "guides",
26
26
  "description": "Reference documentation",
27
- "files": 29
27
+ "files": 30
28
28
  },
29
29
  {
30
30
  "name": "hooks",