diff --git a/AGENTS.md b/AGENTS.md index 0c4d1a26..5eb69707 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -53,8 +53,11 @@ Author or user request - An Omniskills bundle is a deployable skills set with a `workflow.json`, optional `workflow.lock.json`, README, and optional local skills. Omitted - `kind` means workflow; first-class teams declare `kind: "team"` plus a local - declared `coordinator` and unique local declared `members`. + `kind` means workflow. A first-class team declares `kind: "team"`; its + `coordinator` is one declared local entry skill, and every `members[]` source + must be declared in `skills[]` and resolve to a child workflow with exactly + one local entry skill. Child dependencies expand recursively, while only the + root team install record is written. - `startup-team` under `examples/teams/startup-team` is the primary public team. Role workflows such as `cto`, `product-manager`, and `founding-engineer` remain independently installable public examples. diff --git a/docs/architecture.md b/docs/architecture.md index 91ead22e..fde44f08 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -52,8 +52,8 @@ Compatibility aliases: - parse and validate `workflow.json` - preserve omitted `kind` as a legacy workflow and validate first-class - `kind: "team"` manifests with a local declared `coordinator`, unique local - declared `members`, and no coordinator/member overlap + `kind: "team"` manifests with one local entry `coordinator`, unique declared + `members` that resolve to child workflows, and no coordinator/member overlap - parse and validate optional `workflow.lock.json` - generate deterministic skill fingerprints for local and external skill sources through `omniskill lock ` @@ -64,6 +64,9 @@ Compatibility aliases: - resolve local and public git bundle sources; bare `*-team` aliases route to `examples/teams/`, while other bare aliases route to `examples/workflows/` +- recursively resolve child workflows before installation, select the highest + declared semantic version for duplicate workflow names, deduplicate leaf + skills, and reject cycles with the full active workflow path - list skill dependency sources plus optional Skills CLI repository metadata - prepare looped workflow entry skill installs with copied `workflow.json`, generated `loop.mjs`, and generated `loop.metadata.json` @@ -133,11 +136,13 @@ should stay aligned with `workflow.json`. A first-class team uses the same file layout under `examples/teams/` and declares `kind: "team"`, `coordinator`, and `members` in `workflow.json`. -`coordinator` and every `members[]` value must match a declared local -`skills[].source`. For `startup-team`, the coordinator is marked as the callable -entry skill: startup-goal remains the callable coordinator while the seven -startup role skills are members. The public bundle installs as `startup-team`; -users invoke `$startup-goal` after installation. +The coordinator is one declared local entry skill. Every `members[]` source +must be declared in `skills[]` and resolve to a child workflow with exactly one +local entry skill. Member dependencies expand recursively, but only the root +team install record is written. For `startup-team`, startup-goal remains the +callable coordinator while seven canonical standalone role workflows provide +the members. The public bundle installs as `startup-team`; users invoke +`$startup-goal` after installation. `workflow.lock.json` is generated by `omniskill lock `. It records deterministic hashes for local skill files and stable fingerprints for external @@ -145,6 +150,20 @@ skill sources so reviewers can see when a workflow's skill tree changed. Missing lock files remain valid for compatibility, but checked-in public workflows should include them. +Parents declare only direct dependencies. A local dependency directory that +contains `workflow.json` is a child workflow and is scanned recursively. Direct +repository URLs, including `#subdirectory` fragments, work the same way. +`catalog:` selects a canonical catalog workflow without making ordinary +bare skill names ambiguous, and `installed:` reopens an installed +workflow's recorded source. `skill-tree-demo` is the minimal local example. + +New locks use schema `0.2`: they store the selected workflow nodes and edges, +exact git commits, and fingerprints for the fully expanded leaf skill set. +Locked git children fetch their recorded commit directly on repeat installs. +Legacy `0.1` locks remain valid for flat workflows; once a child workflow is +detected, authors must regenerate the lock. Child workflows with the same name +must declare valid semantic versions, and the highest version's subtree wins. + Loop-enabled workflows declare `loop` in `workflow.json`, mark exactly one local skill with `entry: true`, and keep phase instructions in `steps[].instruction`. `loop.script` names the generated compatibility runner output path, usually diff --git a/docs/landing-content.md b/docs/landing-content.md index 145da5ec..4ec1019a 100644 --- a/docs/landing-content.md +++ b/docs/landing-content.md @@ -424,7 +424,7 @@ debugging, review, and verification. Skills: - `founding-engineer`: Set the implementation frame -- `implement`: Implement the planned change +- `mattpocock:implement`: Implement the planned change - `mattpocock:tdd`: Use test-first development - `mattpocock:diagnosing-bugs`: Diagnose failures - `mattpocock:code-review`: Review behavior and risk @@ -434,7 +434,7 @@ Ordered skill path: 1. Brief -> `founding-engineer` - Read the plan and acceptance criteria. -2. Implement -> `implement` +2. Implement -> `mattpocock:implement` - Ship the smallest correct slice. 3. TDD -> `mattpocock:tdd` - Keep tests close to changed behavior. diff --git a/docs/landing-content.zh-Hant.md b/docs/landing-content.zh-Hant.md index c3eb32e8..9eaf9b86 100644 --- a/docs/landing-content.zh-Hant.md +++ b/docs/landing-content.zh-Hant.md @@ -268,9 +268,9 @@ npx omniskill@latest install founding-engineer Description:Implementation lane,聚焦 smallest correct change:tests、debugging、review、verification。 -Skills:`founding-engineer`、`implement`、`mattpocock:tdd`、`mattpocock:diagnosing-bugs`、`mattpocock:code-review`、`superpowers:verification-before-completion`。 +Skills:`founding-engineer`、`mattpocock:implement`、`mattpocock:tdd`、`mattpocock:diagnosing-bugs`、`mattpocock:code-review`、`superpowers:verification-before-completion`。 -Ordered skill path:Brief -> `founding-engineer`;Implement -> `implement`;TDD -> `mattpocock:tdd`;Debug -> `mattpocock:diagnosing-bugs`;Review -> `mattpocock:code-review`;Verify -> `superpowers:verification-before-completion`。 +Ordered skill path:Brief -> `founding-engineer`;Implement -> `mattpocock:implement`;TDD -> `mattpocock:tdd`;Debug -> `mattpocock:diagnosing-bugs`;Review -> `mattpocock:code-review`;Verify -> `superpowers:verification-before-completion`。 ### QA Lead diff --git a/docs/superpowers/plans/2026-07-14-team-workflow-members.md b/docs/superpowers/plans/2026-07-14-team-workflow-members.md new file mode 100644 index 00000000..7f25987e --- /dev/null +++ b/docs/superpowers/plans/2026-07-14-team-workflow-members.md @@ -0,0 +1,719 @@ +# Canonical Team Workflow Members Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Remove duplicated startup-team role skills by making team members resolve to canonical child workflow entry skills. + +**Architecture:** Keep the team coordinator as one local entry skill, resolve every `members[]` source through the existing recursive workflow graph, and validate the selected child workflow's single local entry skill before installation. Migrate `startup-team` to `catalog:` members, retain one root install record, and point landing links at the canonical standalone workflow sources. + +**Tech Stack:** Bun, TypeScript, Commander, Zod, Bun test, Biome, Omniskills workflow manifests and schema `0.2` lock files. + +**Execution rule:** Before each task's first file mutation, use `pony-trail` to record a pre-change snapshot for exactly that task's files. After its final mutation and focused checks, record the matching post-change snapshot before staging or committing. + +--- + +## File Map + +- `src/runtimes/omniskill/workflow-bundles.ts` — synchronous team manifest rules, recursive member resolution, and resolved-team validation. +- `src/omniskill.ts` — make `validate` run the same dependency graph validation as `deps`, `lock`, and `install`. +- `tests/workflow-bundles.test.ts` — public runtime-seam coverage for member workflows and failure modes. +- `tests/omniskill.test.ts` — CLI validation, pre-write failure, install artifact, and root-record coverage. +- `examples/teams/startup-team/workflow.json` — direct coordinator, child workflow members, and root-only steps. +- `examples/teams/startup-team/workflow.lock.json` — generated expanded child workflow graph and leaf fingerprints. +- `examples/teams/startup-team/skills/{ceo,cto,product-manager,web-design,engineering-manager,founding-engineer,qa-lead}/SKILL.md` — delete duplicated role definitions. +- `landing/lib/landing-content.ts` — canonical skill source URLs and startup-team local-skill ownership. +- `landing/components/workflow-detail.tsx` — use canonical skill links. +- `landing/app/workflows/[slug]/page.tsx` — use canonical skill links on static detail routes. +- `landing/components/workflow-run-demo.tsx` — link the coordinator to the team and roles to standalone workflows. +- `tests/landing-app.test.ts` — manifest/member parity and canonical source-link coverage. +- `AGENTS.md`, `docs/architecture.md`, `docs/workflow-author-guide.md` — authoritative team authoring contract. +- `tests/readme.test.ts` — repository-guidance contract coverage. + +### Task 1: Validate Team Members Through the Recursive Workflow Graph + +**Files:** +- Modify: `src/runtimes/omniskill/workflow-bundles.ts:77-150` +- Modify: `src/runtimes/omniskill/workflow-bundles.ts:717-890` +- Test: `tests/workflow-bundles.test.ts:430-560` +- Test: `tests/workflow-bundles.test.ts:1080-1215` + +- [ ] **Step 1: Add a fixture helper for team and child workflow manifests** + +Add this helper beside the existing workflow fixture helpers in `tests/workflow-bundles.test.ts`: + +```ts +async function writeTeamWithMemberFixture(input: { + rootDir: string; + memberSource: string; + childEntrySources?: Array<{ source: string; entry?: boolean }>; +}): Promise<{ teamDir: string; childDir: string }> { + const teamDir = join(input.rootDir, "team"); + const childDir = join(input.rootDir, "child"); + await mkdir(join(teamDir, "skills", "coordinator"), { recursive: true }); + await writeFile(join(teamDir, "skills", "coordinator", "SKILL.md"), "# coordinator\n"); + await mkdir(join(childDir, "skills", "member"), { recursive: true }); + await writeFile(join(childDir, "skills", "member", "SKILL.md"), "# member\n"); + await writeFile( + join(childDir, "workflow.json"), + JSON.stringify({ + schemaVersion: "0.1", + name: "member-workflow", + version: "1.0.0", + description: "Canonical member workflow.", + skills: input.childEntrySources ?? [{ source: "./skills/member", entry: true }], + steps: [{ id: "member", title: "Member", skill: "./skills/member" }], + }), + ); + await writeFile( + join(teamDir, "workflow.json"), + JSON.stringify({ + schemaVersion: "0.1", + kind: "team", + name: "test-team", + version: "1.0.0", + description: "Team with one canonical member workflow.", + coordinator: "./skills/coordinator", + members: [input.memberSource], + skills: [ + { source: "./skills/coordinator", entry: true }, + { source: input.memberSource }, + ], + steps: [ + { id: "coordinate", title: "Coordinate", skill: "./skills/coordinator" }, + { id: "member", title: "Member", skill: input.memberSource }, + ], + }), + ); + return { teamDir, childDir }; +} +``` + +- [ ] **Step 2: Write the failing public-seam tests** + +Add tests that call `resolveWorkflowDependencyGraph`, not private helpers: + +```ts +test("resolves a team member to one canonical child workflow entry skill", async () => { + const rootDir = await mkdtemp(join(tmpdir(), "team-member-workflow-")); + try { + const { teamDir } = await writeTeamWithMemberFixture({ + rootDir, + memberSource: "../child", + }); + const graph = await resolveWorkflowDependencyGraph({ + bundle: await loadWorkflowBundle(teamDir), + }); + + expect(graph.workflows.map(({ name }) => name)).toEqual(["test-team", "member-workflow"]); + expect(graph.edges).toEqual([{ from: "test-team@1.0.0", to: "member-workflow@1.0.0" }]); + expect(graph.dependencies.map(({ source }) => source)).toEqual([ + join(teamDir, "skills", "coordinator"), + join(rootDir, "child", "skills", "member"), + ]); + } finally { + await rm(rootDir, { recursive: true, force: true }); + } +}); + +test("rejects a copied local skill as a team member", async () => { + const rootDir = await mkdtemp(join(tmpdir(), "team-local-member-")); + try { + const { teamDir } = await writeTeamWithMemberFixture({ + rootDir, + memberSource: "./skills/copied-member", + }); + await mkdir(join(teamDir, "skills", "copied-member"), { recursive: true }); + await writeFile(join(teamDir, "skills", "copied-member", "SKILL.md"), "# copied\n"); + + await expect( + resolveWorkflowDependencyGraph({ bundle: await loadWorkflowBundle(teamDir) }), + ).rejects.toThrow( + "Team member must reference a child workflow with exactly one local entry skill: ./skills/copied-member", + ); + } finally { + await rm(rootDir, { recursive: true, force: true }); + } +}); +``` + +Add focused cases for zero entry, a non-local entry, duplicate resolved workflow names, duplicate entry names, and an existing cycle. A child manifest with multiple entries should assert the existing Zod error `Only one workflow skill can be marked as entry` while naming the member source in the wrapping resolution error. + +Extend the existing repository/subdirectory, `catalog:`, and `installed:` resolver tests so each parent is a valid team with a local coordinator and the resolved child skill is marked `entry: true`. Together with the local `../child` case above, these tests prove every supported member source form. + +Extend the existing highest-child-SemVer test so the root is a team whose member points to the lower version while another non-member dependency discovers the higher version of the same workflow. Mark each candidate's distinct local skill as its entry. Assert the selected member entry and flattened dependency come only from version `1.10.0`. + +- [ ] **Step 3: Run the tests and verify the intended failures** + +Run: + +```bash +rtk bun test tests/workflow-bundles.test.ts -t "team member" +``` + +Expected: the canonical child case fails because non-local team members are rejected synchronously, and the copied local member case resolves as a leaf instead of failing the resolved-team rule. + +- [ ] **Step 4: Relax only the synchronous member-path restriction** + +In `WorkflowBundleManifestSchema.superRefine`, retain declaration, duplicate, and coordinator/member overlap checks, but remove this local-path rejection: + +```ts +if (!isLocalWorkflowSkillSource(member)) { + context.addIssue({ + code: z.ZodIssueCode.custom, + message: `Team member must be a local skill path: ${member}`, + path: ["members", index], + }); +} +``` + +Add a coordinator entry check after resolving `coordinatorSkill` from `manifest.skills`: + +```ts +const coordinatorSkill = manifest.skills.find( + (skill) => skill.source === manifest.coordinator, +); +if (coordinatorSkill && coordinatorSkill.entry !== true) { + context.addIssue({ + code: z.ZodIssueCode.custom, + message: "Team coordinator must be marked as the entry skill", + path: ["coordinator"], + }); +} +``` + +- [ ] **Step 5: Add one resolved-team validation module inside the runtime** + +First wrap root-team member resolution errors at the `resolver.resolve` call inside `discover`. This preserves the child parser's original error while identifying which member source failed: + +```ts +const memberSource = + bundle === input.bundle && bundle.manifest.kind === "team" + ? bundle.manifest.members?.find((source) => source === bundle.manifest.skills[index]?.source) + : undefined; +let child: WorkflowBundle | null; +try { + child = await resolver.resolve({ dependency, parent: bundle }); +} catch (error) { + if (!memberSource) throw error; + const message = error instanceof Error ? error.message : String(error); + throw new Error(`Failed to resolve team member ${memberSource}: ${message}`, { cause: error }); +} +``` + +Then keep resolved-team validation private to `workflow-bundles.ts`: + +```ts +function validateResolvedTeamMembers(input: { + root: WorkflowBundle; + resolvedChildren: Map; + selectedByName: Map; +}): void { + if (input.root.manifest.kind !== "team") return; + + const rootId = getCanonicalWorkflowIdentity(input.root); + const workflowNames = new Set(); + const entryNames = new Set(); + + for (const member of input.root.manifest.members ?? []) { + const index = input.root.manifest.skills.findIndex((skill) => skill.source === member); + const discovered = input.resolvedChildren.get(`${rootId}\n${index}`); + const child = discovered + ? (input.selectedByName.get(discovered.manifest.name) ?? discovered) + : null; + const entries = child?.manifest.skills.filter((skill) => skill.entry === true) ?? []; + const entry = entries[0]; + if (!child || entries.length !== 1 || !entry || !isLocalWorkflowSkillSource(entry.source)) { + throw new Error( + `Team member must reference a child workflow with exactly one local entry skill: ${member}`, + ); + } + if (workflowNames.has(child.manifest.name)) { + throw new Error(`Duplicate resolved team workflow: ${child.manifest.name}`); + } + const entryName = basename(entry.source); + if (entryNames.has(entryName)) { + throw new Error(`Duplicate resolved team entry skill: ${entryName}`); + } + workflowNames.add(child.manifest.name); + entryNames.add(entryName); + } +} +``` + +Call it immediately after discovery and before legacy/transitive lock validation: + +```ts +validateResolvedTeamMembers({ + root: input.bundle, + resolvedChildren, + selectedByName, +}); +``` + +Member indexes must continue to match the manifest skill order used by `resolvedChildren`. + +- [ ] **Step 6: Run focused runtime tests** + +Run: + +```bash +rtk bun test tests/workflow-bundles.test.ts -t "team" +rtk bun run typecheck +``` + +Expected: all team tests pass and TypeScript reports no errors. + +- [ ] **Step 7: Commit the runtime contract** + +```bash +rtk git add src/runtimes/omniskill/workflow-bundles.ts tests/workflow-bundles.test.ts +rtk git commit -m "feat: resolve team members from child workflows" +``` + +### Task 2: Make Every CLI Command Enforce Resolved Team Validation + +**Files:** +- Modify: `src/omniskill.ts:255-275` +- Modify: `tests/omniskill.test.ts:47-126` +- Test: `tests/omniskill.test.ts:930-1080` + +- [ ] **Step 1: Migrate the CLI team fixture to a child workflow member** + +When `options.team` is true in `writeGitWorkflowFixtureAt`, create +`member-workflow/skills/git-extra/SKILL.md` and its workflow manifest. The root +team uses `members: ["./member-workflow"]`, declares `./member-workflow` in +`skills[]`, and uses it in the member step. Keep `./skills/git-entry` as the +coordinator with `entry: true`. + +Use this child manifest: + +```ts +await writeFile( + join(workflowDir, "member-workflow", "workflow.json"), + JSON.stringify({ + schemaVersion: "0.1", + name: "git-member", + version: "1.0.0", + description: "Canonical member workflow.", + skills: [{ source: "./skills/git-extra", entry: true }], + steps: [{ id: "member", title: "Member", skill: "./skills/git-extra" }], + }), +); +``` + +- [ ] **Step 2: Write failing CLI tests for validate and pre-write install failure** + +Add: + +```ts +test("validate resolves team member workflows", async () => { + const rootDir = await mkdtemp(join(tmpdir(), "omniskill-team-validate-")); + const program = new Command(); + try { + await writeGitWorkflowFixtureAt(rootDir, { team: true }); + configureOmniskillCommand(program, { rootDir }); + await expect( + program.parseAsync(["validate", rootDir], { from: "user" }), + ).resolves.toBeDefined(); + } finally { + await rm(rootDir, { recursive: true, force: true }); + } +}); +``` + +Add a second fixture whose member is `./skills/git-extra`, call `install`, and +assert the fake `installSkill` call count is zero and no root workflow record +exists. + +Use that same invalid fixture with fresh `Command` instances for `validate`, `deps`, and `lock`. Assert all three reject with `Team member must reference a child workflow`, matching `install`. For the valid fixture, assert install creates only `.omniskills/workflows/git-team.json`; it must not create a `git-member.json` child record. + +- [ ] **Step 3: Run the CLI tests and verify validate is falsely green** + +```bash +rtk bun test tests/omniskill.test.ts -t "team" +``` + +Expected: the invalid local-member `validate` case passes because the current validate command only loads the manifest. + +- [ ] **Step 4: Resolve and clean up the graph in the validate command** + +Replace the validate action body with this shape: + +```ts +const bundle = await loadWorkflowBundle(path, { + cwd: options.rootDir, + ...(options.workflowGitCommandRunner + ? { runGitCommand: options.workflowGitCommandRunner } + : {}), +}); +let graph: Awaited> | undefined; +try { + graph = await resolveWorkflowDependencyGraph({ + bundle, + ...(options.workflowGitCommandRunner + ? { runGitCommand: options.workflowGitCommandRunner } + : {}), + installedRootDir: options.rootDir, + }); + console.log(success(`Omniskills valid: ${bundle.manifest.name}@${bundle.manifest.version}`)); + console.log(keyValue("Steps", String(bundle.manifest.steps.length))); + console.log(keyValue("Skills", String(graph.dependencies.length))); +} finally { + await graph?.cleanup?.(); + await bundle.cleanup?.(); +} +``` + +Use the existing inline load options rather than introducing a second command-specific adapter. + +- [ ] **Step 5: Run focused CLI tests and typecheck** + +```bash +rtk bun test tests/omniskill.test.ts -t "team" +rtk bun test tests/omniskill.test.ts -t "validate" +rtk bun run typecheck +``` + +Expected: validate, install ordering, coordinator next-step output, and cleanup tests pass. + +- [ ] **Step 6: Commit the shared CLI validation path** + +```bash +rtk git add src/omniskill.ts tests/omniskill.test.ts +rtk git commit -m "fix: validate resolved team members in every command" +``` + +### Task 3: Migrate Startup Team to Canonical Role Workflows + +**Files:** +- Modify: `examples/teams/startup-team/workflow.json` +- Modify: `examples/teams/startup-team/workflow.lock.json` +- Delete: `examples/teams/startup-team/skills/ceo/SKILL.md` +- Delete: `examples/teams/startup-team/skills/cto/SKILL.md` +- Delete: `examples/teams/startup-team/skills/product-manager/SKILL.md` +- Delete: `examples/teams/startup-team/skills/web-design/SKILL.md` +- Delete: `examples/teams/startup-team/skills/engineering-manager/SKILL.md` +- Delete: `examples/teams/startup-team/skills/founding-engineer/SKILL.md` +- Delete: `examples/teams/startup-team/skills/qa-lead/SKILL.md` +- Test: `tests/workflow-bundles.test.ts:1080-1215` + +- [ ] **Step 1: Rewrite the startup-team contract test first** + +Change the expected members and role steps to: + +```ts +const canonicalMembers = [ + "catalog:ceo", + "catalog:cto", + "catalog:product-manager", + "catalog:web-design", + "catalog:engineering-manager", + "catalog:founding-engineer", + "catalog:qa-lead", +]; +expect(bundle.manifest.members).toEqual(canonicalMembers); +expect(bundle.manifest.steps.map((step) => [step.id, step.skill])).toEqual([ + ["requirements", "superpowers:brainstorming"], + ["route", "./skills/startup-goal"], + ["strategy", "catalog:ceo"], + ["product", "catalog:product-manager"], + ["design", "catalog:web-design"], + ["technology", "catalog:cto"], + ["delivery", "catalog:engineering-manager"], + ["implementation", "catalog:founding-engineer"], + ["implement", "mattpocock:implement"], + ["qa", "catalog:qa-lead"], +]); +for (const role of canonicalMembers.map((source) => source.slice("catalog:".length))) { + await expect( + stat(join(import.meta.dir, "..", "examples", "teams", "startup-team", "skills", role)), + ).rejects.toThrow(); +} +``` + +Also assert that the expanded graph contains the root plus seven selected child +workflows and seven root edges, and that all seven canonical entry skill names +appear once in the leaf install plan. + +- [ ] **Step 2: Run the startup-team test and verify it fails** + +```bash +rtk bun test tests/workflow-bundles.test.ts -t "startup team" +``` + +Expected: members and steps still reference copied `./skills/` paths. + +- [ ] **Step 3: Replace direct role copies with child workflow sources** + +Keep only these direct non-member skills in `workflow.json`: + +```json +[ + { "source": "./skills/startup-goal", "entry": true }, + { "source": "catalog:ceo" }, + { "source": "catalog:cto" }, + { "source": "catalog:product-manager" }, + { "source": "catalog:web-design" }, + { "source": "catalog:engineering-manager" }, + { "source": "catalog:founding-engineer" }, + { "source": "catalog:qa-lead" }, + { "source": "superpowers:brainstorming", "repo": "obra/superpowers" }, + { + "source": "mattpocock:implement", + "repo": "https://github.com/mattpocock/skills/tree/v1.1.0" + } +] +``` + +Update `members[]` and role `steps[].skill` to the matching `catalog:` values. + +- [ ] **Step 4: Delete the duplicated role skill directories** + +Delete only the seven paths listed in this task. Confirm the coordinator remains: + +```bash +rtk rg --files examples/teams/startup-team/skills +``` + +Expected output: only `examples/teams/startup-team/skills/startup-goal/SKILL.md`. + +- [ ] **Step 5: Regenerate and inspect the expanded lock** + +```bash +rtk bun run dev -- lock examples/teams/startup-team +rtk bun run dev -- validate examples/teams/startup-team +rtk bun run dev -- deps examples/teams/startup-team +``` + +Expected: lock schema `0.2`, eight workflow nodes, seven root-to-member edges, +no deleted team-local role paths, and one leaf dependency per canonical entry +skill after deduplication. + +- [ ] **Step 6: Run focused example tests** + +```bash +rtk bun test tests/workflow-bundles.test.ts -t "startup team" +rtk bun test tests/workflow-bundles.test.ts -t "curated workflow examples" +rtk bun run typecheck +``` + +Expected: all commands pass. + +- [ ] **Step 7: Commit the startup-team migration** + +```bash +rtk git add examples/teams/startup-team tests/workflow-bundles.test.ts +rtk git commit -m "refactor: reuse canonical startup role workflows" +``` + +### Task 4: Point Landing and Documentation at Canonical Role Sources + +**Files:** +- Modify: `landing/lib/landing-content.ts:12-55` +- Modify: `landing/lib/landing-content.ts:74-155` +- Modify: `landing/components/workflow-detail.tsx` +- Modify: `landing/app/workflows/[slug]/page.tsx` +- Modify: `landing/components/workflow-run-demo.tsx:80-115` +- Modify: `tests/landing-app.test.ts:250-300` +- Modify: `tests/landing-app.test.ts:540-565` +- Modify: `AGENTS.md` +- Modify: `docs/architecture.md:135-160` +- Modify: `docs/workflow-author-guide.md:390-425` +- Modify: `tests/readme.test.ts:90-115` + +- [ ] **Step 1: Write failing landing source-link and manifest-parity tests** + +Replace the flat roster assertion with contract assertions: + +```ts +import { githubUrl, startupTeam } from "../landing/lib/landing-content"; + +const memberSkills = startupTeam.members.map(({ skill }) => skill); +expect(manifest.members).toEqual(memberSkills.map((skill) => `catalog:${skill}`)); +expect(startupTeam.localSkillNames).toEqual(["startup-goal"]); +for (const skill of memberSkills) { + expect(startupTeam.skillSourceUrls?.[skill]).toBe( + `${githubUrl}/blob/main/examples/workflows/${skill}/skills/${skill}/SKILL.md`, + ); +} +``` + +Update the workflow-run-demo source test to require both canonical roots: + +```ts +expect(demo).toContain("examples/teams/startup-team/skills/startup-goal/SKILL.md"); +expect(demo).toContain("examples/workflows/${skill}/skills/${skill}/SKILL.md"); +expect(demo).not.toContain("examples/teams/startup-team/skills/${skill}/SKILL.md"); +``` + +- [ ] **Step 2: Run landing tests and verify links still target deleted files** + +```bash +rtk bun test tests/landing-app.test.ts -t "startup-team" +rtk bun test tests/landing-app.test.ts -t "parallel startup-goal" +``` + +Expected: local skill ownership and canonical role URL assertions fail. + +- [ ] **Step 3: Add explicit canonical skill URLs to landing content** + +Add the optional URL map to `CatalogEntryBase` after `sourceUrl: string`, then replace the helper: + +```ts +skillSourceUrls?: Record; + +export function getSkillSourceUrl(workflow: CatalogEntryContent, skill: string) { + const explicitSource = workflow.skillSourceUrls?.[skill]; + if (explicitSource) return explicitSource; + if (!workflow.localSkillNames.includes(skill)) return null; + return `${workflow.sourceUrl.replace("/tree/", "/blob/")}/skills/${skill}/SKILL.md`; +} +``` + +Set `startupTeam.localSkillNames` to `["startup-goal"]` and add: + +```ts +skillSourceUrls: { + "startup-goal": `${githubUrl}/blob/main/examples/teams/startup-team/skills/startup-goal/SKILL.md`, + ceo: `${githubUrl}/blob/main/examples/workflows/ceo/skills/ceo/SKILL.md`, + cto: `${githubUrl}/blob/main/examples/workflows/cto/skills/cto/SKILL.md`, + "product-manager": `${githubUrl}/blob/main/examples/workflows/product-manager/skills/product-manager/SKILL.md`, + "web-design": `${githubUrl}/blob/main/examples/workflows/web-design/skills/web-design/SKILL.md`, + "engineering-manager": `${githubUrl}/blob/main/examples/workflows/engineering-manager/skills/engineering-manager/SKILL.md`, + "founding-engineer": `${githubUrl}/blob/main/examples/workflows/founding-engineer/skills/founding-engineer/SKILL.md`, + "qa-lead": `${githubUrl}/blob/main/examples/workflows/qa-lead/skills/qa-lead/SKILL.md`, +}, +``` + +Rename imports and calls from `getLocalSkillSourceUrl` to `getSkillSourceUrl` in both detail components. + +- [ ] **Step 4: Split workflow-run-demo coordinator and role URL generation** + +Replace the single team root with: + +```ts +const STARTUP_TEAM_SOURCE_ROOT = + "https://github.com/devos-ing/omni-skills/blob/main/examples/teams/startup-team"; +const ROLE_WORKFLOW_SOURCE_ROOT = + "https://github.com/devos-ing/omni-skills/blob/main/examples/workflows"; + +function skillSourceUrl(skill: SkillId) { + return skill === "startup-goal" + ? `${STARTUP_TEAM_SOURCE_ROOT}/skills/startup-goal/SKILL.md` + : `${ROLE_WORKFLOW_SOURCE_ROOT}/${skill}/skills/${skill}/SKILL.md`; +} +``` + +- [ ] **Step 5: Update authoritative team guidance** + +Change `AGENTS.md`, `docs/architecture.md`, and `docs/workflow-author-guide.md` +to state: + +```md +A team coordinator is one declared local entry skill. Every `members[]` source +must be declared in `skills[]` and resolve to a child workflow with exactly one +local entry skill. Member workflow dependencies are expanded recursively; only +the root team install record is written. +``` + +Update `tests/readme.test.ts` to require `resolve to a child workflow` and to +reject the old phrase `unique local declared members`. + +- [ ] **Step 6: Run landing and guidance tests** + +```bash +rtk bun test tests/landing-app.test.ts +rtk bun test tests/landing-content-markdown.test.ts +rtk bun test tests/readme.test.ts +rtk bun run typecheck +``` + +Expected: all tests pass and canonical source URLs point to existing standalone role files. + +- [ ] **Step 7: Commit landing and documentation parity** + +```bash +rtk git add AGENTS.md docs/architecture.md docs/workflow-author-guide.md landing tests/landing-app.test.ts tests/readme.test.ts +rtk git commit -m "docs: link startup team to canonical role workflows" +``` + +### Task 5: Verify Clean Installation and Update the Existing PR + +**Files:** +- Verify: all files changed by Tasks 1-4 +- Generated smoke state: `work/team-workflow-members-smoke/` + +- [ ] **Step 1: Run focused negative and install-order tests** + +```bash +rtk bun test tests/workflow-bundles.test.ts -t "team member" +rtk bun test tests/omniskill.test.ts -t "team" +rtk bun test tests/omniskill.test.ts -t "before target writes" +``` + +Expected: invalid members fail, valid child members expand, and the installer is never called before graph validation succeeds. + +- [ ] **Step 2: Run CLI smokes against the checked-in team** + +```bash +rtk bun run dev -- validate examples/teams/startup-team +rtk bun run dev -- deps examples/teams/startup-team +rtk bun run dev -- lock examples/teams/startup-team +rtk git diff --exit-code -- examples/teams/startup-team/workflow.lock.json +``` + +Expected: validate and deps succeed; regenerating the lock produces no diff. + +- [ ] **Step 3: Run a clean-home install smoke** + +Use a new scratch directory that does not exist before this run: + +```bash +rtk bun run dev -- install examples/teams/startup-team \ + --home work/team-workflow-members-smoke \ + --agents codex +rtk rg --files work/team-workflow-members-smoke/.omniskills/workflows +rtk rg --files work/team-workflow-members-smoke/.agents/skills +``` + +Expected: the workflow-record listing contains only `startup-team.json`; the +skill listing includes `startup-goal`, the seven canonical role entry skills, +and their deduplicated companions. + +- [ ] **Step 4: Run the full repository gate** + +```bash +rtk bun run check +``` + +Expected: Biome, TypeScript, all Bun tests, and the 90% line-coverage gate pass. + +- [ ] **Step 5: Review the complete implementation against the design commit** + +Use fixed point `0d63524`: + +```bash +rtk git diff 0d63524...HEAD --stat +rtk git log 0d63524..HEAD --oneline +rtk git diff --check +``` + +Run the two-axis `mattpocock:code-review` workflow with: + +- standards sources: `AGENTS.md`, `docs/architecture.md`, `biome.json`; +- spec source: `docs/superpowers/specs/2026-07-14-team-workflow-members-design.md`. + +Address every actionable finding with a new red-green test and a focused fix commit. Rerun `rtk bun run check` after the final fix. + +- [ ] **Step 6: Confirm branch and PR scope, then push** + +```bash +rtk git status --short --branch +rtk git log origin/main..HEAD --oneline +rtk git push origin codex/recursive-workflow-skill-tree +rtk gh pr view 373 --repo devos-ing/omni-skills --json url,isDraft,headRefName,baseRefName,state +``` + +Expected: clean branch, PR `#373` remains open as a draft from +`codex/recursive-workflow-skill-tree` to `main`, and all implementation commits +are visible remotely. diff --git a/docs/superpowers/specs/2026-07-14-team-workflow-members-design.md b/docs/superpowers/specs/2026-07-14-team-workflow-members-design.md new file mode 100644 index 00000000..7aaa6494 --- /dev/null +++ b/docs/superpowers/specs/2026-07-14-team-workflow-members-design.md @@ -0,0 +1,157 @@ +# Team Members as Canonical Child Workflows + +## Goal + +Prevent team bundles from copying role `SKILL.md` files that already belong to +standalone workflows. A team should own its coordinator and composition, while +each standalone role workflow owns its role instructions and companion skills. + +`startup-team` remains the public package and the only installed workflow +record. Its callable coordinator remains `$startup-goal`. + +## Current Problem + +`examples/teams/startup-team/skills/` currently contains local copies of CEO, +CTO, product manager, web-design, engineering manager, founding engineer, and +QA lead skills. Equivalent standalone workflows exist under +`examples/workflows/`. The copies differ and can drift because both locations +can be edited independently. + +The current team validator reinforces this duplication by requiring every +`members[]` value to be a declared local skill path. + +## Ownership Model + +- The team owns `skills/startup-goal/SKILL.md`, its unique coordinator. +- Standalone role workflows own their entry skills and companion dependencies. +- A team member is a child workflow reference, not a copied local role skill. +- Installing a team expands child workflows into leaf skills but writes only + the root team install record. + +The standalone role workflow is authoritative. Team-specific copies are not +generated or synchronized. + +## Manifest Contract + +`startup-team` uses the existing string source format: + +```json +{ + "coordinator": "./skills/startup-goal", + "members": [ + "catalog:ceo", + "catalog:cto", + "catalog:product-manager", + "catalog:web-design", + "catalog:engineering-manager", + "catalog:founding-engineer", + "catalog:qa-lead" + ] +} +``` + +Every coordinator and member source must also appear in `skills[]`. Steps refer +to the same declared source strings. The team manifest no longer repeats the +child workflows' companion skills. + +The coordinator remains a declared local skill and the root entry skill. A +member may use any supported child-workflow source form—local workflow path, +repository/subdirectory, `catalog:`, or `installed:`—provided resolution proves +that it is a workflow. + +The manifest schema remains `0.1` because the JSON field shapes do not change. +Team validation semantics intentionally become stricter: local role skills are +no longer valid members. + +## Resolved Team Validation + +Synchronous manifest parsing continues to validate required fields, declared +source references, duplicate source strings, and coordinator/member separation. +Checks that require loading a child source run after dependency resolution. + +For each team member, the runtime must prove that: + +1. The declared source resolves to a child workflow. +2. The selected child workflow declares exactly one `entry: true` skill. +3. The entry skill is a local skill path within that child workflow. +4. The resolved workflow name is unique within the team. +5. The resolved entry skill name is unique within the team. + +The existing highest-SemVer child-workflow selection and cycle detection apply +before these checks. `validate`, `deps`, `lock`, and `install` must use the same +resolved-team validation function so their answers cannot diverge. + +Validation fails before target writes. Errors identify the member source and +the violated rule, including: + +- member did not resolve to a workflow; +- member workflow has no entry skill; +- member workflow has multiple entry skills; +- member entry skill is not local; +- duplicate resolved workflow or entry-skill name; or +- dependency cycle. + +## Resolution and Installation Flow + +1. Load and parse the root team manifest. +2. Resolve the recursive workflow dependency graph. +3. Select the highest workflow version for every logical child workflow. +4. Validate the root coordinator and resolved team-member entry skills. +5. Flatten the selected child workflows into deduplicated leaf skill installs. +6. Validate or generate the expanded lock graph. +7. Install the coordinator, member entry skills, and companion leaf skills. +8. Write one `startup-team` install record containing the resulting artifacts. + +Child workflow records are not registered separately. Installed callable names +remain `$startup-goal`, `$ceo`, `$cto`, `$product-manager`, `$web-design`, +`$engineering-manager`, `$founding-engineer`, and `$qa-lead`. + +## Lock Contract + +The schema `0.2` lock records the root team, child workflow nodes, workflow +edges, exact repository commits, and leaf fingerprints. Regenerating the +`startup-team` lock must capture the canonical standalone role entry skills and +their companion dependencies. Deleted team-local role paths must not remain in +the lock. + +## Repository Migration + +1. Keep `examples/teams/startup-team/skills/startup-goal/SKILL.md`. +2. Delete the seven duplicated team-member skill directories. +3. Replace team member and step sources with `catalog:` references. +4. Remove companion skills now supplied transitively by child workflows. +5. Regenerate `examples/teams/startup-team/workflow.lock.json`. +6. Update architecture, authoring, README, landing, and source-link content. +7. Make landing role links target the canonical standalone workflow skills. + +Existing team manifests with local skill members fail validation with migration +guidance to reference a child workflow. The public install command and package +name remain unchanged. + +## Verification + +Focused tests must prove: + +- local skill members are rejected; +- all supported child-workflow source forms can provide team members; +- zero-entry, multi-entry, non-local-entry, duplicate, and cyclic members fail; +- highest-version workflow selection determines the member entry skill; +- `validate`, `deps`, `lock`, and `install` enforce the same contract; +- each role entry skill installs exactly once; +- companion skills arrive transitively; +- graph failure causes no target writes; +- only the `startup-team` record is written; and +- landing/docs link to canonical standalone role sources. + +Run a clean-home `startup-team` install smoke, the relevant CLI smokes, and +`rtk bun run check`. The repository's 90% line-coverage gate remains required. + +## Non-Goals + +- Registering child workflows as separately installed workflows. +- Moving or rewording the canonical standalone role skills. +- Generating synchronized team-local copies. +- Replacing the team-specific `startup-goal` coordinator. +- Changing role dispatch, approval gates, or runtime subagent behavior. +- Expanding repository URL version parsing beyond the existing dependency + resolution contract. diff --git a/docs/workflow-author-guide.md b/docs/workflow-author-guide.md index 5b2e4578..46df35b5 100644 --- a/docs/workflow-author-guide.md +++ b/docs/workflow-author-guide.md @@ -418,6 +418,12 @@ Install `startup-team` when you want the full role bench. Invoke its bun run dev -- install examples/teams/startup-team ``` +A team coordinator is one declared local entry skill. Every `members[]` source +must be declared in `skills[]` and resolve to a child workflow with exactly one +local entry skill. Member workflow dependencies are expanded recursively; only +the root team install record is written. Local helper skills may still be +declared, but they are not team members. + ## Compatibility Example: Combine RTK, Ponytrail, Superpowers, And Matt Pocock Skills The checked-in `real-engineering` workflow shows how to combine local workflow diff --git a/examples/teams/startup-team/skills/ceo/SKILL.md b/examples/teams/startup-team/skills/ceo/SKILL.md deleted file mode 100644 index 2d2eb5d5..00000000 --- a/examples/teams/startup-team/skills/ceo/SKILL.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -name: ceo -description: "Startup-team CEO role for company direction, tradeoffs, and strategic decisions." ---- - -# CEO - -## Use When - -Use for strategy, positioning, pricing, funding, or company-level tradeoffs. - -## Companions - -- `mattpocock:wayfinder` -- `mattpocock:grill-with-docs` - -If one is unavailable, stop and name it. - -## Do - -1. State the company decision in one sentence. -2. Separate customer, market, product, technical, and funding constraints. -3. Distinguish reversible from irreversible choices. -4. Recommend the smallest evidence-gathering move. - -## Return - -- Decision: recommended company move and accepted tradeoff. -- Evidence: customer, market, funding, or strategic signal. -- Risk: company-level risk requiring owner attention. -- Handoff: decisions downstream roles must preserve or challenge. diff --git a/examples/teams/startup-team/skills/cto/SKILL.md b/examples/teams/startup-team/skills/cto/SKILL.md deleted file mode 100644 index 8e9aa06b..00000000 --- a/examples/teams/startup-team/skills/cto/SKILL.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -name: cto -description: "Startup-team CTO role for architecture, technical risk, and engineering strategy." ---- - -# CTO - -## Use When - -Use for architecture, domain boundaries, platform direction, or technical risk. - -## Companions - -- `mattpocock:codebase-design` -- `mattpocock:domain-modeling` -- `mattpocock:diagnosing-bugs` -- `mattpocock:code-review` - -If one is unavailable, stop and name it. - -## Do - -1. Identify the decision that changes the technical trajectory. -2. Map domain language, module boundaries, and ownership. -3. Separate reversible shortcuts from debt that blocks future product work. -4. Define the next technical move and its verification gate. - -## Return - -- Decision: architecture or platform choice for this slice. -- Evidence: codebase, domain, failure, or review evidence. -- Risk: technical risk most likely to slow future work. -- Handoff: boundary and verification gate implementation must preserve. diff --git a/examples/teams/startup-team/skills/engineering-manager/SKILL.md b/examples/teams/startup-team/skills/engineering-manager/SKILL.md deleted file mode 100644 index 8d3f6245..00000000 --- a/examples/teams/startup-team/skills/engineering-manager/SKILL.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -name: engineering-manager -description: "Startup-team engineering manager role for delivery sequencing and quality gates." ---- - -# Engineering Manager - -## Use When - -Use for delivery sequencing, ownership, blockers, or quality gates. - -## Companions - -- `superpowers:writing-plans` -- `mattpocock:tdd` -- `mattpocock:diagnosing-bugs` -- `mattpocock:code-review` - -If one is unavailable, stop and name it. - -## Do - -1. Identify the smallest shippable result and largest delivery risk. -2. Sequence work so every step leaves a verifiable repository state. -3. Assign quality gates by blast radius. -4. Escalate missing ownership, acceptance criteria, or decisions. - -## Return - -- Decision: implementation sequence for the next slice. -- Evidence: dependency, ownership, and quality-gate rationale. -- Risk: delivery blocker or ownership ambiguity. -- Handoff: ordered plan and gate for implementation and QA. diff --git a/examples/teams/startup-team/skills/founding-engineer/SKILL.md b/examples/teams/startup-team/skills/founding-engineer/SKILL.md deleted file mode 100644 index 4522bb1a..00000000 --- a/examples/teams/startup-team/skills/founding-engineer/SKILL.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -name: founding-engineer -description: "Startup-team founding engineer role for framing an approved implementation slice and handing it to the implementation phase." ---- - -# Founding Engineer - -## Use When - -Use when the approved slice needs a precise implementation frame before execution. - -## Companions - -- `implement` for executing the approved handoff. -- `mattpocock:tdd` for selecting the test seam. - -If one is unavailable, stop and name it. - -## Do - -1. Read the plan, acceptance criteria, and local repo instructions. -2. Define the smallest correct implementation slice, affected boundaries, test seam, risks, and completion checks. -3. Do not edit files or run implementation commands; prepare the implementation frame and handoff for `implement`. - -## Return - -- Change: implementation frame prepared with no repository changes. -- Evidence: plan, acceptance criteria, affected boundaries, and test seam inspected. -- Risk: blocker, unresolved technical choice, or missing acceptance detail. -- Handoff: `implement` receives the slice, expected files, test seam, and completion checks. diff --git a/examples/teams/startup-team/skills/product-manager/SKILL.md b/examples/teams/startup-team/skills/product-manager/SKILL.md deleted file mode 100644 index 51e0741b..00000000 --- a/examples/teams/startup-team/skills/product-manager/SKILL.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -name: product-manager -description: "Startup-team product manager role for discovery, PRDs, and issue slicing." ---- - -# Product Manager - -## Use When - -Use for customer value, product scope, acceptance criteria, or issue slicing. - -## Companions - -- `superpowers:brainstorming` -- `mattpocock:to-spec` -- `mattpocock:to-tickets` -- `superpowers:writing-plans` - -If one is unavailable, stop and name it. - -## Do - -1. Name the target user, pain, and desired behavior change. -2. Separate must-have behavior from launch polish. -3. Write acceptance criteria engineering and QA can verify. -4. Slice work so each issue creates visible product progress. - -## Return - -- Decision: must-have scope for this slice. -- Evidence: customer signal or approved product rationale. -- Risk: unresolved product or learning assumption. -- Handoff: acceptance criteria and issue boundary for delivery. diff --git a/examples/teams/startup-team/skills/qa-lead/SKILL.md b/examples/teams/startup-team/skills/qa-lead/SKILL.md deleted file mode 100644 index 14998d91..00000000 --- a/examples/teams/startup-team/skills/qa-lead/SKILL.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -name: qa-lead -description: "Startup-team QA lead role for acceptance checks, regression risk, and release verification." ---- - -# QA Lead - -## Use When - -Use for acceptance, regression risk, and release verification. - -## Companions - -- `mattpocock:code-review` -- `mattpocock:diagnosing-bugs` -- `superpowers:verification-before-completion` - -If one is unavailable, stop and name it. - -## Do - -1. Restate the user-visible behavior that must be true. -2. Verify the highest-risk regression paths with concrete evidence. -3. Separate verified facts from residual risk. -4. Run `superpowers:verification-before-completion` before recommending release or block. - -## Return - -- Decision: release, block, or next verification step. -- Evidence: checks, reproduction steps, and command output. -- Risk: unverified behavior and why it matters. -- Handoff: release recommendation or actionable blocker. diff --git a/examples/teams/startup-team/skills/web-design/SKILL.md b/examples/teams/startup-team/skills/web-design/SKILL.md deleted file mode 100644 index d9ba2ad2..00000000 --- a/examples/teams/startup-team/skills/web-design/SKILL.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -name: web-design -description: "Startup-team web-design role for interface direction, responsive interaction states, and animation review." ---- - -# Web Design - -## Use When - -Use for customer-facing hierarchy, responsive interaction, accessibility, or motion. - -## Companions - -- `interface-craft:design-engineering` -- `interface-craft:motion-vocabulary` -- `interface-craft:fluid-interface-design` when gestures are in scope. -- `interface-craft:motion-review` - -If one is unavailable, stop and name it. - -## Do - -1. Define the target user, job, hierarchy, states, responsive behavior, and accessibility constraints. -2. Require a user benefit, frequency, and reduced-motion behavior for every motion. -3. Name interactions before implementation and use the relevant interface-craft review. -4. Run `interface-craft:motion-review` on every changed animation; return `Before | After | Why` and an explicit **Approve** or **Block** verdict. - -## Return - -- Decision: implementable interface and motion direction. -- Evidence: hierarchy, state, responsive, accessibility, and review findings. -- Risk: unresolved usability or motion issue; **Block** is a release gate. -- Handoff: implementation requirements and QA acceptance checks. diff --git a/examples/teams/startup-team/workflow.json b/examples/teams/startup-team/workflow.json index 9ec2aad0..18a05dca 100644 --- a/examples/teams/startup-team/workflow.json +++ b/examples/teams/startup-team/workflow.json @@ -6,13 +6,13 @@ "description": "Install a startup team as one goal-oriented Omniskills bundle: a startup-goal coordinator plus CEO, CTO, product manager, web-design lead, engineering manager, founding engineer, and QA lead.", "coordinator": "./skills/startup-goal", "members": [ - "./skills/ceo", - "./skills/cto", - "./skills/product-manager", - "./skills/web-design", - "./skills/engineering-manager", - "./skills/founding-engineer", - "./skills/qa-lead" + "catalog:ceo", + "catalog:cto", + "catalog:product-manager", + "catalog:web-design", + "catalog:engineering-manager", + "catalog:founding-engineer", + "catalog:qa-lead" ], "skills": [ { @@ -20,90 +20,30 @@ "entry": true }, { - "source": "./skills/ceo" + "source": "catalog:ceo" }, { - "source": "./skills/cto" + "source": "catalog:cto" }, { - "source": "./skills/product-manager" + "source": "catalog:product-manager" }, { - "source": "./skills/web-design" + "source": "catalog:web-design" }, { - "source": "./skills/engineering-manager" + "source": "catalog:engineering-manager" }, { - "source": "./skills/founding-engineer" + "source": "catalog:founding-engineer" }, { - "source": "./skills/qa-lead" - }, - { - "source": "emilkowalski:emil-design-eng", - "repo": "emilkowalski/skills" - }, - { - "source": "emilkowalski:animation-vocabulary", - "repo": "emilkowalski/skills" - }, - { - "source": "emilkowalski:apple-design", - "repo": "emilkowalski/skills" - }, - { - "source": "emilkowalski:review-animations", - "repo": "emilkowalski/skills" + "source": "catalog:qa-lead" }, { "source": "superpowers:brainstorming", "repo": "obra/superpowers" }, - { - "source": "superpowers:writing-plans", - "repo": "obra/superpowers" - }, - { - "source": "superpowers:verification-before-completion", - "repo": "obra/superpowers" - }, - { - "source": "mattpocock:wayfinder", - "repo": "https://github.com/mattpocock/skills/tree/v1.1.0" - }, - { - "source": "mattpocock:grill-with-docs", - "repo": "https://github.com/mattpocock/skills/tree/v1.1.0" - }, - { - "source": "mattpocock:to-spec", - "repo": "https://github.com/mattpocock/skills/tree/v1.1.0" - }, - { - "source": "mattpocock:to-tickets", - "repo": "https://github.com/mattpocock/skills/tree/v1.1.0" - }, - { - "source": "mattpocock:codebase-design", - "repo": "https://github.com/mattpocock/skills/tree/v1.1.0" - }, - { - "source": "mattpocock:domain-modeling", - "repo": "https://github.com/mattpocock/skills/tree/v1.1.0" - }, - { - "source": "mattpocock:tdd", - "repo": "https://github.com/mattpocock/skills/tree/v1.1.0" - }, - { - "source": "mattpocock:diagnosing-bugs", - "repo": "https://github.com/mattpocock/skills/tree/v1.1.0" - }, - { - "source": "mattpocock:code-review", - "repo": "https://github.com/mattpocock/skills/tree/v1.1.0" - }, { "source": "mattpocock:implement", "repo": "https://github.com/mattpocock/skills/tree/v1.1.0" @@ -127,33 +67,33 @@ { "id": "strategy", "title": "Clarify company direction", - "skill": "./skills/ceo", + "skill": "catalog:ceo", "gate": "human_approval" }, { "id": "product", "title": "Shape product scope", - "skill": "./skills/product-manager" + "skill": "catalog:product-manager" }, { "id": "design", "title": "Set web interface direction and motion quality", - "skill": "./skills/web-design" + "skill": "catalog:web-design" }, { "id": "technology", "title": "Set technical direction", - "skill": "./skills/cto" + "skill": "catalog:cto" }, { "id": "delivery", "title": "Plan engineering execution", - "skill": "./skills/engineering-manager" + "skill": "catalog:engineering-manager" }, { "id": "implementation", "title": "Frame the implementation slice", - "skill": "./skills/founding-engineer" + "skill": "catalog:founding-engineer" }, { "id": "implement", @@ -163,7 +103,7 @@ { "id": "qa", "title": "Verify release readiness", - "skill": "./skills/qa-lead" + "skill": "catalog:qa-lead" } ] } diff --git a/examples/teams/startup-team/workflow.lock.json b/examples/teams/startup-team/workflow.lock.json index 707a186d..7e9d1565 100644 --- a/examples/teams/startup-team/workflow.lock.json +++ b/examples/teams/startup-team/workflow.lock.json @@ -1,105 +1,137 @@ { - "schemaVersion": "0.1", + "schemaVersion": "0.2", "workflow": "startup-team", "workflowVersion": "0.2.0", - "generatedAt": "2026-07-13T18:02:25.039Z", - "skills": [ + "generatedAt": "2026-07-14T09:18:54.936Z", + "workflows": [ { - "source": "./skills/startup-goal", - "resolvedName": "startup-goal", - "kind": "local", - "hash": "sha256:77c4e62583ebac9854618464495338793fdc604034e2824f2dc7b997d77a62c2" + "id": "workflow:startup-team@0.2.0", + "name": "startup-team", + "version": "0.2.0", + "source": { + "kind": "root" + } }, { - "source": "./skills/ceo", - "resolvedName": "ceo", - "kind": "local", - "hash": "sha256:1061ba4bcbd4c75660ab08c6f22cac59c3b0a671cf17d4d829c0211300555b64" + "id": "workflow:ceo@0.1.1", + "name": "ceo", + "version": "0.1.1", + "source": { + "kind": "git", + "url": "https://github.com/devos-ing/omni-skills.git#examples/workflows/ceo", + "commit": "45e8b05fcce1140b9ed06559bb27430d99761407", + "subdirectory": "examples/workflows/ceo" + } }, { - "source": "./skills/cto", - "resolvedName": "cto", - "kind": "local", - "hash": "sha256:25cc20e161d81e8a7589a933dcf720ddcc74469b0fea8726dfe659e31405b848" + "id": "workflow:cto@0.1.1", + "name": "cto", + "version": "0.1.1", + "source": { + "kind": "git", + "url": "https://github.com/devos-ing/omni-skills.git#examples/workflows/cto", + "commit": "45e8b05fcce1140b9ed06559bb27430d99761407", + "subdirectory": "examples/workflows/cto" + } }, { - "source": "./skills/product-manager", - "resolvedName": "product-manager", - "kind": "local", - "hash": "sha256:f1660fd825b3975c844229f70020ab6dc2e0957b1305befc20ce97c10a5b7207" + "id": "workflow:product-manager@0.1.1", + "name": "product-manager", + "version": "0.1.1", + "source": { + "kind": "git", + "url": "https://github.com/devos-ing/omni-skills.git#examples/workflows/product-manager", + "commit": "45e8b05fcce1140b9ed06559bb27430d99761407", + "subdirectory": "examples/workflows/product-manager" + } }, { - "source": "./skills/web-design", - "resolvedName": "web-design", - "kind": "local", - "hash": "sha256:67261d9b6ee94a368d85adea8113c5ddc65009fb6a120a2da6e44376e95aa21f" + "id": "workflow:web-design@0.1.0", + "name": "web-design", + "version": "0.1.0", + "source": { + "kind": "git", + "url": "https://github.com/devos-ing/omni-skills.git#examples/workflows/web-design", + "commit": "45e8b05fcce1140b9ed06559bb27430d99761407", + "subdirectory": "examples/workflows/web-design" + } }, { - "source": "./skills/engineering-manager", - "resolvedName": "engineering-manager", - "kind": "local", - "hash": "sha256:04212171f62b217d8a2a375b6df5a322ad9368b3133521d51c803f74e712ae2b" + "id": "workflow:engineering-manager@0.1.1", + "name": "engineering-manager", + "version": "0.1.1", + "source": { + "kind": "git", + "url": "https://github.com/devos-ing/omni-skills.git#examples/workflows/engineering-manager", + "commit": "45e8b05fcce1140b9ed06559bb27430d99761407", + "subdirectory": "examples/workflows/engineering-manager" + } }, { - "source": "./skills/founding-engineer", - "resolvedName": "founding-engineer", - "kind": "local", - "hash": "sha256:e14da40516ae72766e406371473f2c2e7e46589deef0c19bb23d92808d5ceb07" + "id": "workflow:founding-engineer@0.1.1", + "name": "founding-engineer", + "version": "0.1.1", + "source": { + "kind": "git", + "url": "https://github.com/devos-ing/omni-skills.git#examples/workflows/founding-engineer", + "commit": "45e8b05fcce1140b9ed06559bb27430d99761407", + "subdirectory": "examples/workflows/founding-engineer" + } }, { - "source": "./skills/qa-lead", - "resolvedName": "qa-lead", - "kind": "local", - "hash": "sha256:c6d13166af6a97fd2ef859d3414fa1e9211da153cab426cf46408fa6aa6d4af3" + "id": "workflow:qa-lead@0.1.1", + "name": "qa-lead", + "version": "0.1.1", + "source": { + "kind": "git", + "url": "https://github.com/devos-ing/omni-skills.git#examples/workflows/qa-lead", + "commit": "45e8b05fcce1140b9ed06559bb27430d99761407", + "subdirectory": "examples/workflows/qa-lead" + } + } + ], + "edges": [ + { + "from": "workflow:startup-team@0.2.0", + "to": "workflow:ceo@0.1.1" }, { - "source": "emilkowalski:emil-design-eng", - "resolvedName": "emilkowalski:emil-design-eng", - "kind": "external", - "repo": "emilkowalski/skills", - "hash": "sha256:c98e0e85967f367ece5fd23f9b2bcef62c1a9d548579472bb829464c3ebdf461" + "from": "workflow:startup-team@0.2.0", + "to": "workflow:cto@0.1.1" }, { - "source": "emilkowalski:animation-vocabulary", - "resolvedName": "emilkowalski:animation-vocabulary", - "kind": "external", - "repo": "emilkowalski/skills", - "hash": "sha256:17043916f71310aff8b03af847f4cf1280496807113072ff9fb836e64f90f133" + "from": "workflow:startup-team@0.2.0", + "to": "workflow:product-manager@0.1.1" }, { - "source": "emilkowalski:apple-design", - "resolvedName": "emilkowalski:apple-design", - "kind": "external", - "repo": "emilkowalski/skills", - "hash": "sha256:4f2d0e6e554a9b8d313ae3b32a66f9e4f1ba4c9f491e0f050ad077e100eeefa3" + "from": "workflow:startup-team@0.2.0", + "to": "workflow:web-design@0.1.0" }, { - "source": "emilkowalski:review-animations", - "resolvedName": "emilkowalski:review-animations", - "kind": "external", - "repo": "emilkowalski/skills", - "hash": "sha256:f9266e7cdefa9ceadc60558f201618755382f03b06d5ab37d2ac73bdb7807b98" + "from": "workflow:startup-team@0.2.0", + "to": "workflow:engineering-manager@0.1.1" }, { - "source": "superpowers:brainstorming", - "resolvedName": "superpowers-brainstorming", - "kind": "external", - "repo": "obra/superpowers", - "hash": "sha256:a688fac4f89e4b3481c2a2804c54872ef5186ee8ab50103b5ac9777737234387" + "from": "workflow:startup-team@0.2.0", + "to": "workflow:founding-engineer@0.1.1" }, { - "source": "superpowers:writing-plans", - "resolvedName": "superpowers-writing-plans", - "kind": "external", - "repo": "obra/superpowers", - "hash": "sha256:af085fb88831241d778d94c43b0f2b8ecdddfa250851dc08a977233d031dede6" + "from": "workflow:startup-team@0.2.0", + "to": "workflow:qa-lead@0.1.1" + } + ], + "skills": [ + { + "source": "./skills/startup-goal", + "resolvedName": "startup-goal", + "kind": "local", + "hash": "sha256:77c4e62583ebac9854618464495338793fdc604034e2824f2dc7b997d77a62c2" }, { - "source": "superpowers:verification-before-completion", - "resolvedName": "superpowers-verification-before-completion", - "kind": "external", - "repo": "obra/superpowers", - "hash": "sha256:26401a7561086d127295b4267e19ccbc44a8b0d04ca519723a8a70301ae6efdf" + "source": "workflow:ceo@0.1.1#./skills/ceo", + "resolvedName": "ceo", + "kind": "local", + "hash": "sha256:b0e1abf139bef48618da9e1727ecc4ec35d427b949771f959c4569fdaafefd19" }, { "source": "mattpocock:wayfinder", @@ -115,6 +147,53 @@ "repo": "https://github.com/mattpocock/skills/tree/v1.1.0", "hash": "sha256:a7e2ffc2e216483f140c486c5e1b5e3e66d6ca7cf47980357069b21887645069" }, + { + "source": "workflow:cto@0.1.1#./skills/cto", + "resolvedName": "cto", + "kind": "local", + "hash": "sha256:537d4753b34622b969200709611d0751263e807a0500f02a1b35a5157b60320b" + }, + { + "source": "mattpocock:codebase-design", + "resolvedName": "codebase-design", + "kind": "external", + "repo": "https://github.com/mattpocock/skills/tree/v1.1.0", + "hash": "sha256:452bfb044551a8177528b7df68e204e6a77b8a7f89daa741ef659f652c441376" + }, + { + "source": "mattpocock:domain-modeling", + "resolvedName": "domain-modeling", + "kind": "external", + "repo": "https://github.com/mattpocock/skills/tree/v1.1.0", + "hash": "sha256:f01e41e3fdaf3c4d4c20ddea9eb00e8330003d91bb564ef4518aaee856d4bf69" + }, + { + "source": "mattpocock:diagnosing-bugs", + "resolvedName": "diagnosing-bugs", + "kind": "external", + "repo": "https://github.com/mattpocock/skills/tree/v1.1.0", + "hash": "sha256:8148a4181f76442579999629563f08f31fa3784955584e781a190b64d65a1501" + }, + { + "source": "mattpocock:code-review", + "resolvedName": "code-review", + "kind": "external", + "repo": "https://github.com/mattpocock/skills/tree/v1.1.0", + "hash": "sha256:913b01e36a6d3e28173b68e3147295754dd1ff2b91dbc23ebb1161cc687c91e6" + }, + { + "source": "workflow:product-manager@0.1.1#./skills/product-manager", + "resolvedName": "product-manager", + "kind": "local", + "hash": "sha256:4d0db8b9f5e72b0b8708685ad2d4998373454719efea402f60f81fc1ca877970" + }, + { + "source": "superpowers:brainstorming", + "resolvedName": "superpowers-brainstorming", + "kind": "external", + "repo": "obra/superpowers", + "hash": "sha256:a688fac4f89e4b3481c2a2804c54872ef5186ee8ab50103b5ac9777737234387" + }, { "source": "mattpocock:to-spec", "resolvedName": "to-spec", @@ -130,18 +209,51 @@ "hash": "sha256:49679c184e8970591136c431ba4fa00a4890aff23a2701c194465f79007a23c9" }, { - "source": "mattpocock:codebase-design", - "resolvedName": "codebase-design", + "source": "superpowers:writing-plans", + "resolvedName": "superpowers-writing-plans", "kind": "external", - "repo": "https://github.com/mattpocock/skills/tree/v1.1.0", - "hash": "sha256:452bfb044551a8177528b7df68e204e6a77b8a7f89daa741ef659f652c441376" + "repo": "obra/superpowers", + "hash": "sha256:af085fb88831241d778d94c43b0f2b8ecdddfa250851dc08a977233d031dede6" }, { - "source": "mattpocock:domain-modeling", - "resolvedName": "domain-modeling", + "source": "workflow:web-design@0.1.0#./skills/web-design", + "resolvedName": "web-design", + "kind": "local", + "hash": "sha256:5cd02b629f13409c04a8f28f92909aeae7ca7d392eba6b95587876b662814f88" + }, + { + "source": "emilkowalski:emil-design-eng", + "resolvedName": "emilkowalski:emil-design-eng", "kind": "external", - "repo": "https://github.com/mattpocock/skills/tree/v1.1.0", - "hash": "sha256:f01e41e3fdaf3c4d4c20ddea9eb00e8330003d91bb564ef4518aaee856d4bf69" + "repo": "emilkowalski/skills", + "hash": "sha256:c98e0e85967f367ece5fd23f9b2bcef62c1a9d548579472bb829464c3ebdf461" + }, + { + "source": "emilkowalski:animation-vocabulary", + "resolvedName": "emilkowalski:animation-vocabulary", + "kind": "external", + "repo": "emilkowalski/skills", + "hash": "sha256:17043916f71310aff8b03af847f4cf1280496807113072ff9fb836e64f90f133" + }, + { + "source": "emilkowalski:apple-design", + "resolvedName": "emilkowalski:apple-design", + "kind": "external", + "repo": "emilkowalski/skills", + "hash": "sha256:4f2d0e6e554a9b8d313ae3b32a66f9e4f1ba4c9f491e0f050ad077e100eeefa3" + }, + { + "source": "emilkowalski:review-animations", + "resolvedName": "emilkowalski:review-animations", + "kind": "external", + "repo": "emilkowalski/skills", + "hash": "sha256:f9266e7cdefa9ceadc60558f201618755382f03b06d5ab37d2ac73bdb7807b98" + }, + { + "source": "workflow:engineering-manager@0.1.1#./skills/engineering-manager", + "resolvedName": "engineering-manager", + "kind": "local", + "hash": "sha256:83e32c2d3a29d869085cb4735a6c1c8259e1b68acb6a92ddc2f42d9c331a8291" }, { "source": "mattpocock:tdd", @@ -151,18 +263,23 @@ "hash": "sha256:e845c35d776277cb08cbf3b68ea32b28e181069620c4a6b9d9642871184105f8" }, { - "source": "mattpocock:diagnosing-bugs", - "resolvedName": "diagnosing-bugs", - "kind": "external", - "repo": "https://github.com/mattpocock/skills/tree/v1.1.0", - "hash": "sha256:8148a4181f76442579999629563f08f31fa3784955584e781a190b64d65a1501" + "source": "workflow:founding-engineer@0.1.1#./skills/founding-engineer", + "resolvedName": "founding-engineer", + "kind": "local", + "hash": "sha256:31849f572dc09e4df212fe66981a04cb67749364441501526d0c48ebb0175490" }, { - "source": "mattpocock:code-review", - "resolvedName": "code-review", + "source": "superpowers:verification-before-completion", + "resolvedName": "superpowers-verification-before-completion", "kind": "external", - "repo": "https://github.com/mattpocock/skills/tree/v1.1.0", - "hash": "sha256:913b01e36a6d3e28173b68e3147295754dd1ff2b91dbc23ebb1161cc687c91e6" + "repo": "obra/superpowers", + "hash": "sha256:26401a7561086d127295b4267e19ccbc44a8b0d04ca519723a8a70301ae6efdf" + }, + { + "source": "workflow:qa-lead@0.1.1#./skills/qa-lead", + "resolvedName": "qa-lead", + "kind": "local", + "hash": "sha256:a9c4e9f241b612ab0c4302bb847b5c0232c32210b599b616c6c388f3b899b647" }, { "source": "mattpocock:implement", diff --git a/examples/workflows/founding-engineer/workflow.json b/examples/workflows/founding-engineer/workflow.json index 4a617704..77faa0ce 100644 --- a/examples/workflows/founding-engineer/workflow.json +++ b/examples/workflows/founding-engineer/workflow.json @@ -9,7 +9,8 @@ "entry": true }, { - "source": "implement" + "source": "mattpocock:implement", + "repo": "https://github.com/mattpocock/skills/tree/v1.1.0" }, { "source": "mattpocock:tdd", @@ -38,7 +39,7 @@ { "id": "implement", "title": "Implement the planned change", - "skill": "implement" + "skill": "mattpocock:implement" }, { "id": "tdd", diff --git a/examples/workflows/founding-engineer/workflow.lock.json b/examples/workflows/founding-engineer/workflow.lock.json index 9f8649e4..6136bae5 100644 --- a/examples/workflows/founding-engineer/workflow.lock.json +++ b/examples/workflows/founding-engineer/workflow.lock.json @@ -1,8 +1,19 @@ { - "schemaVersion": "0.1", + "schemaVersion": "0.2", "workflow": "founding-engineer", "workflowVersion": "0.1.1", - "generatedAt": "2026-07-11T16:12:50.563Z", + "generatedAt": "2026-07-14T09:18:44.589Z", + "workflows": [ + { + "id": "workflow:founding-engineer@0.1.1", + "name": "founding-engineer", + "version": "0.1.1", + "source": { + "kind": "root" + } + } + ], + "edges": [], "skills": [ { "source": "./skills/founding-engineer", @@ -11,10 +22,11 @@ "hash": "sha256:31849f572dc09e4df212fe66981a04cb67749364441501526d0c48ebb0175490" }, { - "source": "implement", + "source": "mattpocock:implement", "resolvedName": "implement", "kind": "external", - "hash": "sha256:16f51d5ecc0b385c98451eb9da8edc19bf16bd27d7c65321abdd26592b1df311" + "repo": "https://github.com/mattpocock/skills/tree/v1.1.0", + "hash": "sha256:1ad478cef4ccf1cde4cfff91cd551cb781e21da4e6d4940ef4df64c209db35cc" }, { "source": "mattpocock:tdd", diff --git a/examples/workflows/skill-tree-demo/README.md b/examples/workflows/skill-tree-demo/README.md new file mode 100644 index 00000000..622a9ebf --- /dev/null +++ b/examples/workflows/skill-tree-demo/README.md @@ -0,0 +1,10 @@ +# Skill Tree Demo + +This parent lists only its local entry skill and the direct `../cto` child +workflow. Omniskills scans the child workflow and installs its leaf skills. + +```bash +omniskill deps examples/workflows/skill-tree-demo +omniskill lock examples/workflows/skill-tree-demo +omniskill install examples/workflows/skill-tree-demo +``` diff --git a/examples/workflows/skill-tree-demo/skills/skill-tree-demo/SKILL.md b/examples/workflows/skill-tree-demo/skills/skill-tree-demo/SKILL.md new file mode 100644 index 00000000..cc5d015e --- /dev/null +++ b/examples/workflows/skill-tree-demo/skills/skill-tree-demo/SKILL.md @@ -0,0 +1,8 @@ +--- +name: skill-tree-demo +description: "Use when demonstrating recursive Omniskills workflow dependencies." +--- + +# Skill Tree Demo + +Coordinate the parent request, then use the installed CTO child workflow skills. diff --git a/examples/workflows/skill-tree-demo/workflow.json b/examples/workflows/skill-tree-demo/workflow.json new file mode 100644 index 00000000..891e1710 --- /dev/null +++ b/examples/workflows/skill-tree-demo/workflow.json @@ -0,0 +1,27 @@ +{ + "schemaVersion": "0.1", + "name": "skill-tree-demo", + "version": "0.1.0", + "description": "Demonstrates a parent that declares one direct child workflow.", + "skills": [ + { + "source": "./skills/skill-tree-demo", + "entry": true + }, + { + "source": "../cto" + } + ], + "steps": [ + { + "id": "coordinate", + "title": "Coordinate the skill tree", + "skill": "./skills/skill-tree-demo" + }, + { + "id": "architecture", + "title": "Run the CTO child workflow", + "skill": "../cto" + } + ] +} diff --git a/examples/workflows/skill-tree-demo/workflow.lock.json b/examples/workflows/skill-tree-demo/workflow.lock.json new file mode 100644 index 00000000..caebe9aa --- /dev/null +++ b/examples/workflows/skill-tree-demo/workflow.lock.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": "0.2", + "workflow": "skill-tree-demo", + "workflowVersion": "0.1.0", + "generatedAt": "2026-07-14T07:48:54.368Z", + "workflows": [ + { + "id": "workflow:skill-tree-demo@0.1.0", + "name": "skill-tree-demo", + "version": "0.1.0", + "source": { + "kind": "root" + } + }, + { + "id": "workflow:cto@0.1.1", + "name": "cto", + "version": "0.1.1", + "source": { + "kind": "local", + "path": "../cto" + } + } + ], + "edges": [ + { + "from": "workflow:skill-tree-demo@0.1.0", + "to": "workflow:cto@0.1.1" + } + ], + "skills": [ + { + "source": "./skills/skill-tree-demo", + "resolvedName": "skill-tree-demo", + "kind": "local", + "hash": "sha256:473a43c02d642775b7210b749a592c84cd7df6fcfb2816ff08ddbe38d69f9173" + }, + { + "source": "../cto/skills/cto", + "resolvedName": "cto", + "kind": "local", + "hash": "sha256:537d4753b34622b969200709611d0751263e807a0500f02a1b35a5157b60320b" + }, + { + "source": "mattpocock:codebase-design", + "resolvedName": "codebase-design", + "kind": "external", + "repo": "https://github.com/mattpocock/skills/tree/v1.1.0", + "hash": "sha256:452bfb044551a8177528b7df68e204e6a77b8a7f89daa741ef659f652c441376" + }, + { + "source": "mattpocock:domain-modeling", + "resolvedName": "domain-modeling", + "kind": "external", + "repo": "https://github.com/mattpocock/skills/tree/v1.1.0", + "hash": "sha256:f01e41e3fdaf3c4d4c20ddea9eb00e8330003d91bb564ef4518aaee856d4bf69" + }, + { + "source": "mattpocock:diagnosing-bugs", + "resolvedName": "diagnosing-bugs", + "kind": "external", + "repo": "https://github.com/mattpocock/skills/tree/v1.1.0", + "hash": "sha256:8148a4181f76442579999629563f08f31fa3784955584e781a190b64d65a1501" + }, + { + "source": "mattpocock:code-review", + "resolvedName": "code-review", + "kind": "external", + "repo": "https://github.com/mattpocock/skills/tree/v1.1.0", + "hash": "sha256:913b01e36a6d3e28173b68e3147295754dd1ff2b91dbc23ebb1161cc687c91e6" + } + ] +} diff --git a/landing/app/workflows/[slug]/page.tsx b/landing/app/workflows/[slug]/page.tsx index f29e5b55..882d8b69 100644 --- a/landing/app/workflows/[slug]/page.tsx +++ b/landing/app/workflows/[slug]/page.tsx @@ -3,7 +3,7 @@ import Link from "next/link"; import { notFound } from "next/navigation"; import { CopyableInstallCommand } from "../../../components/copyable-install-command"; import { WorkflowAvatar } from "../../../components/workflow-avatar"; -import { catalogEntries, getLocalSkillSourceUrl } from "../../../lib/landing-content"; +import { catalogEntries, getSkillSourceUrl } from "../../../lib/landing-content"; interface WorkflowPageProps { params: Promise<{ @@ -25,7 +25,7 @@ export default async function WorkflowPage({ params }: WorkflowPageProps) { notFound(); } - const entrySkillSourceUrl = getLocalSkillSourceUrl(workflow, workflow.entrySkill); + const entrySkillSourceUrl = getSkillSourceUrl(workflow, workflow.entrySkill); return (
@@ -103,7 +103,7 @@ export default async function WorkflowPage({ params }: WorkflowPageProps) {
{workflow.diagramSteps.map((step, index) => { - const skillSourceUrl = getLocalSkillSourceUrl(workflow, step.skill); + const skillSourceUrl = getSkillSourceUrl(workflow, step.skill); return (
diff --git a/landing/components/workflow-detail.tsx b/landing/components/workflow-detail.tsx index 80089ca4..e8687806 100644 --- a/landing/components/workflow-detail.tsx +++ b/landing/components/workflow-detail.tsx @@ -1,5 +1,5 @@ import { ArrowRight, ExternalLink, GitBranch, Zap } from "lucide-react"; -import { getLocalSkillSourceUrl, type WorkflowCardContent } from "../lib/landing-content"; +import { getSkillSourceUrl, type WorkflowCardContent } from "../lib/landing-content"; import { WorkflowAvatar } from "./workflow-avatar"; interface WorkflowDetailProps { @@ -7,7 +7,7 @@ interface WorkflowDetailProps { } export function WorkflowDetail({ workflow }: WorkflowDetailProps) { - const entrySkillSourceUrl = getLocalSkillSourceUrl(workflow, workflow.entrySkill); + const entrySkillSourceUrl = getSkillSourceUrl(workflow, workflow.entrySkill); return (