From 7b8204924acbf9b1e0d652e19a738eed3f37703c Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Wed, 4 Feb 2026 15:04:49 +0900 Subject: [PATCH 1/6] feat(config): update task config schema for global storage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Make storage_path truly optional (remove default) - Add task_list_id as config alternative to env var - Fix build-schema.ts to use zodToJsonSchema 🤖 Generated with assistance of OhMyOpenCode --- assets/oh-my-opencode.schema.json | 2460 ++--------------------------- script/build-schema.ts | 6 +- src/config/schema.ts | 6 +- 3 files changed, 133 insertions(+), 2339 deletions(-) diff --git a/assets/oh-my-opencode.schema.json b/assets/oh-my-opencode.schema.json index c562bdad..809b7db7 100644 --- a/assets/oh-my-opencode.schema.json +++ b/assets/oh-my-opencode.schema.json @@ -150,9 +150,6 @@ }, "tools": { "type": "object", - "propertyNames": { - "type": "string" - }, "additionalProperties": { "type": "boolean" } @@ -189,54 +186,27 @@ "bash": { "anyOf": [ { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] + "$ref": "#/properties/agents/properties/build/properties/permission/properties/edit" }, { "type": "object", - "propertyNames": { - "type": "string" - }, "additionalProperties": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] + "$ref": "#/properties/agents/properties/build/properties/permission/properties/edit" } } ] }, "webfetch": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] + "$ref": "#/properties/agents/properties/build/properties/permission/properties/edit" }, "doom_loop": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] + "$ref": "#/properties/agents/properties/build/properties/permission/properties/edit" }, "external_directory": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] + "$ref": "#/properties/agents/properties/build/properties/permission/properties/edit" } - } + }, + "additionalProperties": false }, "maxTokens": { "type": "number" @@ -257,7 +227,8 @@ }, "required": [ "type" - ] + ], + "additionalProperties": false }, "reasoningEffort": { "type": "string", @@ -278,2243 +249,55 @@ }, "providerOptions": { "type": "object", - "propertyNames": { - "type": "string" - }, "additionalProperties": {} } - } + }, + "additionalProperties": false }, "plan": { - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "variant": { - "type": "string" - }, - "category": { - "type": "string" - }, - "skills": { - "type": "array", - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number", - "minimum": 0, - "maximum": 2 - }, - "top_p": { - "type": "number", - "minimum": 0, - "maximum": 1 - }, - "prompt": { - "type": "string" - }, - "prompt_append": { - "type": "string" - }, - "tools": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "boolean" - } - }, - "disable": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "mode": { - "type": "string", - "enum": [ - "subagent", - "primary", - "all" - ] - }, - "color": { - "type": "string", - "pattern": "^#[0-9A-Fa-f]{6}$" - }, - "permission": { - "type": "object", - "properties": { - "edit": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "bash": { - "anyOf": [ - { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - ] - }, - "webfetch": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "doom_loop": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "external_directory": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - }, - "maxTokens": { - "type": "number" - }, - "thinking": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "enabled", - "disabled" - ] - }, - "budgetTokens": { - "type": "number" - } - }, - "required": [ - "type" - ] - }, - "reasoningEffort": { - "type": "string", - "enum": [ - "low", - "medium", - "high", - "xhigh" - ] - }, - "textVerbosity": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ] - }, - "providerOptions": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": {} - } - } + "$ref": "#/properties/agents/properties/build" }, "sisyphus": { - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "variant": { - "type": "string" - }, - "category": { - "type": "string" - }, - "skills": { - "type": "array", - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number", - "minimum": 0, - "maximum": 2 - }, - "top_p": { - "type": "number", - "minimum": 0, - "maximum": 1 - }, - "prompt": { - "type": "string" - }, - "prompt_append": { - "type": "string" - }, - "tools": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "boolean" - } - }, - "disable": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "mode": { - "type": "string", - "enum": [ - "subagent", - "primary", - "all" - ] - }, - "color": { - "type": "string", - "pattern": "^#[0-9A-Fa-f]{6}$" - }, - "permission": { - "type": "object", - "properties": { - "edit": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "bash": { - "anyOf": [ - { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - ] - }, - "webfetch": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "doom_loop": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "external_directory": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - }, - "maxTokens": { - "type": "number" - }, - "thinking": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "enabled", - "disabled" - ] - }, - "budgetTokens": { - "type": "number" - } - }, - "required": [ - "type" - ] - }, - "reasoningEffort": { - "type": "string", - "enum": [ - "low", - "medium", - "high", - "xhigh" - ] - }, - "textVerbosity": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ] - }, - "providerOptions": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": {} - } - } + "$ref": "#/properties/agents/properties/build" }, "hephaestus": { - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "variant": { - "type": "string" - }, - "category": { - "type": "string" - }, - "skills": { - "type": "array", - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number", - "minimum": 0, - "maximum": 2 - }, - "top_p": { - "type": "number", - "minimum": 0, - "maximum": 1 - }, - "prompt": { - "type": "string" - }, - "prompt_append": { - "type": "string" - }, - "tools": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "boolean" - } - }, - "disable": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "mode": { - "type": "string", - "enum": [ - "subagent", - "primary", - "all" - ] - }, - "color": { - "type": "string", - "pattern": "^#[0-9A-Fa-f]{6}$" - }, - "permission": { - "type": "object", - "properties": { - "edit": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "bash": { - "anyOf": [ - { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - ] - }, - "webfetch": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "doom_loop": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "external_directory": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - }, - "maxTokens": { - "type": "number" - }, - "thinking": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "enabled", - "disabled" - ] - }, - "budgetTokens": { - "type": "number" - } - }, - "required": [ - "type" - ] - }, - "reasoningEffort": { - "type": "string", - "enum": [ - "low", - "medium", - "high", - "xhigh" - ] - }, - "textVerbosity": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ] - }, - "providerOptions": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": {} - } - } + "$ref": "#/properties/agents/properties/build" }, "sisyphus-junior": { - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "variant": { - "type": "string" - }, - "category": { - "type": "string" - }, - "skills": { - "type": "array", - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number", - "minimum": 0, - "maximum": 2 - }, - "top_p": { - "type": "number", - "minimum": 0, - "maximum": 1 - }, - "prompt": { - "type": "string" - }, - "prompt_append": { - "type": "string" - }, - "tools": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "boolean" - } - }, - "disable": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "mode": { - "type": "string", - "enum": [ - "subagent", - "primary", - "all" - ] - }, - "color": { - "type": "string", - "pattern": "^#[0-9A-Fa-f]{6}$" - }, - "permission": { - "type": "object", - "properties": { - "edit": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "bash": { - "anyOf": [ - { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - ] - }, - "webfetch": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "doom_loop": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "external_directory": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - }, - "maxTokens": { - "type": "number" - }, - "thinking": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "enabled", - "disabled" - ] - }, - "budgetTokens": { - "type": "number" - } - }, - "required": [ - "type" - ] - }, - "reasoningEffort": { - "type": "string", - "enum": [ - "low", - "medium", - "high", - "xhigh" - ] - }, - "textVerbosity": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ] - }, - "providerOptions": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": {} - } - } + "$ref": "#/properties/agents/properties/build" }, "OpenCode-Builder": { - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "variant": { - "type": "string" - }, - "category": { - "type": "string" - }, - "skills": { - "type": "array", - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number", - "minimum": 0, - "maximum": 2 - }, - "top_p": { - "type": "number", - "minimum": 0, - "maximum": 1 - }, - "prompt": { - "type": "string" - }, - "prompt_append": { - "type": "string" - }, - "tools": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "boolean" - } - }, - "disable": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "mode": { - "type": "string", - "enum": [ - "subagent", - "primary", - "all" - ] - }, - "color": { - "type": "string", - "pattern": "^#[0-9A-Fa-f]{6}$" - }, - "permission": { - "type": "object", - "properties": { - "edit": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "bash": { - "anyOf": [ - { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - ] - }, - "webfetch": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "doom_loop": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "external_directory": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - }, - "maxTokens": { - "type": "number" - }, - "thinking": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "enabled", - "disabled" - ] - }, - "budgetTokens": { - "type": "number" - } - }, - "required": [ - "type" - ] - }, - "reasoningEffort": { - "type": "string", - "enum": [ - "low", - "medium", - "high", - "xhigh" - ] - }, - "textVerbosity": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ] - }, - "providerOptions": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": {} - } - } + "$ref": "#/properties/agents/properties/build" }, "prometheus": { - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "variant": { - "type": "string" - }, - "category": { - "type": "string" - }, - "skills": { - "type": "array", - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number", - "minimum": 0, - "maximum": 2 - }, - "top_p": { - "type": "number", - "minimum": 0, - "maximum": 1 - }, - "prompt": { - "type": "string" - }, - "prompt_append": { - "type": "string" - }, - "tools": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "boolean" - } - }, - "disable": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "mode": { - "type": "string", - "enum": [ - "subagent", - "primary", - "all" - ] - }, - "color": { - "type": "string", - "pattern": "^#[0-9A-Fa-f]{6}$" - }, - "permission": { - "type": "object", - "properties": { - "edit": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "bash": { - "anyOf": [ - { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - ] - }, - "webfetch": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "doom_loop": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "external_directory": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - }, - "maxTokens": { - "type": "number" - }, - "thinking": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "enabled", - "disabled" - ] - }, - "budgetTokens": { - "type": "number" - } - }, - "required": [ - "type" - ] - }, - "reasoningEffort": { - "type": "string", - "enum": [ - "low", - "medium", - "high", - "xhigh" - ] - }, - "textVerbosity": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ] - }, - "providerOptions": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": {} - } - } + "$ref": "#/properties/agents/properties/build" }, "metis": { - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "variant": { - "type": "string" - }, - "category": { - "type": "string" - }, - "skills": { - "type": "array", - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number", - "minimum": 0, - "maximum": 2 - }, - "top_p": { - "type": "number", - "minimum": 0, - "maximum": 1 - }, - "prompt": { - "type": "string" - }, - "prompt_append": { - "type": "string" - }, - "tools": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "boolean" - } - }, - "disable": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "mode": { - "type": "string", - "enum": [ - "subagent", - "primary", - "all" - ] - }, - "color": { - "type": "string", - "pattern": "^#[0-9A-Fa-f]{6}$" - }, - "permission": { - "type": "object", - "properties": { - "edit": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "bash": { - "anyOf": [ - { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - ] - }, - "webfetch": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "doom_loop": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "external_directory": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - }, - "maxTokens": { - "type": "number" - }, - "thinking": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "enabled", - "disabled" - ] - }, - "budgetTokens": { - "type": "number" - } - }, - "required": [ - "type" - ] - }, - "reasoningEffort": { - "type": "string", - "enum": [ - "low", - "medium", - "high", - "xhigh" - ] - }, - "textVerbosity": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ] - }, - "providerOptions": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": {} - } - } + "$ref": "#/properties/agents/properties/build" }, "momus": { - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "variant": { - "type": "string" - }, - "category": { - "type": "string" - }, - "skills": { - "type": "array", - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number", - "minimum": 0, - "maximum": 2 - }, - "top_p": { - "type": "number", - "minimum": 0, - "maximum": 1 - }, - "prompt": { - "type": "string" - }, - "prompt_append": { - "type": "string" - }, - "tools": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "boolean" - } - }, - "disable": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "mode": { - "type": "string", - "enum": [ - "subagent", - "primary", - "all" - ] - }, - "color": { - "type": "string", - "pattern": "^#[0-9A-Fa-f]{6}$" - }, - "permission": { - "type": "object", - "properties": { - "edit": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "bash": { - "anyOf": [ - { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - ] - }, - "webfetch": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "doom_loop": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "external_directory": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - }, - "maxTokens": { - "type": "number" - }, - "thinking": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "enabled", - "disabled" - ] - }, - "budgetTokens": { - "type": "number" - } - }, - "required": [ - "type" - ] - }, - "reasoningEffort": { - "type": "string", - "enum": [ - "low", - "medium", - "high", - "xhigh" - ] - }, - "textVerbosity": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ] - }, - "providerOptions": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": {} - } - } + "$ref": "#/properties/agents/properties/build" }, "oracle": { - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "variant": { - "type": "string" - }, - "category": { - "type": "string" - }, - "skills": { - "type": "array", - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number", - "minimum": 0, - "maximum": 2 - }, - "top_p": { - "type": "number", - "minimum": 0, - "maximum": 1 - }, - "prompt": { - "type": "string" - }, - "prompt_append": { - "type": "string" - }, - "tools": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "boolean" - } - }, - "disable": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "mode": { - "type": "string", - "enum": [ - "subagent", - "primary", - "all" - ] - }, - "color": { - "type": "string", - "pattern": "^#[0-9A-Fa-f]{6}$" - }, - "permission": { - "type": "object", - "properties": { - "edit": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "bash": { - "anyOf": [ - { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - ] - }, - "webfetch": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "doom_loop": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "external_directory": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - }, - "maxTokens": { - "type": "number" - }, - "thinking": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "enabled", - "disabled" - ] - }, - "budgetTokens": { - "type": "number" - } - }, - "required": [ - "type" - ] - }, - "reasoningEffort": { - "type": "string", - "enum": [ - "low", - "medium", - "high", - "xhigh" - ] - }, - "textVerbosity": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ] - }, - "providerOptions": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": {} - } - } + "$ref": "#/properties/agents/properties/build" }, "librarian": { - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "variant": { - "type": "string" - }, - "category": { - "type": "string" - }, - "skills": { - "type": "array", - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number", - "minimum": 0, - "maximum": 2 - }, - "top_p": { - "type": "number", - "minimum": 0, - "maximum": 1 - }, - "prompt": { - "type": "string" - }, - "prompt_append": { - "type": "string" - }, - "tools": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "boolean" - } - }, - "disable": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "mode": { - "type": "string", - "enum": [ - "subagent", - "primary", - "all" - ] - }, - "color": { - "type": "string", - "pattern": "^#[0-9A-Fa-f]{6}$" - }, - "permission": { - "type": "object", - "properties": { - "edit": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "bash": { - "anyOf": [ - { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - ] - }, - "webfetch": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "doom_loop": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "external_directory": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - }, - "maxTokens": { - "type": "number" - }, - "thinking": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "enabled", - "disabled" - ] - }, - "budgetTokens": { - "type": "number" - } - }, - "required": [ - "type" - ] - }, - "reasoningEffort": { - "type": "string", - "enum": [ - "low", - "medium", - "high", - "xhigh" - ] - }, - "textVerbosity": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ] - }, - "providerOptions": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": {} - } - } + "$ref": "#/properties/agents/properties/build" }, "explore": { - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "variant": { - "type": "string" - }, - "category": { - "type": "string" - }, - "skills": { - "type": "array", - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number", - "minimum": 0, - "maximum": 2 - }, - "top_p": { - "type": "number", - "minimum": 0, - "maximum": 1 - }, - "prompt": { - "type": "string" - }, - "prompt_append": { - "type": "string" - }, - "tools": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "boolean" - } - }, - "disable": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "mode": { - "type": "string", - "enum": [ - "subagent", - "primary", - "all" - ] - }, - "color": { - "type": "string", - "pattern": "^#[0-9A-Fa-f]{6}$" - }, - "permission": { - "type": "object", - "properties": { - "edit": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "bash": { - "anyOf": [ - { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - ] - }, - "webfetch": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "doom_loop": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "external_directory": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - }, - "maxTokens": { - "type": "number" - }, - "thinking": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "enabled", - "disabled" - ] - }, - "budgetTokens": { - "type": "number" - } - }, - "required": [ - "type" - ] - }, - "reasoningEffort": { - "type": "string", - "enum": [ - "low", - "medium", - "high", - "xhigh" - ] - }, - "textVerbosity": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ] - }, - "providerOptions": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": {} - } - } + "$ref": "#/properties/agents/properties/build" }, "multimodal-looker": { - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "variant": { - "type": "string" - }, - "category": { - "type": "string" - }, - "skills": { - "type": "array", - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number", - "minimum": 0, - "maximum": 2 - }, - "top_p": { - "type": "number", - "minimum": 0, - "maximum": 1 - }, - "prompt": { - "type": "string" - }, - "prompt_append": { - "type": "string" - }, - "tools": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "boolean" - } - }, - "disable": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "mode": { - "type": "string", - "enum": [ - "subagent", - "primary", - "all" - ] - }, - "color": { - "type": "string", - "pattern": "^#[0-9A-Fa-f]{6}$" - }, - "permission": { - "type": "object", - "properties": { - "edit": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "bash": { - "anyOf": [ - { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - ] - }, - "webfetch": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "doom_loop": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "external_directory": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - }, - "maxTokens": { - "type": "number" - }, - "thinking": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "enabled", - "disabled" - ] - }, - "budgetTokens": { - "type": "number" - } - }, - "required": [ - "type" - ] - }, - "reasoningEffort": { - "type": "string", - "enum": [ - "low", - "medium", - "high", - "xhigh" - ] - }, - "textVerbosity": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ] - }, - "providerOptions": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": {} - } - } + "$ref": "#/properties/agents/properties/build" }, "atlas": { - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "variant": { - "type": "string" - }, - "category": { - "type": "string" - }, - "skills": { - "type": "array", - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number", - "minimum": 0, - "maximum": 2 - }, - "top_p": { - "type": "number", - "minimum": 0, - "maximum": 1 - }, - "prompt": { - "type": "string" - }, - "prompt_append": { - "type": "string" - }, - "tools": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "boolean" - } - }, - "disable": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "mode": { - "type": "string", - "enum": [ - "subagent", - "primary", - "all" - ] - }, - "color": { - "type": "string", - "pattern": "^#[0-9A-Fa-f]{6}$" - }, - "permission": { - "type": "object", - "properties": { - "edit": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "bash": { - "anyOf": [ - { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - ] - }, - "webfetch": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "doom_loop": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "external_directory": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - } - } - }, - "maxTokens": { - "type": "number" - }, - "thinking": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "enabled", - "disabled" - ] - }, - "budgetTokens": { - "type": "number" - } - }, - "required": [ - "type" - ] - }, - "reasoningEffort": { - "type": "string", - "enum": [ - "low", - "medium", - "high", - "xhigh" - ] - }, - "textVerbosity": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ] - }, - "providerOptions": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": {} - } - } + "$ref": "#/properties/agents/properties/build" } - } + }, + "additionalProperties": false }, "categories": { "type": "object", - "propertyNames": { - "type": "string" - }, "additionalProperties": { "type": "object", "properties": { @@ -2556,7 +339,8 @@ }, "required": [ "type" - ] + ], + "additionalProperties": false }, "reasoningEffort": { "type": "string", @@ -2577,9 +361,6 @@ }, "tools": { "type": "object", - "propertyNames": { - "type": "string" - }, "additionalProperties": { "type": "boolean" } @@ -2590,7 +371,8 @@ "is_unstable_agent": { "type": "boolean" } - } + }, + "additionalProperties": false } }, "claude_code": { @@ -2616,14 +398,12 @@ }, "plugins_override": { "type": "object", - "propertyNames": { - "type": "string" - }, "additionalProperties": { "type": "boolean" } } - } + }, + "additionalProperties": false }, "sisyphus_agent": { "type": "object", @@ -2640,7 +420,8 @@ "replace_plan": { "type": "boolean" } - } + }, + "additionalProperties": false }, "comment_checker": { "type": "object", @@ -2648,7 +429,8 @@ "custom_prompt": { "type": "string" } - } + }, + "additionalProperties": false }, "experimental": { "type": "object", @@ -2669,34 +451,39 @@ "type": "object", "properties": { "enabled": { - "default": false, - "type": "boolean" + "type": "boolean", + "default": false }, "notification": { - "default": "detailed", "type": "string", "enum": [ "off", "minimal", "detailed" - ] + ], + "default": "detailed" }, "turn_protection": { "type": "object", "properties": { "enabled": { - "default": true, - "type": "boolean" + "type": "boolean", + "default": true }, "turns": { - "default": 3, "type": "number", "minimum": 1, - "maximum": 10 + "maximum": 10, + "default": 3 } - } + }, + "additionalProperties": false }, "protected_tools": { + "type": "array", + "items": { + "type": "string" + }, "default": [ "task", "todowrite", @@ -2705,11 +492,7 @@ "session_read", "session_write", "session_search" - ], - "type": "array", - "items": { - "type": "string" - } + ] }, "strategies": { "type": "object", @@ -2718,47 +501,53 @@ "type": "object", "properties": { "enabled": { - "default": true, - "type": "boolean" + "type": "boolean", + "default": true } - } + }, + "additionalProperties": false }, "supersede_writes": { "type": "object", "properties": { "enabled": { - "default": true, - "type": "boolean" + "type": "boolean", + "default": true }, "aggressive": { - "default": false, - "type": "boolean" + "type": "boolean", + "default": false } - } + }, + "additionalProperties": false }, "purge_errors": { "type": "object", "properties": { "enabled": { - "default": true, - "type": "boolean" + "type": "boolean", + "default": true }, "turns": { - "default": 5, "type": "number", "minimum": 1, - "maximum": 20 + "maximum": 20, + "default": 5 } - } + }, + "additionalProperties": false } - } + }, + "additionalProperties": false } - } + }, + "additionalProperties": false }, "task_system": { "type": "boolean" } - } + }, + "additionalProperties": false }, "auto_update": { "type": "boolean" @@ -2775,9 +564,6 @@ "allOf": [ { "type": "object", - "propertyNames": { - "type": "string" - }, "additionalProperties": { "anyOf": [ { @@ -2815,9 +601,6 @@ }, "metadata": { "type": "object", - "propertyNames": { - "type": "string" - }, "additionalProperties": {} }, "allowed-tools": { @@ -2829,7 +612,8 @@ "disable": { "type": "boolean" } - } + }, + "additionalProperties": false } ] } @@ -2859,7 +643,8 @@ }, "required": [ "path" - ] + ], + "additionalProperties": false } ] } @@ -2886,19 +671,20 @@ "type": "object", "properties": { "enabled": { - "default": false, - "type": "boolean" + "type": "boolean", + "default": false }, "default_max_iterations": { - "default": 100, "type": "number", "minimum": 1, - "maximum": 1000 + "maximum": 1000, + "default": 100 }, "state_dir": { "type": "string" } - } + }, + "additionalProperties": false }, "background_task": { "type": "object", @@ -2909,9 +695,6 @@ }, "providerConcurrency": { "type": "object", - "propertyNames": { - "type": "string" - }, "additionalProperties": { "type": "number", "minimum": 0 @@ -2919,9 +702,6 @@ }, "modelConcurrency": { "type": "object", - "propertyNames": { - "type": "string" - }, "additionalProperties": { "type": "number", "minimum": 0 @@ -2931,7 +711,8 @@ "type": "number", "minimum": 60000 } - } + }, + "additionalProperties": false }, "notification": { "type": "object", @@ -2939,43 +720,47 @@ "force_enable": { "type": "boolean" } - } + }, + "additionalProperties": false }, "babysitting": { "type": "object", "properties": { "timeout_ms": { - "default": 120000, - "type": "number" + "type": "number", + "default": 120000 } - } + }, + "additionalProperties": false }, "git_master": { "type": "object", "properties": { "commit_footer": { - "default": true, - "type": "boolean" + "type": "boolean", + "default": true }, "include_co_authored_by": { - "default": true, - "type": "boolean" + "type": "boolean", + "default": true } - } + }, + "additionalProperties": false }, "browser_automation_engine": { "type": "object", "properties": { "provider": { - "default": "playwright", "type": "string", "enum": [ "playwright", "agent-browser", "dev-browser" - ] + ], + "default": "playwright" } - } + }, + "additionalProperties": false }, "websearch": { "type": "object", @@ -2987,17 +772,17 @@ "tavily" ] } - } + }, + "additionalProperties": false }, "tmux": { "type": "object", "properties": { "enabled": { - "default": false, - "type": "boolean" + "type": "boolean", + "default": false }, "layout": { - "default": "main-vertical", "type": "string", "enum": [ "main-horizontal", @@ -3005,25 +790,27 @@ "tiled", "even-horizontal", "even-vertical" - ] + ], + "default": "main-vertical" }, "main_pane_size": { - "default": 60, "type": "number", "minimum": 20, - "maximum": 80 + "maximum": 80, + "default": 60 }, "main_pane_min_width": { - "default": 120, "type": "number", - "minimum": 40 + "minimum": 40, + "default": 120 }, "agent_pane_min_width": { - "default": 40, "type": "number", - "minimum": 20 + "minimum": 20, + "default": 40 } - } + }, + "additionalProperties": false }, "sisyphus": { "type": "object", @@ -3032,16 +819,21 @@ "type": "object", "properties": { "storage_path": { - "default": ".sisyphus/tasks", + "type": "string" + }, + "task_list_id": { "type": "string" }, "claude_code_compat": { - "default": false, - "type": "boolean" + "type": "boolean", + "default": false } - } + }, + "additionalProperties": false } - } + }, + "additionalProperties": false } - } + }, + "additionalProperties": false } \ No newline at end of file diff --git a/script/build-schema.ts b/script/build-schema.ts index e2b0aa66..d0ed70d3 100644 --- a/script/build-schema.ts +++ b/script/build-schema.ts @@ -1,5 +1,6 @@ #!/usr/bin/env bun import * as z from "zod" +import { zodToJsonSchema } from "zod-to-json-schema" import { OhMyOpenCodeConfigSchema } from "../src/config/schema" const SCHEMA_OUTPUT_PATH = "assets/oh-my-opencode.schema.json" @@ -7,9 +8,8 @@ const SCHEMA_OUTPUT_PATH = "assets/oh-my-opencode.schema.json" async function main() { console.log("Generating JSON Schema...") - const jsonSchema = z.toJSONSchema(OhMyOpenCodeConfigSchema, { - io: "input", - target: "draft-7", + const jsonSchema = zodToJsonSchema(OhMyOpenCodeConfigSchema, { + target: "draft7", }) const finalSchema = { diff --git a/src/config/schema.ts b/src/config/schema.ts index d0aca627..b7441055 100644 --- a/src/config/schema.ts +++ b/src/config/schema.ts @@ -368,8 +368,10 @@ export const TmuxConfigSchema = z.object({ }) export const SisyphusTasksConfigSchema = z.object({ - /** Storage path for tasks (default: .sisyphus/tasks) */ - storage_path: z.string().default(".sisyphus/tasks"), + /** Absolute or relative storage path override. When set, bypasses global config dir. */ + storage_path: z.string().optional(), + /** Force task list ID (alternative to env ULTRAWORK_TASK_LIST_ID) */ + task_list_id: z.string().optional(), /** Enable Claude Code path compatibility mode */ claude_code_compat: z.boolean().default(false), }) From bf31e7289e5346babb96eb6bcbccd22cea198800 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Wed, 4 Feb 2026 15:08:06 +0900 Subject: [PATCH 2/6] feat(tasks): migrate storage to global config dir with ULTRAWORK_TASK_LIST_ID support --- src/features/claude-tasks/storage.test.ts | 135 ++++++++++++++++++++-- src/features/claude-tasks/storage.ts | 28 ++++- 2 files changed, 152 insertions(+), 11 deletions(-) diff --git a/src/features/claude-tasks/storage.test.ts b/src/features/claude-tasks/storage.test.ts index 9fbc9b4a..8ceda380 100644 --- a/src/features/claude-tasks/storage.test.ts +++ b/src/features/claude-tasks/storage.test.ts @@ -1,26 +1,99 @@ import { describe, test, expect, beforeEach, afterEach } from "bun:test" import { existsSync, mkdirSync, rmSync, writeFileSync } from "fs" -import { join } from "path" +import { join, basename } from "path" import { z } from "zod" -import { getTaskDir, readJsonSafe, writeJsonAtomic, acquireLock, generateTaskId, listTaskFiles } from "./storage" +import { getOpenCodeConfigDir } from "../../shared/opencode-config-dir" +import { + getTaskDir, + readJsonSafe, + writeJsonAtomic, + acquireLock, + generateTaskId, + listTaskFiles, + resolveTaskListId, + sanitizePathSegment, +} from "./storage" import type { OhMyOpenCodeConfig } from "../../config/schema" const TEST_DIR = ".test-claude-tasks" const TEST_DIR_ABS = join(process.cwd(), TEST_DIR) describe("getTaskDir", () => { - test("returns correct path for default config", () => { + const originalTaskListId = process.env.ULTRAWORK_TASK_LIST_ID + + beforeEach(() => { + if (originalTaskListId === undefined) { + delete process.env.ULTRAWORK_TASK_LIST_ID + } else { + process.env.ULTRAWORK_TASK_LIST_ID = originalTaskListId + } + }) + + afterEach(() => { + if (originalTaskListId === undefined) { + delete process.env.ULTRAWORK_TASK_LIST_ID + } else { + process.env.ULTRAWORK_TASK_LIST_ID = originalTaskListId + } + }) + + test("returns global config path for default config", () => { //#given const config: Partial = {} + const configDir = getOpenCodeConfigDir({ binary: "opencode" }) + const expectedListId = sanitizePathSegment(basename(process.cwd())) //#when const result = getTaskDir(config) //#then - expect(result).toBe(join(process.cwd(), ".sisyphus/tasks")) + expect(result).toBe(join(configDir, "tasks", expectedListId)) }) - test("returns correct path with custom storage_path", () => { + test("respects ULTRAWORK_TASK_LIST_ID env var", () => { + //#given + process.env.ULTRAWORK_TASK_LIST_ID = "custom list/id" + const configDir = getOpenCodeConfigDir({ binary: "opencode" }) + + //#when + const result = getTaskDir() + + //#then + expect(result).toBe(join(configDir, "tasks", "custom-list-id")) + }) + + test("falls back to sanitized cwd basename when env var not set", () => { + //#given + delete process.env.ULTRAWORK_TASK_LIST_ID + const configDir = getOpenCodeConfigDir({ binary: "opencode" }) + const expectedListId = sanitizePathSegment(basename(process.cwd())) + + //#when + const result = getTaskDir() + + //#then + expect(result).toBe(join(configDir, "tasks", expectedListId)) + }) + + test("returns absolute storage_path without joining cwd", () => { + //#given + const config: Partial = { + sisyphus: { + tasks: { + storage_path: "/tmp/custom-task-path", + claude_code_compat: false, + }, + }, + } + + //#when + const result = getTaskDir(config) + + //#then + expect(result).toBe("/tmp/custom-task-path") + }) + + test("joins relative storage_path with cwd", () => { //#given const config: Partial = { sisyphus: { @@ -37,13 +110,59 @@ describe("getTaskDir", () => { //#then expect(result).toBe(join(process.cwd(), ".custom/tasks")) }) +}) + +describe("resolveTaskListId", () => { + const originalTaskListId = process.env.ULTRAWORK_TASK_LIST_ID + + beforeEach(() => { + if (originalTaskListId === undefined) { + delete process.env.ULTRAWORK_TASK_LIST_ID + } else { + process.env.ULTRAWORK_TASK_LIST_ID = originalTaskListId + } + }) + + afterEach(() => { + if (originalTaskListId === undefined) { + delete process.env.ULTRAWORK_TASK_LIST_ID + } else { + process.env.ULTRAWORK_TASK_LIST_ID = originalTaskListId + } + }) + + test("returns env var when set", () => { + //#given + process.env.ULTRAWORK_TASK_LIST_ID = "custom-list" - test("returns correct path with default config parameter", () => { //#when - const result = getTaskDir() + const result = resolveTaskListId() //#then - expect(result).toBe(join(process.cwd(), ".sisyphus/tasks")) + expect(result).toBe("custom-list") + }) + + test("sanitizes special characters", () => { + //#given + process.env.ULTRAWORK_TASK_LIST_ID = "custom list/id" + + //#when + const result = resolveTaskListId() + + //#then + expect(result).toBe("custom-list-id") + }) + + test("returns sanitized cwd basename when env var not set", () => { + //#given + delete process.env.ULTRAWORK_TASK_LIST_ID + const expected = sanitizePathSegment(basename(process.cwd())) + + //#when + const result = resolveTaskListId() + + //#then + expect(result).toBe(expected) }) }) diff --git a/src/features/claude-tasks/storage.ts b/src/features/claude-tasks/storage.ts index e889c1df..b51ad417 100644 --- a/src/features/claude-tasks/storage.ts +++ b/src/features/claude-tasks/storage.ts @@ -1,13 +1,35 @@ -import { join, dirname } from "path" +import { join, dirname, basename } from "path" import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync, unlinkSync, readdirSync } from "fs" import { randomUUID } from "crypto" +import { getOpenCodeConfigDir } from "../../shared/opencode-config-dir" import type { z } from "zod" import type { OhMyOpenCodeConfig } from "../../config/schema" export function getTaskDir(config: Partial = {}): string { const tasksConfig = config.sisyphus?.tasks - const storagePath = tasksConfig?.storage_path ?? ".sisyphus/tasks" - return join(process.cwd(), storagePath) + const storagePath = tasksConfig?.storage_path + + if (storagePath) { + return storagePath.startsWith("/") ? storagePath : join(process.cwd(), storagePath) + } + + const configDir = getOpenCodeConfigDir({ binary: "opencode" }) + const listId = resolveTaskListId(config) + return join(configDir, "tasks", listId) +} + +export function sanitizePathSegment(value: string): string { + return value.replace(/[^a-zA-Z0-9_-]/g, "-") || "default" +} + +export function resolveTaskListId(config: Partial = {}): string { + const envId = process.env.ULTRAWORK_TASK_LIST_ID?.trim() + if (envId) return sanitizePathSegment(envId) + + const configId = config.sisyphus?.tasks?.task_list_id?.trim() + if (configId) return sanitizePathSegment(configId) + + return sanitizePathSegment(basename(process.cwd())) } export function ensureDir(dirPath: string): void { From ace268818633287d2635b3a61c5d4c8e6be73295 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Wed, 4 Feb 2026 15:10:58 +0900 Subject: [PATCH 3/6] chore: regenerate schema after Task 1 changes --- assets/oh-my-opencode.schema.json | 835 +----------------------------- 1 file changed, 1 insertion(+), 834 deletions(-) diff --git a/assets/oh-my-opencode.schema.json b/assets/oh-my-opencode.schema.json index 809b7db7..343c3c07 100644 --- a/assets/oh-my-opencode.schema.json +++ b/assets/oh-my-opencode.schema.json @@ -2,838 +2,5 @@ "$schema": "http://json-schema.org/draft-07/schema#", "$id": "https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/master/assets/oh-my-opencode.schema.json", "title": "Oh My OpenCode Configuration", - "description": "Configuration schema for oh-my-opencode plugin", - "type": "object", - "properties": { - "$schema": { - "type": "string" - }, - "new_task_system_enabled": { - "type": "boolean" - }, - "default_run_agent": { - "type": "string" - }, - "disabled_mcps": { - "type": "array", - "items": { - "type": "string", - "minLength": 1 - } - }, - "disabled_agents": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "sisyphus", - "hephaestus", - "prometheus", - "oracle", - "librarian", - "explore", - "multimodal-looker", - "metis", - "momus", - "atlas" - ] - } - }, - "disabled_skills": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "playwright", - "agent-browser", - "frontend-ui-ux", - "git-master" - ] - } - }, - "disabled_hooks": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "todo-continuation-enforcer", - "context-window-monitor", - "session-recovery", - "session-notification", - "comment-checker", - "grep-output-truncator", - "tool-output-truncator", - "directory-agents-injector", - "directory-readme-injector", - "empty-task-response-detector", - "think-mode", - "anthropic-context-window-limit-recovery", - "preemptive-compaction", - "rules-injector", - "background-notification", - "auto-update-checker", - "startup-toast", - "keyword-detector", - "agent-usage-reminder", - "non-interactive-env", - "interactive-bash-session", - "thinking-block-validator", - "ralph-loop", - "category-skill-reminder", - "compaction-context-injector", - "claude-code-hooks", - "auto-slash-command", - "edit-error-recovery", - "delegate-task-retry", - "prometheus-md-only", - "sisyphus-junior-notepad", - "start-work", - "atlas", - "unstable-agent-babysitter", - "stop-continuation-guard", - "tasks-todowrite-disabler" - ] - } - }, - "disabled_commands": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "init-deep", - "start-work" - ] - } - }, - "disabled_tools": { - "type": "array", - "items": { - "type": "string" - } - }, - "agents": { - "type": "object", - "properties": { - "build": { - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "variant": { - "type": "string" - }, - "category": { - "type": "string" - }, - "skills": { - "type": "array", - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number", - "minimum": 0, - "maximum": 2 - }, - "top_p": { - "type": "number", - "minimum": 0, - "maximum": 1 - }, - "prompt": { - "type": "string" - }, - "prompt_append": { - "type": "string" - }, - "tools": { - "type": "object", - "additionalProperties": { - "type": "boolean" - } - }, - "disable": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "mode": { - "type": "string", - "enum": [ - "subagent", - "primary", - "all" - ] - }, - "color": { - "type": "string", - "pattern": "^#[0-9A-Fa-f]{6}$" - }, - "permission": { - "type": "object", - "properties": { - "edit": { - "type": "string", - "enum": [ - "ask", - "allow", - "deny" - ] - }, - "bash": { - "anyOf": [ - { - "$ref": "#/properties/agents/properties/build/properties/permission/properties/edit" - }, - { - "type": "object", - "additionalProperties": { - "$ref": "#/properties/agents/properties/build/properties/permission/properties/edit" - } - } - ] - }, - "webfetch": { - "$ref": "#/properties/agents/properties/build/properties/permission/properties/edit" - }, - "doom_loop": { - "$ref": "#/properties/agents/properties/build/properties/permission/properties/edit" - }, - "external_directory": { - "$ref": "#/properties/agents/properties/build/properties/permission/properties/edit" - } - }, - "additionalProperties": false - }, - "maxTokens": { - "type": "number" - }, - "thinking": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "enabled", - "disabled" - ] - }, - "budgetTokens": { - "type": "number" - } - }, - "required": [ - "type" - ], - "additionalProperties": false - }, - "reasoningEffort": { - "type": "string", - "enum": [ - "low", - "medium", - "high", - "xhigh" - ] - }, - "textVerbosity": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ] - }, - "providerOptions": { - "type": "object", - "additionalProperties": {} - } - }, - "additionalProperties": false - }, - "plan": { - "$ref": "#/properties/agents/properties/build" - }, - "sisyphus": { - "$ref": "#/properties/agents/properties/build" - }, - "hephaestus": { - "$ref": "#/properties/agents/properties/build" - }, - "sisyphus-junior": { - "$ref": "#/properties/agents/properties/build" - }, - "OpenCode-Builder": { - "$ref": "#/properties/agents/properties/build" - }, - "prometheus": { - "$ref": "#/properties/agents/properties/build" - }, - "metis": { - "$ref": "#/properties/agents/properties/build" - }, - "momus": { - "$ref": "#/properties/agents/properties/build" - }, - "oracle": { - "$ref": "#/properties/agents/properties/build" - }, - "librarian": { - "$ref": "#/properties/agents/properties/build" - }, - "explore": { - "$ref": "#/properties/agents/properties/build" - }, - "multimodal-looker": { - "$ref": "#/properties/agents/properties/build" - }, - "atlas": { - "$ref": "#/properties/agents/properties/build" - } - }, - "additionalProperties": false - }, - "categories": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "description": { - "type": "string" - }, - "model": { - "type": "string" - }, - "variant": { - "type": "string" - }, - "temperature": { - "type": "number", - "minimum": 0, - "maximum": 2 - }, - "top_p": { - "type": "number", - "minimum": 0, - "maximum": 1 - }, - "maxTokens": { - "type": "number" - }, - "thinking": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "enabled", - "disabled" - ] - }, - "budgetTokens": { - "type": "number" - } - }, - "required": [ - "type" - ], - "additionalProperties": false - }, - "reasoningEffort": { - "type": "string", - "enum": [ - "low", - "medium", - "high", - "xhigh" - ] - }, - "textVerbosity": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ] - }, - "tools": { - "type": "object", - "additionalProperties": { - "type": "boolean" - } - }, - "prompt_append": { - "type": "string" - }, - "is_unstable_agent": { - "type": "boolean" - } - }, - "additionalProperties": false - } - }, - "claude_code": { - "type": "object", - "properties": { - "mcp": { - "type": "boolean" - }, - "commands": { - "type": "boolean" - }, - "skills": { - "type": "boolean" - }, - "agents": { - "type": "boolean" - }, - "hooks": { - "type": "boolean" - }, - "plugins": { - "type": "boolean" - }, - "plugins_override": { - "type": "object", - "additionalProperties": { - "type": "boolean" - } - } - }, - "additionalProperties": false - }, - "sisyphus_agent": { - "type": "object", - "properties": { - "disabled": { - "type": "boolean" - }, - "default_builder_enabled": { - "type": "boolean" - }, - "planner_enabled": { - "type": "boolean" - }, - "replace_plan": { - "type": "boolean" - } - }, - "additionalProperties": false - }, - "comment_checker": { - "type": "object", - "properties": { - "custom_prompt": { - "type": "string" - } - }, - "additionalProperties": false - }, - "experimental": { - "type": "object", - "properties": { - "aggressive_truncation": { - "type": "boolean" - }, - "auto_resume": { - "type": "boolean" - }, - "preemptive_compaction": { - "type": "boolean" - }, - "truncate_all_tool_outputs": { - "type": "boolean" - }, - "dynamic_context_pruning": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "default": false - }, - "notification": { - "type": "string", - "enum": [ - "off", - "minimal", - "detailed" - ], - "default": "detailed" - }, - "turn_protection": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "default": true - }, - "turns": { - "type": "number", - "minimum": 1, - "maximum": 10, - "default": 3 - } - }, - "additionalProperties": false - }, - "protected_tools": { - "type": "array", - "items": { - "type": "string" - }, - "default": [ - "task", - "todowrite", - "todoread", - "lsp_rename", - "session_read", - "session_write", - "session_search" - ] - }, - "strategies": { - "type": "object", - "properties": { - "deduplication": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "default": true - } - }, - "additionalProperties": false - }, - "supersede_writes": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "default": true - }, - "aggressive": { - "type": "boolean", - "default": false - } - }, - "additionalProperties": false - }, - "purge_errors": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "default": true - }, - "turns": { - "type": "number", - "minimum": 1, - "maximum": 20, - "default": 5 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - "task_system": { - "type": "boolean" - } - }, - "additionalProperties": false - }, - "auto_update": { - "type": "boolean" - }, - "skills": { - "anyOf": [ - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "allOf": [ - { - "type": "object", - "additionalProperties": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "object", - "properties": { - "description": { - "type": "string" - }, - "template": { - "type": "string" - }, - "from": { - "type": "string" - }, - "model": { - "type": "string" - }, - "agent": { - "type": "string" - }, - "subtask": { - "type": "boolean" - }, - "argument-hint": { - "type": "string" - }, - "license": { - "type": "string" - }, - "compatibility": { - "type": "string" - }, - "metadata": { - "type": "object", - "additionalProperties": {} - }, - "allowed-tools": { - "type": "array", - "items": { - "type": "string" - } - }, - "disable": { - "type": "boolean" - } - }, - "additionalProperties": false - } - ] - } - }, - { - "type": "object", - "properties": { - "sources": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "object", - "properties": { - "path": { - "type": "string" - }, - "recursive": { - "type": "boolean" - }, - "glob": { - "type": "string" - } - }, - "required": [ - "path" - ], - "additionalProperties": false - } - ] - } - }, - "enable": { - "type": "array", - "items": { - "type": "string" - } - }, - "disable": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - ] - } - ] - }, - "ralph_loop": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "default": false - }, - "default_max_iterations": { - "type": "number", - "minimum": 1, - "maximum": 1000, - "default": 100 - }, - "state_dir": { - "type": "string" - } - }, - "additionalProperties": false - }, - "background_task": { - "type": "object", - "properties": { - "defaultConcurrency": { - "type": "number", - "minimum": 1 - }, - "providerConcurrency": { - "type": "object", - "additionalProperties": { - "type": "number", - "minimum": 0 - } - }, - "modelConcurrency": { - "type": "object", - "additionalProperties": { - "type": "number", - "minimum": 0 - } - }, - "staleTimeoutMs": { - "type": "number", - "minimum": 60000 - } - }, - "additionalProperties": false - }, - "notification": { - "type": "object", - "properties": { - "force_enable": { - "type": "boolean" - } - }, - "additionalProperties": false - }, - "babysitting": { - "type": "object", - "properties": { - "timeout_ms": { - "type": "number", - "default": 120000 - } - }, - "additionalProperties": false - }, - "git_master": { - "type": "object", - "properties": { - "commit_footer": { - "type": "boolean", - "default": true - }, - "include_co_authored_by": { - "type": "boolean", - "default": true - } - }, - "additionalProperties": false - }, - "browser_automation_engine": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "enum": [ - "playwright", - "agent-browser", - "dev-browser" - ], - "default": "playwright" - } - }, - "additionalProperties": false - }, - "websearch": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "enum": [ - "exa", - "tavily" - ] - } - }, - "additionalProperties": false - }, - "tmux": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "default": false - }, - "layout": { - "type": "string", - "enum": [ - "main-horizontal", - "main-vertical", - "tiled", - "even-horizontal", - "even-vertical" - ], - "default": "main-vertical" - }, - "main_pane_size": { - "type": "number", - "minimum": 20, - "maximum": 80, - "default": 60 - }, - "main_pane_min_width": { - "type": "number", - "minimum": 40, - "default": 120 - }, - "agent_pane_min_width": { - "type": "number", - "minimum": 20, - "default": 40 - } - }, - "additionalProperties": false - }, - "sisyphus": { - "type": "object", - "properties": { - "tasks": { - "type": "object", - "properties": { - "storage_path": { - "type": "string" - }, - "task_list_id": { - "type": "string" - }, - "claude_code_compat": { - "type": "boolean", - "default": false - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false + "description": "Configuration schema for oh-my-opencode plugin" } \ No newline at end of file From d66e39a887ac9a64687a33e268b19cf49aabd467 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Wed, 4 Feb 2026 15:12:28 +0900 Subject: [PATCH 4/6] refactor(tasks): consolidate task-list path resolution to use getTaskDir --- src/tools/task/task-list.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/tools/task/task-list.ts b/src/tools/task/task-list.ts index d7ba921b..2fbdb55b 100644 --- a/src/tools/task/task-list.ts +++ b/src/tools/task/task-list.ts @@ -4,7 +4,7 @@ import { existsSync, readdirSync } from "fs" import type { OhMyOpenCodeConfig } from "../../config/schema" import type { TaskObject, TaskStatus } from "./types" import { TaskObjectSchema } from "./types" -import { readJsonSafe } from "../../features/claude-tasks/storage" +import { readJsonSafe, getTaskDir } from "../../features/claude-tasks/storage" interface TaskSummary { id: string @@ -23,9 +23,7 @@ For each task's blockedBy field, filters to only include unresolved (non-complet Returns summary format: id, subject, status, owner, blockedBy (not full description).`, args: {}, execute: async (): Promise => { - const tasksConfig = config.sisyphus?.tasks - const storagePath = tasksConfig?.storage_path ?? ".sisyphus/tasks" - const taskDir = storagePath.startsWith("/") ? storagePath : join(process.cwd(), storagePath) + const taskDir = getTaskDir(config) if (!existsSync(taskDir)) { return JSON.stringify({ tasks: [] }) From 17129070572ccd3a3ceb6d0eaef080ab58837afe Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Wed, 4 Feb 2026 15:15:08 +0900 Subject: [PATCH 5/6] docs(tasks): update AGENTS.md for global storage architecture --- src/features/claude-tasks/AGENTS.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/features/claude-tasks/AGENTS.md b/src/features/claude-tasks/AGENTS.md index 356cdd65..4b152a2d 100644 --- a/src/features/claude-tasks/AGENTS.md +++ b/src/features/claude-tasks/AGENTS.md @@ -54,7 +54,26 @@ The task system includes a sync layer (`todo-sync.ts`) that automatically mirror ### getTaskDir(config) -Returns: `.sisyphus/tasks` (or custom path from config) +Returns the task storage directory path. + +**Default behavior (no config override):** +Returns `~/.config/opencode/tasks//` where: +- Task list ID is resolved via `resolveTaskListId()` + +**With `storage_path` config:** +- Absolute paths (starting with `/`) are returned as-is +- Relative paths are joined with `process.cwd()` + +### resolveTaskListId(config) + +Resolves the task list ID for directory scoping. + +**Priority order:** +1. `ULTRAWORK_TASK_LIST_ID` environment variable +2. `config.sisyphus?.tasks?.task_list_id` config option +3. Sanitized `basename(process.cwd())` as fallback + +**Sanitization:** Replaces non-alphanumeric characters (except `-` and `_`) with `-` ### readJsonSafe(filePath, schema) From 8e349aad7e3386bd27323ef538e6b7a29e6bbe64 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Wed, 4 Feb 2026 15:37:12 +0900 Subject: [PATCH 6/6] fix(tasks): use path.isAbsolute() for cross-platform path detection Fixes Cubic AI review finding: startsWith('/') doesn't work on Windows where absolute paths use drive letters (e.g., C:\). --- src/features/claude-tasks/storage.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/features/claude-tasks/storage.ts b/src/features/claude-tasks/storage.ts index b51ad417..b8916d4e 100644 --- a/src/features/claude-tasks/storage.ts +++ b/src/features/claude-tasks/storage.ts @@ -1,4 +1,4 @@ -import { join, dirname, basename } from "path" +import { join, dirname, basename, isAbsolute } from "path" import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync, unlinkSync, readdirSync } from "fs" import { randomUUID } from "crypto" import { getOpenCodeConfigDir } from "../../shared/opencode-config-dir" @@ -10,7 +10,7 @@ export function getTaskDir(config: Partial = {}): string { const storagePath = tasksConfig?.storage_path if (storagePath) { - return storagePath.startsWith("/") ? storagePath : join(process.cwd(), storagePath) + return isAbsolute(storagePath) ? storagePath : join(process.cwd(), storagePath) } const configDir = getOpenCodeConfigDir({ binary: "opencode" })