@opellen/opengoal 1.0.3 → 1.0.5

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.ja.md CHANGED
@@ -332,13 +332,13 @@ AI: ✓ サブゴールをアーカイブしました。Goal Aに戻ります
332
332
 
333
333
  - [Planura](https://github.com/opellen/Planura) — ネイティブなダイレクトモデリング3Dアプリケーション(C++20 / Qt 6 / OpenGL): half-edgeジオメトリカーネル、CSGソリッドモデリング、推論駆動の描画を、専用フレームワーク [Ordo](https://github.com/opellen/Ordo) の上に実装。
334
334
  - [Ordo](https://github.com/opellen/Ordo) — Planura から切り出された C++20 の型付きイベント・アプリケーションフレームワークです。イベントはただの構造体で、型がアイデンティティ、フィールドがペイロードです。
335
+ - [OrdoStateDesigner](https://github.com/opellen/OrdoStateDesigner) — Ordo の上に構築したステートチャート・デザイナー(C++20 / Qt 6)です。キャンバスに状態機械を描き、その場でシミュレートし、それを動かす C++ を生成します。
335
336
  - リバースエンジニアリングのキャンペーン — OpenGoalが設計された本来の領域であり、ゴールは大きく、道筋は不明で、進捗が細かく分割できるかどうかにかかっています。
336
337
 
337
338
  **アプリケーションとツール**
338
339
 
339
340
  - [SeedNote](https://github.com/opellen/Seed-Note) — Android向けの構造化ブロックエディタ(Kotlin / Jetpack Compose)
340
341
  - [ScreenUse](https://github.com/opellen/Screen-Use) — 実際のアプリを操作・記録する、シナリオ駆動のUIリプレイ&検証ツール
341
- - [OpenIllust](https://github.com/opellen/OpenIllust) — Claude Code と Codex のためのキャンペーン駆動型 AI ベクター素材制作ツールです。このリポジトリのロゴ一式も OpenIllust で制作しました。
342
342
 
343
343
  **特化ツール**
344
344
 
package/README.ko.md CHANGED
@@ -333,6 +333,8 @@ AI: ✓ 서브골 아카이브 완료. Goal A로 복귀 — 포인터 태스크
333
333
  자체 프레임워크인 [Ordo](https://github.com/opellen/Ordo) 기반으로 구현했습니다.
334
334
  - [Ordo](https://github.com/opellen/Ordo) — Planura에서 추출된 C++20용 타입 이벤트 애플리케이션 프레임워크입니다.
335
335
  이벤트는 평범한 구조체이며, 타입이 곧 정체성이고 필드가 곧 페이로드입니다.
336
+ - [OrdoStateDesigner](https://github.com/opellen/OrdoStateDesigner) — Ordo 기반의 상태차트 디자이너입니다
337
+ (C++20 / Qt 6). 캔버스에 상태 머신을 그리고, 실시간으로 시뮬레이션하고, 그것을 실행하는 C++ 코드를 생성합니다.
336
338
  - 리버스엔지니어링 캠페인 — OpenGoal이 처음 고안된 도메인입니다. 목표는 거대하고 길은
337
339
  보이지 않아서, 목표를 잘게 쪼갤 수 있을 때에만 전진할 수 있는 영역입니다.
338
340
 
@@ -340,8 +342,6 @@ AI: ✓ 서브골 아카이브 완료. Goal A로 복귀 — 포인터 태스크
340
342
 
341
343
  - [SeedNote](https://github.com/opellen/Seed-Note) — Android용 구조화 블록 에디터 (Kotlin / Jetpack Compose)
342
344
  - [ScreenUse](https://github.com/opellen/Screen-Use) — 시나리오 기반 UI 재생 및 검증 도구 (실제 앱을 구동해 녹화)
343
- - [OpenIllust](https://github.com/opellen/OpenIllust) — Claude Code와 Codex를 위한 캠페인 기반 AI 벡터 에셋 제작
344
- 도구입니다. 이 저장소의 로고 세트도 OpenIllust로 제작했습니다.
345
345
 
346
346
  **집중형 도구**
347
347
 
package/README.md CHANGED
@@ -341,6 +341,8 @@ That range is the point.
341
341
  drawing, on [Ordo](https://github.com/opellen/Ordo), its purpose-built application framework.
342
342
  - [Ordo](https://github.com/opellen/Ordo) — a typed-event application framework for C++20, extracted from
343
343
  Planura. An event is a plain struct: the type is the identity, the fields are the payload.
344
+ - [OrdoStateDesigner](https://github.com/opellen/OrdoStateDesigner) — a statechart designer built on Ordo
345
+ (C++20 / Qt 6): draw a state machine on a canvas, simulate it live, and generate the C++ that runs it.
344
346
  - Reverse-engineering campaigns — the domain OpenGoal was designed in, where the goal is
345
347
  large, the path is unknown, and progress depends on splitting it finely.
346
348
 
@@ -348,8 +350,6 @@ That range is the point.
348
350
 
349
351
  - [SeedNote](https://github.com/opellen/Seed-Note) — a structured block editor for Android (Kotlin / Jetpack Compose)
350
352
  - [ScreenUse](https://github.com/opellen/Screen-Use) — a scenario-driven UI replay and verification tool that drives a real app and records it
351
- - [OpenIllust](https://github.com/opellen/OpenIllust) — campaign-driven AI vector asset production for Claude Code and
352
- Codex; the logo set in this repository was produced with it
353
353
 
354
354
  **Focused tools**
355
355
 
package/README.zh-CN.md CHANGED
@@ -356,6 +356,8 @@ AI: ✓ sub-goal 已归档。回到目标 A —— 对应的指针任务已勾
356
356
  绘图,构建在自研框架 [Ordo](https://github.com/opellen/Ordo) 之上。
357
357
  - [Ordo](https://github.com/opellen/Ordo) — 从 Planura 中提取出来的 C++20 类型化事件应用框架。
358
358
  事件就是一个普通的结构体:类型即身份,字段即载荷。
359
+ - [OrdoStateDesigner](https://github.com/opellen/OrdoStateDesigner) — 构建在 Ordo 之上的状态图设计器
360
+ (C++20 / Qt 6):在画布上绘制状态机,实时模拟,并生成运行它的 C++ 代码。
359
361
  - 逆向工程项目 — OpenGoal 最初就是为这类场景设计的:目标庞大、路径未知,
360
362
  进展全靠把任务拆得足够细。
361
363
 
@@ -363,8 +365,6 @@ AI: ✓ sub-goal 已归档。回到目标 A —— 对应的指针任务已勾
363
365
 
364
366
  - [SeedNote](https://github.com/opellen/Seed-Note) — 一款面向 Android 的结构化块编辑器(Kotlin / Jetpack Compose)
365
367
  - [ScreenUse](https://github.com/opellen/Screen-Use) — 一款场景驱动的 UI 回放与验证工具,能驱动真实应用并录制过程
366
- - [OpenIllust](https://github.com/opellen/OpenIllust) — 面向 Claude Code 与 Codex 的、以 campaign 为单位的 AI
367
- 矢量素材生产工具。本仓库的 logo 套件正是用它制作的。
368
368
 
369
369
  **专注型工具**
370
370
 
@@ -1,7 +1,29 @@
1
+ import { dirname } from "node:path";
2
+ const capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
3
+ // Codex labels a skill from agents/openai.yaml when present; without it the
4
+ // label is derived from the frontmatter name with the casing flattened
5
+ // ("opengoal:go" shows as "Opengoal: Go").
6
+ const commandLabel = (name) => `OpenGoal: ${capitalize(name)}`;
7
+ function displayName(target) {
8
+ return target.kind === "command"
9
+ ? commandLabel(target.name)
10
+ : `OpenGoal ${capitalize(target.name.replace(/^opengoal-/, ""))}`;
11
+ }
1
12
  export const codex = {
2
13
  id: "codex",
3
14
  displayName: "Codex",
4
15
  configDir: ".codex",
5
16
  commandPath: (name, prefix) => `.codex/skills/${prefix}-${name}/SKILL.md`,
6
17
  formatCommand: (body) => body,
18
+ // Skills are invoked from Codex's picker, so prose refers to them by the
19
+ // label the picker shows, not by a slash form.
20
+ commandRef: (name) => commandLabel(name),
21
+ companionFiles: (target) => [
22
+ {
23
+ dst: `${dirname(target.dst).replace(/\\/g, "/")}/agents/openai.yaml`,
24
+ content: "interface:\n" +
25
+ ` display_name: ${JSON.stringify(displayName(target))}\n` +
26
+ ` short_description: ${JSON.stringify(target.description)}\n`,
27
+ },
28
+ ],
7
29
  };
@@ -4,6 +4,21 @@ export interface CommandMeta {
4
4
  category?: string;
5
5
  tags?: string[];
6
6
  }
7
+ /** An extra file a platform wants installed next to a command or skill. */
8
+ export interface CompanionFile {
9
+ /** Install path relative to the project root. */
10
+ dst: string;
11
+ content: string;
12
+ }
13
+ export interface CompanionTarget {
14
+ kind: "command" | "skill";
15
+ /** Command name ("go") or skill name ("opengoal-flow"). */
16
+ name: string;
17
+ description: string;
18
+ /** Install path of the file the companions accompany. */
19
+ dst: string;
20
+ prefix: string;
21
+ }
7
22
  export interface PlatformAdapter {
8
23
  id: string;
9
24
  displayName: string;
@@ -15,5 +30,18 @@ export interface PlatformAdapter {
15
30
  supportsCommands?: boolean;
16
31
  commandPath(name: string, prefix: string): string;
17
32
  formatCommand(body: string, meta: CommandMeta, prefix: string): string;
33
+ /**
34
+ * How an installed command is invoked on this platform, as written in the
35
+ * prose that templates emit ("run /opgl:go"). Platforms whose invocation
36
+ * differs from the Claude Code slash form `/<prefix>:<name>` override this;
37
+ * when omitted that form is used.
38
+ */
39
+ commandRef?(name: string, prefix: string): string;
40
+ /**
41
+ * Extra files the platform needs beside an installed command or skill, such
42
+ * as Codex's `agents/openai.yaml` display manifest. They are installed and
43
+ * uninstalled together with the file they accompany.
44
+ */
45
+ companionFiles?(target: CompanionTarget): CompanionFile[];
18
46
  }
19
47
  export declare const DEFAULT_PLATFORM = "claude";
@@ -15,6 +15,8 @@ export interface TemplateEntry {
15
15
  adapter: PlatformAdapter;
16
16
  meta: CommandMeta;
17
17
  rawContent: string;
18
+ /** Companion file produced by the adapter; rawContent is final, no rendering. */
19
+ generated?: boolean;
18
20
  }
19
21
  export declare function resolveTemplates(config: OpenGoalConfig): TemplateEntry[];
20
22
  export declare function renderFile(entry: TemplateEntry, config: OpenGoalConfig): string;
package/dist/templates.js CHANGED
@@ -18,6 +18,18 @@ const OPENGOAL_VERSION = (() => {
18
18
  }
19
19
  })();
20
20
  export const DEFAULT_PREFIX = "opgl";
21
+ function companionEntries(adapter, target, meta) {
22
+ if (!adapter.companionFiles)
23
+ return [];
24
+ return adapter.companionFiles(target).map((file) => ({
25
+ src: `generated/${target.kind}/${target.name}`,
26
+ dst: file.dst,
27
+ adapter,
28
+ meta,
29
+ rawContent: file.content,
30
+ generated: true,
31
+ }));
32
+ }
21
33
  const COMMAND_TEMPLATES = [
22
34
  "scout", "goal", "context", "design",
23
35
  "roadmap", "verify", "recap", "overview", "go",
@@ -64,32 +76,36 @@ export function resolveTemplates(config) {
64
76
  for (const adapter of adapters) {
65
77
  if (adapter.supportsCommands !== false) {
66
78
  for (const { cmd, src, rawContent, meta } of commandMetas) {
67
- entries.push({ src, dst: adapter.commandPath(cmd, config.prefix), adapter, meta, rawContent });
79
+ const dst = adapter.commandPath(cmd, config.prefix);
80
+ entries.push({ src, dst, adapter, meta, rawContent });
81
+ entries.push(...companionEntries(adapter, { kind: "command", name: cmd, description: meta.description, dst, prefix: config.prefix }, meta));
68
82
  }
69
83
  }
70
84
  for (const skill of skillContents) {
71
- entries.push({
72
- src: skill.src,
73
- dst: skillInstallPath(adapter, skill.skillName),
74
- adapter,
75
- meta: { name: skill.skillName, description: "" },
76
- rawContent: skill.rawContent,
77
- });
85
+ const dst = skillInstallPath(adapter, skill.skillName);
86
+ const description = skill.rawContent.replace(/\r\n/g, "\n").match(/^description:\s*(.+)$/m)?.[1]?.trim() ?? "";
87
+ const meta = { name: skill.skillName, description };
88
+ entries.push({ src: skill.src, dst, adapter, meta, rawContent: skill.rawContent });
89
+ entries.push(...companionEntries(adapter, { kind: "skill", name: skill.skillName, description, dst, prefix: config.prefix }, meta));
78
90
  }
79
91
  }
80
92
  return entries;
81
93
  }
82
94
  export function renderFile(entry, config) {
95
+ if (entry.generated)
96
+ return entry.rawContent;
83
97
  const content = entry.rawContent.replace(/\r\n/g, "\n");
84
98
  const rendered = renderTemplate(content, {
85
99
  conditions: {
86
100
  subagent: config.subagent,
87
101
  },
88
102
  });
103
+ const commandRef = entry.adapter.commandRef ?? ((name, prefix) => `/${prefix}:${name}`);
89
104
  const substituted = rendered
90
105
  .replace(/\$DocsDir/g, config.docsDir)
91
106
  .replace(/\$CodebaseDir/g, config.codebaseDir)
92
107
  .replace(/\$OpenGoalVersion/g, OPENGOAL_VERSION)
108
+ .replace(/\/\$CommandPrefix:([a-z-]+)/g, (_match, name) => commandRef(name, config.prefix))
93
109
  .replace(/\$CommandPrefix/g, config.prefix);
94
110
  if (entry.src.startsWith("skills/")) {
95
111
  return formatSkill(substituted);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opellen/opengoal",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Goal-centric AI harness. Plain markdown, zero runtime — nothing runs but your agent.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -48,4 +48,4 @@
48
48
  "chalk": "^5.6.2",
49
49
  "yaml": "^2.8.3"
50
50
  }
51
- }
51
+ }