📦 deps(thirdparty): update snapshots

This commit is contained in:
ci[bot]
2026-05-29 08:33:53 +00:00
parent fdb52f1e96
commit 06e0d13d57
1615 changed files with 232858 additions and 0 deletions
@@ -0,0 +1,175 @@
---
name: stack-feedback
version: 0.3.0
description: Creates GitHub issues for problems discovered while using @outfitter/* packages. Use when finding bugs, missing features, unclear documentation, or improvement opportunities.
context: fork
agent: stacker
allowed-tools: Bash(gh *) Bash(bun *) Read
user-invocable: false
---
# Stack Feedback
Create GitHub issues on `outfitter-dev/outfitter` for problems discovered while using the stack.
## When to Use
Invoke this skill when you discover:
- **Bugs** in @outfitter/* packages
- **Missing features** that would improve DX
- **Unclear documentation** that caused confusion
- **Pattern gaps** where guidance is missing
- **Ergonomic issues** that made tasks harder than expected
## Issue Categories
| Category | Label | Example |
|----------|-------|---------|
| `bug` | `bug` | Package throws when it should return Result |
| `enhancement` | `feature` | Add helper for common pattern |
| `docs` | `documentation` | Handler contract docs missing edge case |
| `unclear-pattern` | `question` | How to handle X scenario with Result types |
| `dx` | `dx` | Error message unclear, hard to debug |
| `migration-pattern` | `adoption` | Migration scenario lacks guidance |
| `conversion-helper` | `adoption` | Need utility for legacy conversion |
| `compatibility` | `adoption` | Breaking change concern |
| `migration-docs` | `migration, documentation` | Migration docs gap |
## Using the Helper Script
The preferred method for creating issues. The script handles templates, labels, and validation.
### Basic Usage
```bash
bun plugins/outfitter-stack/skills/stack-feedback/scripts/create-issue.ts \
--type bug \
--title "Result.unwrap throws on valid input" \
--package "@outfitter/contracts" \
--description "When calling unwrap on Ok value, it unexpectedly throws" \
--actual "Throws TypeError instead of returning value"
```
### Dry-Run Mode (Default)
By default, the script outputs JSON with the `gh` command without executing it:
```json
{
"command": "gh issue create --repo outfitter-dev/outfitter --title '[Bug] Result.unwrap throws...' --label bug --label feedback --label source/agent --body '...'",
"title": "[Bug] Result.unwrap throws on valid input",
"labels": ["bug", "feedback", "source/agent"],
"body": "## Package\n\n`@outfitter/contracts`\n..."
}
```
### Origin Detection
The script automatically detects the git origin of the current directory and adds a "Discovered In" section to the issue body with a link to the source repo. This helps track where feedback originates.
### Submit Mode
Add `--submit` to actually create the issue:
```bash
bun plugins/outfitter-stack/skills/stack-feedback/scripts/create-issue.ts \
--type enhancement \
--title "Add Result.tap helper" \
--package "@outfitter/contracts" \
--description "Helper to run side effects without unwrapping" \
--useCase "Logging without breaking method chains" \
--submit
```
### View Template Requirements
Run with just `--type` to see required and optional fields:
```bash
bun plugins/outfitter-stack/skills/stack-feedback/scripts/create-issue.ts --type bug
```
### Available Types
| Type | Required Fields |
|------|-----------------|
| `bug` | package, description, actual |
| `enhancement` | package, description, useCase |
| `docs` | package, description, gap |
| `unclear-pattern` | package, description, context |
| `dx` | package, description, current |
| `migration-pattern` | sourcePattern, description, scenario |
| `conversion-helper` | legacyPattern, description, targetPattern |
| `compatibility` | package, description, breakingChange |
| `migration-docs` | area, description, gap |
## Manual Issue Creation
For cases where the script doesn't fit, use `gh` directly:
```bash
gh issue create \
--repo outfitter-dev/outfitter \
--title "[Bug] Brief description" \
--label "bug" \
--label "feedback" \
--label "source/agent" \
--body "$(cat <<'EOF'
## Package
`@outfitter/package-name`
## Description
What went wrong or what's missing.
## Actual Behavior
What actually happens.
---
*Created via `outfitter-stack:stack-feedback` skill*
EOF
)"
```
## Tracking Feedback
After creating, track in your project:
```markdown
## Stack Feedback
- [ ] #123: Result.unwrap throws on valid input — bug
```
## Check Existing Issues
Before creating a new issue, check if it already exists:
```bash
gh issue list --repo outfitter-dev/outfitter --label feedback
gh issue list --repo outfitter-dev/outfitter --search "{{KEYWORDS}}"
```
## Batch Feedback
If multiple issues have accumulated:
1. Review all feedback items
2. Deduplicate similar issues
3. Create issues with cross-references where related
4. Update tracking with issue numbers
## Best Practices
1. **Be specific** — Include package, function, and line if known
2. **Provide context** — Explain what task led to discovery
3. **Include workaround** — If you found one, share it
4. **Link related issues** — Reference if similar issues exist
5. **Stay constructive** — Focus on improvement, not complaint
## References
- [Migration-specific feedback](references/migration-feedback.md)
@@ -0,0 +1,84 @@
# Migration-Specific Feedback
When migrating existing code to Outfitter Stack, you may discover issues that are particularly relevant to the migration process.
## Migration-Specific Categories
| Category | When to Use |
|----------|-------------|
| `migration-pattern` | Common migration scenario lacks guidance |
| `conversion-helper` | Need a utility to convert from legacy pattern |
| `compatibility` | Breaking change or compatibility concern |
| `migration-docs` | Migration documentation gap |
## Migration Context Template
When creating issues discovered during migration, use this context format:
```markdown
## Context
Discovered during migration of **{PROJECT_NAME}** to Outfitter Stack.
**Migration stage:** {Foundation | Handlers | Errors | Paths | Adapters}
**Source pattern:** {What the code looked like before}
**Target pattern:** {What we're trying to achieve}
```
## Common Migration Feedback
### Pattern Gap: Throw to Result
```bash
gh issue create \
--repo outfitter-dev/outfitter \
--title "[migration] Guidance needed for X throw pattern" \
--label "documentation" \
--label "feedback" \
--label "adoption" \
--body "..."
```
### Missing Helper: Error Conversion
```bash
gh issue create \
--repo outfitter-dev/outfitter \
--title "[enhancement] Add helper to convert custom errors to taxonomy" \
--label "enhancement" \
--label "feedback" \
--label "adoption" \
--body "..."
```
### Compatibility Issue
```bash
gh issue create \
--repo outfitter-dev/outfitter \
--title "[bug] X doesn't work with common library Y" \
--label "bug" \
--label "feedback" \
--label "adoption" \
--body "..."
```
## Linking to Adoption Plan
When adopting, track feedback in `.outfitter/adopt/plan/99-unknowns.md`:
```markdown
## Stack Feedback (Migration)
- [ ] #123: Need guidance for async throw patterns — docs
- [ ] #124: Add wrapLegacy helper — enhancement
- [ ] #125: Compatibility with express middleware — bug
```
## After Migration
Once migration is complete, review all feedback issues and:
1. Close any that were resolved by workarounds
2. Add reproduction details now that you have working code
3. Prioritize based on how painful the issue was
@@ -0,0 +1,322 @@
#!/usr/bin/env bun
/**
* Create GitHub issues for stack-feedback skill
*
* Usage:
* bun scripts/create-issue.ts --type bug --title "..." --package "@outfitter/result" ...
*
* Options:
* --type Issue type (bug, enhancement, docs, unclear-pattern, dx,
* migration-pattern, conversion-helper, compatibility, migration-docs)
* --title Issue title (prefix added automatically)
* --submit Actually create the issue (default: dry-run)
* --help Show this help message
*
* All other options are passed as template fields (e.g., --package, --description)
*/
import { parseArgs } from "util";
import { templates, templateTypes, type IssueTemplate } from "../templates";
const REPO = "outfitter-dev/outfitter";
/**
* Detect the origin repo from git remote.
* Returns GitHub owner/repo format or null if not detectable.
*/
async function detectOriginRepo(): Promise<string | null> {
try {
const proc = Bun.spawn(["git", "remote", "get-url", "origin"], {
stdout: "pipe",
stderr: "pipe",
});
const stdout = await new Response(proc.stdout).text();
const exitCode = await proc.exited;
if (exitCode !== 0) {
// Silently fail - this is expected when not in a git repo
return null;
}
const url = stdout.trim();
// Handle SSH format: git@github.com:owner/repo.git
const sshMatch = url.match(/git@github\.com:([^/]+\/[^/]+?)(?:\.git)?$/);
if (sshMatch) {
return sshMatch[1];
}
// Handle HTTPS format: https://github.com/owner/repo.git
const httpsMatch = url.match(/github\.com\/([^/]+\/[^/]+?)(?:\.git)?$/);
if (httpsMatch) {
return httpsMatch[1];
}
return null;
} catch {
return null;
}
}
interface ParsedArgs {
type?: string;
title?: string;
submit?: boolean;
help?: boolean;
[key: string]: string | boolean | undefined;
}
function showHelp(): void {
console.log(`
stack-feedback: Create GitHub issues for Outfitter Stack feedback
USAGE
bun scripts/create-issue.ts --type <type> --title <title> [--field value]... [--submit]
OPTIONS
--type <type> Issue type (required)
--title <title> Issue title without prefix (required)
--submit Create issue (default: dry-run mode)
--help Show this help
ISSUE TYPES
${templateTypes.map((t) => ` ${t}`).join("\n")}
TEMPLATE FIELDS
Each issue type has required and optional fields. Pass them as --fieldName "value".
Use --type <type> without other args to see required fields.
EXAMPLES
# Dry-run a bug report
bun scripts/create-issue.ts \\
--type bug \\
--title "Result.unwrap throws on valid input" \\
--package "@outfitter/result" \\
--description "When calling unwrap on Ok, it throws" \\
--actual "Throws TypeError"
# Submit an enhancement request
bun scripts/create-issue.ts \\
--type enhancement \\
--title "Add Result.tap helper" \\
--package "@outfitter/result" \\
--description "Helper to run side effects without unwrapping" \\
--useCase "Logging without breaking chains" \\
--submit
`);
}
function showTypeHelp(template: IssueTemplate): void {
console.log(`
Type: ${template.type}
Labels: ${template.labels.join(", ")}
Title prefix: ${template.titlePrefix}
Required fields:
${template.requiredFields.map((f) => ` --${f}`).join("\n")}
Optional fields:
${template.optionalFields.map((f) => ` --${f}`).join("\n")}
`);
}
function interpolate(template: string, fields: Record<string, string>): string {
let result = template;
// Replace all {placeholder} patterns
const placeholderRegex = /\{(\w+)\}/g;
result = result.replace(placeholderRegex, (match, fieldName) => {
const value = fields[fieldName];
if (value !== undefined && value !== "") {
return value;
}
// Remove the section if the field is empty
return "_No information provided_";
});
return result;
}
/**
* Escape single quotes for shell display.
* NOTE: This is ONLY used for displaying the command to users (dry-run output).
* Actual issue creation uses Bun.spawn with array arguments, which is safe.
*/
function escapeForShell(str: string): string {
return str.replace(/'/g, "'\\''");
}
function buildGhCommand(
title: string,
labels: string[],
body: string
): string {
const labelArgs = labels.map((l) => `--label '${l}'`).join(" ");
const escapedTitle = escapeForShell(title);
const escapedBody = escapeForShell(body);
return `gh issue create --repo ${REPO} --title '${escapedTitle}' ${labelArgs} --body '${escapedBody}'`;
}
async function createIssue(
title: string,
labels: string[],
body: string
): Promise<string> {
const proc = Bun.spawn(
[
"gh",
"issue",
"create",
"--repo",
REPO,
"--title",
title,
...labels.flatMap((l) => ["--label", l]),
"--body",
body,
],
{
stdout: "pipe",
stderr: "pipe",
}
);
const stdout = await new Response(proc.stdout).text();
const stderr = await new Response(proc.stderr).text();
const exitCode = await proc.exited;
if (exitCode !== 0) {
throw new Error(`gh issue create failed: ${stderr}`);
}
return stdout.trim();
}
async function main(): Promise<void> {
// Parse known options first, collect rest as fields
const args = process.argv.slice(2);
// Handle --help early
if (args.includes("--help") || args.includes("-h") || args.length === 0) {
showHelp();
process.exit(0);
}
// Build options object for parseArgs
const options: Record<string, { type: "string" | "boolean" }> = {
type: { type: "string" },
title: { type: "string" },
submit: { type: "boolean" },
help: { type: "boolean" },
};
// Add all possible template fields as string options
const allFields = new Set<string>();
for (const template of Object.values(templates)) {
for (const field of [...template.requiredFields, ...template.optionalFields]) {
allFields.add(field);
options[field] = { type: "string" };
}
}
let parsed: ParsedArgs;
try {
const result = parseArgs({
args,
options,
strict: false, // Allow unknown options
});
parsed = result.values as ParsedArgs;
} catch (error) {
console.error("Error parsing arguments:", error);
process.exit(1);
}
// Validate type
const issueType = parsed.type;
if (!issueType) {
console.error("Error: --type is required");
console.error(`Available types: ${templateTypes.join(", ")}`);
process.exit(1);
}
const template = templates[issueType];
if (!template) {
console.error(`Error: Unknown type '${issueType}'`);
console.error(`Available types: ${templateTypes.join(", ")}`);
process.exit(1);
}
// If only type provided, show type help
if (!parsed.title && Object.keys(parsed).length <= 1) {
showTypeHelp(template);
process.exit(0);
}
// Validate title
if (!parsed.title) {
console.error("Error: --title is required");
process.exit(1);
}
// Collect field values
const fields: Record<string, string> = {};
for (const field of [...template.requiredFields, ...template.optionalFields]) {
const value = parsed[field];
if (typeof value === "string") {
fields[field] = value;
}
}
// Validate required fields
const missingFields = template.requiredFields.filter(
(f) => !fields[f] || fields[f] === ""
);
if (missingFields.length > 0) {
console.error(`Error: Missing required fields: ${missingFields.join(", ")}`);
showTypeHelp(template);
process.exit(1);
}
// Build issue
const fullTitle = `${template.titlePrefix} ${parsed.title}`;
let body = interpolate(template.bodyTemplate, fields);
// Add origin repo context if detectable
const originRepo = await detectOriginRepo();
if (originRepo && originRepo !== REPO) {
// Insert before the footer
const footerMarker = "---\n\n*Created via";
if (body.includes(footerMarker)) {
body = body.replace(
footerMarker,
`## Discovered In\n\n[\`${originRepo}\`](https://github.com/${originRepo})\n\n${footerMarker}`
);
}
}
if (parsed.submit) {
// Submit mode: actually create the issue
try {
const url = await createIssue(fullTitle, template.labels, body);
console.log(`Created issue: ${url}`);
} catch (error) {
console.error("Failed to create issue:", error);
process.exit(1);
}
} else {
// Dry-run mode: output JSON with command
const command = buildGhCommand(fullTitle, template.labels, body);
const output = {
command,
title: fullTitle,
labels: template.labels,
body,
};
console.log(JSON.stringify(output, null, 2));
}
}
main();
@@ -0,0 +1,8 @@
{
"type": "bug",
"labels": ["bug", "feedback", "source/agent"],
"titlePrefix": "[bug]:",
"bodyTemplate": "## Package\n\n`{package}`\n\n## Description\n\n{description}\n\n## Expected Behavior\n\n{expected}\n\n## Actual Behavior\n\n{actual}\n\n## Reproduction\n\n{steps}\n\n## Workaround\n\n{workaround}\n\n---\n\n*Created via `outfitter-stack:stack-feedback` skill*",
"requiredFields": ["package", "description", "actual"],
"optionalFields": ["expected", "steps", "workaround"]
}
@@ -0,0 +1,8 @@
{
"type": "compatibility",
"labels": ["adoption", "feedback", "source/agent"],
"titlePrefix": "[compat]:",
"bodyTemplate": "## Package\n\n`{package}`\n\n## Description\n\n{description}\n\n## Breaking Change\n\n{breakingChange}\n\n## Impact Assessment\n\n{impact}\n\n## Suggested Mitigation\n\n{mitigation}\n\n---\n\n*Created via `outfitter-stack:stack-feedback` skill*",
"requiredFields": ["package", "description", "breakingChange"],
"optionalFields": ["impact", "mitigation"]
}
@@ -0,0 +1,8 @@
{
"type": "conversion-helper",
"labels": ["adoption", "feedback", "source/agent"],
"titlePrefix": "[adoption]:",
"bodyTemplate": "## Legacy Pattern\n\n{legacyPattern}\n\n## Description\n\n{description}\n\n## Target Pattern\n\n{targetPattern}\n\n## Proposed Helper\n\n{proposedHelper}\n\n## Frequency\n\n{frequency}\n\n---\n\n*Created via `outfitter-stack:stack-feedback` skill*",
"requiredFields": ["legacyPattern", "description", "targetPattern"],
"optionalFields": ["proposedHelper", "frequency"]
}
@@ -0,0 +1,8 @@
{
"type": "docs",
"labels": ["documentation", "feedback", "source/agent"],
"titlePrefix": "[docs]:",
"bodyTemplate": "## Package/Area\n\n`{package}`\n\n## Description\n\n{description}\n\n## What's Missing or Unclear\n\n{gap}\n\n## Suggested Improvement\n\n{suggestion}\n\n## Context\n\n{context}\n\n---\n\n*Created via `outfitter-stack:stack-feedback` skill*",
"requiredFields": ["package", "description", "gap"],
"optionalFields": ["suggestion", "context"]
}
@@ -0,0 +1,8 @@
{
"type": "dx",
"labels": ["dx", "feedback", "source/agent"],
"titlePrefix": "[dx]:",
"bodyTemplate": "## Package\n\n`{package}`\n\n## Description\n\n{description}\n\n## Current Experience\n\n{current}\n\n## Ideal Experience\n\n{ideal}\n\n## Impact\n\n{impact}\n\n---\n\n*Created via `outfitter-stack:stack-feedback` skill*",
"requiredFields": ["package", "description", "current"],
"optionalFields": ["ideal", "impact"]
}
@@ -0,0 +1,8 @@
{
"type": "enhancement",
"labels": ["feature", "feedback", "source/agent"],
"titlePrefix": "[feat]:",
"bodyTemplate": "## Package\n\n`{package}`\n\n## Description\n\n{description}\n\n## Use Case\n\n{useCase}\n\n## Proposed API\n\n{proposedApi}\n\n## Alternatives Considered\n\n{alternatives}\n\n---\n\n*Created via `outfitter-stack:stack-feedback` skill*",
"requiredFields": ["package", "description", "useCase"],
"optionalFields": ["proposedApi", "alternatives"]
}
@@ -0,0 +1,41 @@
/**
* Issue template types and registry for stack-feedback skill
*/
export interface IssueTemplate {
type: string;
labels: string[];
titlePrefix: string;
bodyTemplate: string;
requiredFields: string[];
optionalFields: string[];
}
export interface TemplateFields {
[key: string]: string | undefined;
}
// Import all templates
import bug from "./bug.json";
import enhancement from "./enhancement.json";
import docs from "./docs.json";
import unclearPattern from "./unclear-pattern.json";
import dx from "./dx.json";
import migrationPattern from "./migration-pattern.json";
import conversionHelper from "./conversion-helper.json";
import compatibility from "./compatibility.json";
import migrationDocs from "./migration-docs.json";
export const templates: Record<string, IssueTemplate> = {
bug,
enhancement,
docs,
"unclear-pattern": unclearPattern,
dx,
"migration-pattern": migrationPattern,
"conversion-helper": conversionHelper,
compatibility,
"migration-docs": migrationDocs,
};
export const templateTypes = Object.keys(templates);
@@ -0,0 +1,8 @@
{
"type": "migration-docs",
"labels": ["documentation", "adoption", "feedback", "source/agent"],
"titlePrefix": "[docs]:",
"bodyTemplate": "## Migration Area\n\n{area}\n\n## Description\n\n{description}\n\n## Documentation Gap\n\n{gap}\n\n## Suggested Content\n\n{suggestion}\n\n## Priority\n\n{priority}\n\n---\n\n*Created via `outfitter-stack:stack-feedback` skill*",
"requiredFields": ["area", "description", "gap"],
"optionalFields": ["suggestion", "priority"]
}
@@ -0,0 +1,8 @@
{
"type": "migration-pattern",
"labels": ["adoption", "feedback", "source/agent"],
"titlePrefix": "[adoption]:",
"bodyTemplate": "## Source Pattern\n\n{sourcePattern}\n\n## Description\n\n{description}\n\n## Migration Scenario\n\n{scenario}\n\n## Current Guidance\n\n{currentGuidance}\n\n## Suggested Approach\n\n{suggestion}\n\n---\n\n*Created via `outfitter-stack:stack-feedback` skill*",
"requiredFields": ["sourcePattern", "description", "scenario"],
"optionalFields": ["currentGuidance", "suggestion"]
}
@@ -0,0 +1,8 @@
{
"type": "unclear-pattern",
"labels": ["question", "feedback", "source/agent"],
"titlePrefix": "[question]:",
"bodyTemplate": "## Package/Area\n\n`{package}`\n\n## Question\n\n{description}\n\n## Context\n\n{context}\n\n## What I've Tried\n\n{attempted}\n\n## Specific Confusion\n\n{confusion}\n\n---\n\n*Created via `outfitter-stack:stack-feedback` skill*",
"requiredFields": ["package", "description", "context"],
"optionalFields": ["attempted", "confusion"]
}