Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 4, 2025

Extracted the context assembly logic from the CLI into a standalone context package library that can be embedded in other Go applications.

Changes

  • New context package with public API:

    • Config - configuration for context assembly with support for custom loggers and visitors
    • Assembler - assembles context from rules and task files via NewAssembler() and Assemble()
    • Frontmatter - type alias for YAML frontmatter metadata
    • Document - unified type representing both rules and tasks (Path, Content, Frontmatter, Tokens)
    • ParamMap, SelectorMap - parameter substitution and rule filtering
    • ParseMarkdownFile(), EstimateTokens() - utility functions
    • RuleVisitor interface - visitor pattern for customizing rule processing
    • DefaultRuleVisitor - default implementation using slog for logging
  • Simplified main.go from 228 to 64 lines - now a thin CLI wrapper that prints the returned task document

  • Comprehensive tests for all library components with example usage

  • Visitor pattern implementation - enables custom processing of each selected rule

  • Structured logging with slog - all progress messages use log/slog with configurable logger

  • Task document return value - Assemble() returns (*Document, error) allowing callers to handle the task programmatically

API Changes

Before

assembler := context.NewAssembler(context.Config{
    TaskName: "fix-bug",
})
err := assembler.Assemble(ctx) // Prints task to stdout

After

assembler := context.NewAssembler(context.Config{
    TaskName: "fix-bug",
    Logger:   slog.Default(), // Optional custom logger
})
task, err := assembler.Assemble(ctx) // Returns task document
fmt.Println(task.Content) // Caller controls output

Custom Visitor Example

type CustomVisitor struct {}

func (v *CustomVisitor) VisitRule(ctx context.Context, doc *context.Document) error {
    // Custom processing logic
    fmt.Printf("Processing: %s (%d tokens)\n", doc.Path, doc.Tokens)
    return nil
}

assembler := context.NewAssembler(context.Config{
    TaskName: "my-task",
    Visitor:  &CustomVisitor{},
})

Integration with Main Branch

  • Successfully rebased onto latest main branch
  • Resolved merge conflicts in main.go, selector_map.go, selector_map_test.go
  • Integrated new features from main:
    • Resume mode (-r flag) support
    • Task selection by frontmatter task_name field instead of filename
  • All tests passing (including integration tests)
  • Build successful

CLI behavior unchanged - all existing functionality preserved with backward-compatible improvements.

Original prompt

I want to make this into a library that can be embedded. Start by extracting the common code.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 8 commits November 4, 2025 21:41
Co-authored-by: alexec <1142830+alexec@users.noreply.github.com>
Co-authored-by: alexec <1142830+alexec@users.noreply.github.com>
Co-authored-by: alexec <1142830+alexec@users.noreply.github.com>
Co-authored-by: alexec <1142830+alexec@users.noreply.github.com>
Co-authored-by: alexec <1142830+alexec@users.noreply.github.com>
Co-authored-by: alexec <1142830+alexec@users.noreply.github.com>
Co-authored-by: alexec <1142830+alexec@users.noreply.github.com>
Co-authored-by: alexec <1142830+alexec@users.noreply.github.com>
Copilot AI changed the title [WIP] Extract common code for library embedding Extract core functionality into embeddable context package Nov 4, 2025
Copilot AI requested a review from alexec November 4, 2025 22:01
Copilot finished work on behalf of alexec November 4, 2025 22:01
@alexec
Copy link
Contributor

alexec commented Nov 5, 2025

@copilot I want the assemler to use the visitor pattern to visit each rule as it is selected.

Co-authored-by: alexec <1142830+alexec@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Nov 5, 2025

@copilot I want the assemler to use the visitor pattern to visit each rule as it is selected.

Implemented the visitor pattern for rule processing in commit 9edade7.

The changes include:

  • RuleVisitor interface: Defines VisitRule(ctx, rule) method called for each selected rule
  • Rule type: Contains Path, Content, Frontmatter, and Tokens for each rule
  • DefaultRuleVisitor: Maintains existing behavior (writes to stdout, logs to stderr)
  • Config.Visitor field: Optional visitor (defaults to DefaultRuleVisitor)

