Skip to content

Conversation

@sisyphus-dev-ai
Copy link
Collaborator

@sisyphus-dev-ai sisyphus-dev-ai commented Jan 2, 2026

Summary

  • Upgrade frontmatter parser to use js-yaml for complex YAML support (speckit compatibility)
  • Add HandoffDefinition interface for speckit-style workflow transitions
  • Update CommandFrontmatter and CommandDefinition to include handoffs
  • Add comprehensive tests for backward compatibility and complex YAML parsing

Changes

Core Changes

  • src/shared/frontmatter.ts: Replace manual line-by-line parsing with js-yaml for full YAML spec support
  • src/features/claude-code-command-loader/types.ts: Add HandoffDefinition interface and update command types
  • src/features/claude-code-command-loader/loader.ts: Pass handoffs through to command definitions

Supporting Changes

  • src/hooks/auto-slash-command/executor.ts: Add explicit type parameter for frontmatter parsing
  • src/tools/slashcommand/tools.ts: Add explicit type parameter for frontmatter parsing
  • src/features/opencode-skill-loader/loader.test.ts: Update test for new YAML parsing behavior

Tests

  • src/shared/frontmatter.test.ts: New comprehensive test suite covering:
    • Backward compatibility (simple key-value pairs)
    • Boolean value parsing
    • Complex array frontmatter (speckit handoffs)
    • Nested objects
    • Edge cases (no frontmatter, empty frontmatter, invalid YAML, CRLF)

Handoff Format (speckit)

Commands can now use complex handoffs in frontmatter:

---
description: Execute planning workflow
handoffs: 
  - label: Create Tasks
    agent: speckit.tasks
    prompt: Break the plan into tasks
    send: true
  - label: Create Checklist
    agent: speckit.checklist
    prompt: Create a checklist
---

Closes #407


Summary by cubic

Adds speckit-style handoffs to commands by switching frontmatter parsing to full YAML with js-yaml and extending command types. Enables complex workflow definitions in command frontmatter while preserving backward compatibility, and closes #407.

  • New Features
    • Parse frontmatter with js-yaml using JSON_SCHEMA (supports arrays, nested objects, booleans; safer parsing).
    • Add HandoffDefinition and handoffs fields to CommandFrontmatter and CommandDefinition.
    • Pass handoffs through in loaders; use typed parseFrontmatter in command discovery and slash tools.
    • Add tests for simple/complex YAML, nested objects, invalid YAML handling, CRLF, and extra fields tolerance.

Written for commit fb7230f. Summary will update on new commits.

- Upgrade frontmatter parser to use js-yaml for complex YAML support
- Add HandoffDefinition interface for speckit-style workflow transitions
- Update CommandFrontmatter and CommandDefinition to include handoffs
- Add comprehensive tests for backward compatibility and complex YAML
- Fix type parameters in auto-slash-command and slashcommand tools

Closes #407
Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 7 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

@greptile-apps
Copy link

greptile-apps bot commented Jan 2, 2026

Greptile Summary

Replaces manual line-by-line frontmatter parser with js-yaml to support complex YAML structures (arrays, nested objects) needed for speckit's handoff workflow pattern. Adds HandoffDefinition interface to command types for multi-agent orchestration.

Key Changes:

  • Migrated from simple colon-split parsing to full YAML parser using js-yaml library
  • Added HandoffDefinition interface with label, agent, prompt, and optional send fields
  • Updated CommandDefinition and CommandFrontmatter types to include handoffs array
  • Loader passes handoffs through from frontmatter to command definitions
  • Added explicit type parameters to parseFrontmatter<CommandFrontmatter>() calls for type safety
  • Comprehensive test suite covers backward compatibility and edge cases

Critical Issue:

  • yaml.load() without SAFE_SCHEMA option can execute arbitrary code via !!js/function tags - security vulnerability

Confidence Score: 3/5

  • Safe to merge after fixing the YAML code execution vulnerability
  • Score reduced from 5 to 3 due to critical security issue: yaml.load() can execute arbitrary code. The implementation is otherwise solid with good backward compatibility and test coverage, but the security vulnerability must be addressed before merging.
  • Pay close attention to src/shared/frontmatter.ts - the YAML parsing security issue must be fixed

Important Files Changed

Filename Overview
src/shared/frontmatter.ts Replaced manual line-by-line parsing with js-yaml for full YAML spec support, enabling complex nested structures
src/features/claude-code-command-loader/types.ts Added HandoffDefinition interface with proper documentation for speckit workflow transitions
src/features/claude-code-command-loader/loader.ts Pass through handoffs field from frontmatter to command definitions
src/shared/frontmatter.test.ts Comprehensive test suite covering backward compatibility, complex YAML, and edge cases