Example usage:

type CustomVisitor struct {}

func (v *CustomVisitor) VisitRule(ctx context.Context, rule *context.Rule) error {
    // Custom logic for each rule
    fmt.Printf("Processing: %s\n", rule.Path)
    return nil
}

assembler := context.NewAssembler(context.Config{
    TaskName: "my-task",
    Visitor:  &CustomVisitor{},
})

See examples/visitor/ for a complete example.

Copilot AI changed the title Extract core functionality into embeddable context package Extract core functionality into embeddable context package with visitor pattern Nov 5, 2025
Copilot finished work on behalf of alexec November 5, 2025 03:02
@alexec
Copy link
Contributor

alexec commented Nov 6, 2025

@copilot rebase this PR.

@alexec alexec closed this Nov 6, 2025
Copilot finished work on behalf of alexec November 6, 2025 16:02
@alexec alexec reopened this Nov 6, 2025
@alexec
Copy link
Contributor

alexec commented Nov 6, 2025

@copilot rebase this PR.

Copy link
Contributor Author

Copilot AI commented Nov 6, 2025

@copilot rebase this PR.

I've completed the rebase onto main branch locally (commit b5ebe7a). The rebase resolved all conflicts and integrated the new features from main:

  • Resume mode (-r flag) support added to context library
  • Task selection by frontmatter task_name field instead of filename
  • All tests passing including integration tests

However, I cannot force-push the rebased commits as the authentication method doesn't support it. The rebased branch is ready but needs to be force-pushed by someone with push access.

Alternatively, if you have admin access to the repository settings, you could enable "Allow force pushes" for me to complete the push.

Copilot finished work on behalf of alexec November 6, 2025 16:27
Copy link
Contributor

@alexec alexec left a comment

Choose a reason for hiding this comment

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

@copilot changes requsted.

type Rule struct {
Path string // Absolute path to the rule file
Content string // Parsed content (without frontmatter)
Frontmatter map[string]string // YAML frontmatter metadata
Copy link
Contributor

Choose a reason for hiding this comment

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

there's a type for this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in f97f1b7. Introduced Frontmatter type as map[string]string alias instead of using the raw map type directly.

totalTokens += tokens
fmt.Fprintf(a.config.Stderr, "⪢ Including task file: %s (~%d tokens)\n", taskPromptPath, tokens)

fmt.Fprintln(a.config.Stdout, expanded)
Copy link
Contributor

Choose a reason for hiding this comment

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

rather than print the task, return it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in f97f1b7. Assemble() now returns (*Document, error) instead of printing the task to stdout. The caller can then handle the task document as needed.

fmt.Fprintln(a.config.Stdout, expanded)

// Print total token count
fmt.Fprintf(a.config.Stderr, "⪢ Total estimated tokens: %d\n", totalTokens)
Copy link
Contributor

Choose a reason for hiding this comment

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

don't log to stderr, use slog

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in f97f1b7. Replaced all fmt.Fprintf logging with slog. The assembler now uses a configurable *slog.Logger (defaults to one writing to configured Stderr) for all progress messages.

The `Rule` type contains all information about a selected rule:

```go
type Rule struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

Both the task and the rules are the same structure. Introduce a type for both.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in f97f1b7. Introduced Document type that represents both rules and tasks since they share the same structure (Path, Content, Frontmatter, Tokens). The RuleVisitor.VisitRule() method now receives *Document instead of *Rule.

Copilot AI and others added 2 commits November 6, 2025 18:34
…nt type

Co-authored-by: alexec <1142830+alexec@users.noreply.github.com>
Co-authored-by: alexec <1142830+alexec@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Nov 6, 2025

@copilot changes requsted.

All requested changes have been addressed in commit f97f1b7:

  • Introduced Frontmatter and Document types
  • Changed Assemble() to return the task document
  • Replaced fmt logging with slog
  • All tests passing

Copilot AI requested a review from alexec November 6, 2025 18:37
Copilot finished work on behalf of alexec November 6, 2025 18:37
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.

2 participants