Sequence Diagram

sequenceDiagram
    participant User
    participant CommandLoader as Command Loader
    participant Frontmatter as parseFrontmatter()
    participant YAML as js-yaml
    participant Command as CommandDefinition

    User->>CommandLoader: Load command from .md file
    CommandLoader->>Frontmatter: Parse file content
    Frontmatter->>YAML: yaml.load(yamlContent)
    YAML-->>Frontmatter: Parsed object with handoffs[]
    Frontmatter-->>CommandLoader: {data: CommandFrontmatter, body}
    CommandLoader->>CommandLoader: Extract handoffs from data
    CommandLoader->>Command: Create CommandDefinition with handoffs
    Command-->>User: Command ready with handoff workflows
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines 22 to 26
const parsed = yaml.load(yamlContent)
const data = (parsed ?? {}) as T
return { data, body }
} catch {
return { data: {} as T, body }
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: yaml.load() can execute arbitrary JavaScript code when parsing YAML with !!js/function tags by default

add { schema: yaml.SAFE_SCHEMA } option to prevent code execution:

Suggested change
const parsed = yaml.load(yamlContent)
const data = (parsed ?? {}) as T
return { data, body }
} catch {
return { data: {} as T, body }
const parsed = yaml.load(yamlContent, { schema: yaml.SAFE_SCHEMA })
const data = (parsed ?? {}) as T
return { data, body }
} catch {
return { data: {} as T, body }
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/shared/frontmatter.ts
Line: 22:26

Comment:
**logic:** `yaml.load()` can execute arbitrary JavaScript code when parsing YAML with `!!js/function` tags by default

add `{ schema: yaml.SAFE_SCHEMA }` option to prevent code execution:

```suggestion
    const parsed = yaml.load(yamlContent, { schema: yaml.SAFE_SCHEMA })
    const data = (parsed ?? {}) as T
    return { data, body }
  } catch {
    return { data: {} as T, body }
```

How can I resolve this? If you propose a fix, please make it concise.

content: string
): FrontmatterResult<T> {
const frontmatterRegex = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/
const frontmatterRegex = /^---\r?\n([\s\S]*?)\r?\n?---\r?\n([\s\S]*)$/
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: regex now allows optional newline before closing ---, which relaxes the frontmatter format validation

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/shared/frontmatter.ts
Line: 11:11

Comment:
**style:** regex now allows optional newline before closing `---`, which relaxes the frontmatter format validation

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

@code-yeongyu
Copy link
Owner

@sisyphus-dev-ai

  1. reflect the reviews
  2. even if we put some extra stuff, it should not fail- is that right for current impl? if not, you should ultrawork to fix it

@sisyphus-dev-ai sisyphus-dev-ai added the sisyphus: working Sisyphus is currently working on this label Jan 2, 2026
…olerance tests

- Use JSON_SCHEMA in yaml.load() to prevent code execution via YAML tags
- Add tests to verify extra fields in frontmatter don't cause failures
- Address Greptile security review comment
@sisyphus-dev-ai
Copy link
Collaborator Author

Review Feedback Addressed

I've addressed the review feedback:

1. Security Fix (Greptile Review)

  • Added JSON_SCHEMA option to yaml.load() in src/shared/frontmatter.ts to prevent code execution via YAML tags like !!js/function
  • This is the safest schema option in js-yaml v4.x, supporting only JSON-compatible types (strings, numbers, booleans, null, arrays, objects)

2. Extra Fields Tolerance (User Request)

Yes, the current implementation correctly handles extra fields without failing.

Added tests to confirm and document this behavior:

  • allows extra fields beyond typed interface - Verifies that frontmatter with additional fields not in the typed interface parses successfully
  • extra fields do not interfere with expected fields - Confirms complex types like handoffs work alongside unknown fields

The implementation casts the parsed YAML to the generic type T at runtime, which means:

  • All fields from the YAML are parsed and available
  • TypeScript only enforces types at compile-time
  • Extra fields are included in the result and accessible (with @ts-expect-error for type safety)

Changes

  • src/shared/frontmatter.ts: Added { schema: yaml.JSON_SCHEMA } option
  • src/shared/frontmatter.test.ts: Added 2 new tests for extra fields tolerance

All 430 tests pass. Build successful.

@sisyphus-dev-ai sisyphus-dev-ai removed the sisyphus: working Sisyphus is currently working on this label Jan 2, 2026
@code-yeongyu code-yeongyu merged commit 99711da into dev Jan 2, 2026
3 checks passed
@code-yeongyu code-yeongyu deleted the feat/speckit-handoffs-support branch January 2, 2026 06:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

speckit compat issue

3 participants