@lousy-agents/cli 2.2.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/copilot-with-fastify/biome.json +1 -1
- package/cli/copilot-with-citty/.devcontainer/devcontainer.json +76 -0
- package/cli/copilot-with-citty/.editorconfig +16 -0
- package/cli/copilot-with-citty/.github/ISSUE_TEMPLATE/feature-to-spec.yml +54 -0
- package/cli/copilot-with-citty/.github/copilot-instructions.md +228 -0
- package/cli/copilot-with-citty/.github/instructions/pipeline.instructions.md +92 -0
- package/cli/copilot-with-citty/.github/instructions/software-architecture.instructions.md +166 -0
- package/cli/copilot-with-citty/.github/instructions/spec.instructions.md +127 -0
- package/cli/copilot-with-citty/.github/instructions/test.instructions.md +157 -0
- package/cli/copilot-with-citty/.github/specs/README.md +84 -0
- package/cli/copilot-with-citty/.github/workflows/assign-copilot.yml +59 -0
- package/cli/copilot-with-citty/.github/workflows/ci.yml +67 -0
- package/cli/copilot-with-citty/.nvmrc +1 -0
- package/cli/copilot-with-citty/.vscode/extensions.json +13 -0
- package/cli/copilot-with-citty/.vscode/launch.json +25 -0
- package/cli/copilot-with-citty/.vscode/mcp.json +19 -0
- package/cli/copilot-with-citty/.yamllint +18 -0
- package/cli/copilot-with-citty/biome.json +31 -0
- package/cli/copilot-with-citty/package.json +29 -0
- package/cli/copilot-with-citty/tsconfig.json +28 -0
- package/cli/copilot-with-citty/vitest.config.ts +15 -0
- package/cli/copilot-with-citty/vitest.setup.ts +2 -0
- package/dist/index.js +205 -55
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.js +3 -0
- package/dist/mcp-server.js.map +1 -1
- package/package.json +3 -2
- package/ui/copilot-with-react/biome.json +1 -1
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: "**/spec.md"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Spec Development Instructions
|
|
6
|
+
|
|
7
|
+
You are a product management partner helping define features for <product> targeting <customers>.
|
|
8
|
+
|
|
9
|
+
> Placeholder variables:
|
|
10
|
+
> - `<product>` is the name of the product or system for which this spec is being written.
|
|
11
|
+
> - `<customers>` describes the primary customer or user segments targeted by the spec.
|
|
12
|
+
> These placeholders may be automatically populated by your tooling; if not, replace them manually with the appropriate values before using this document.
|
|
13
|
+
## Your Role
|
|
14
|
+
|
|
15
|
+
Act as a collaborative PM pair, not a passive assistant. This means:
|
|
16
|
+
|
|
17
|
+
- **Challenge assumptions** — Ask "why" before writing. Probe for the underlying problem.
|
|
18
|
+
- **Identify gaps** — Flag missing acceptance criteria, edge cases, and error states.
|
|
19
|
+
- **Guard scope** — Call out when a feature is too large for a single increment. Suggest phasing.
|
|
20
|
+
- **Propose value** — Don't wait to be asked. Assess and state which value types a feature delivers.
|
|
21
|
+
- **Ensure persona coverage** — Every spec must identify impacted personas. Push back if missing.
|
|
22
|
+
|
|
23
|
+
## Collaboration Approach
|
|
24
|
+
|
|
25
|
+
Before writing or modifying a spec:
|
|
26
|
+
|
|
27
|
+
1. Confirm you understand the problem being solved, not just the solution requested
|
|
28
|
+
2. Ask clarifying questions if the request is ambiguous
|
|
29
|
+
3. Identify which personas are affected and how
|
|
30
|
+
4. Propose a value assessment
|
|
31
|
+
5. Suggest scope boundaries if the feature feels too broad
|
|
32
|
+
|
|
33
|
+
When reviewing a spec:
|
|
34
|
+
|
|
35
|
+
1. Verify all acceptance criteria use EARS notation
|
|
36
|
+
2. Check that personas are explicitly named with impact described
|
|
37
|
+
3. Confirm design aligns with engineering guidance
|
|
38
|
+
4. Identify any missing error states or edge cases
|
|
39
|
+
5. Assess whether tasks are appropriately sized for the coding agent
|
|
40
|
+
|
|
41
|
+
## EARS Requirement Syntax
|
|
42
|
+
|
|
43
|
+
All acceptance criteria must use EARS (Easy Approach to Requirements Syntax) patterns:
|
|
44
|
+
|
|
45
|
+
| Pattern | Template | Use When |
|
|
46
|
+
|---------|----------|----------|
|
|
47
|
+
| Ubiquitous | The `<system>` shall `<response>` | Always true, no trigger |
|
|
48
|
+
| Event-driven | When `<trigger>`, the `<system>` shall `<response>` | Responding to an event |
|
|
49
|
+
| State-driven | While `<state>`, the `<system>` shall `<response>` | Active during a condition |
|
|
50
|
+
| Optional | Where `<feature>` is enabled, the `<system>` shall `<response>` | Configurable capability |
|
|
51
|
+
| Unwanted | If `<condition>`, then the `<system>` shall `<response>` | Error handling, edge cases |
|
|
52
|
+
| Complex | While `<state>`, when `<trigger>`, the `<system>` shall `<response>` | Combining conditions |
|
|
53
|
+
|
|
54
|
+
### EARS Examples
|
|
55
|
+
|
|
56
|
+
```markdown
|
|
57
|
+
- The CLI shall validate all input arguments before execution.
|
|
58
|
+
- When a user runs `init`, the system shall display a project type selection prompt.
|
|
59
|
+
- While verbose mode is enabled, the system shall log detailed debug information.
|
|
60
|
+
- Where custom configuration is provided, the system shall use it instead of defaults.
|
|
61
|
+
- If the configuration file is invalid, then the system shall display a validation error with details.
|
|
62
|
+
- While strict mode is enabled, when an unknown argument is provided, the system shall reject the command.
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## User Story Format
|
|
66
|
+
|
|
67
|
+
```markdown
|
|
68
|
+
### Story: <Concise Title>
|
|
69
|
+
|
|
70
|
+
As a **<persona>**,
|
|
71
|
+
I want **<capability>**,
|
|
72
|
+
so that I can **<outcome/problem solved>**.
|
|
73
|
+
|
|
74
|
+
#### Acceptance Criteria
|
|
75
|
+
|
|
76
|
+
- When <trigger>, the <system> shall <response>
|
|
77
|
+
- While <state>, the <system> shall <response>
|
|
78
|
+
- If <error condition>, then the <system> shall <response>
|
|
79
|
+
|
|
80
|
+
#### Notes
|
|
81
|
+
|
|
82
|
+
<Context, constraints, or open questions>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Spec File Structure
|
|
86
|
+
|
|
87
|
+
A spec has three sections that flow into each other:
|
|
88
|
+
|
|
89
|
+
1. **Requirements** — What we're building and why (human and agent context)
|
|
90
|
+
2. **Design** — How it fits into the system (agent context for implementation)
|
|
91
|
+
3. **Tasks** — Discrete units of work (directly assignable to coding agent)
|
|
92
|
+
|
|
93
|
+
## Task Design Guidelines
|
|
94
|
+
|
|
95
|
+
### Size
|
|
96
|
+
|
|
97
|
+
- Completable in one agent session (~1-3 files, ~200-300 lines changed)
|
|
98
|
+
- If a task feels too large, split it
|
|
99
|
+
- If you have more than 7-10 tasks, split the feature into phases
|
|
100
|
+
|
|
101
|
+
### Clarity
|
|
102
|
+
|
|
103
|
+
- **Objective** — One sentence, action-oriented
|
|
104
|
+
- **Context** — Explains why; agents make better decisions with intent
|
|
105
|
+
- **Affected files** — Tells the agent where to focus
|
|
106
|
+
- **Requirements** — Links back to specific acceptance criteria
|
|
107
|
+
|
|
108
|
+
### Verification
|
|
109
|
+
|
|
110
|
+
Every task must include verification steps the agent can run:
|
|
111
|
+
|
|
112
|
+
```markdown
|
|
113
|
+
**Verification**:
|
|
114
|
+
- [ ] `npm test` passes
|
|
115
|
+
- [ ] `npm run lint` passes
|
|
116
|
+
- [ ] New command returns expected output for valid input
|
|
117
|
+
- [ ] New command returns error message for invalid input
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Diagram Requirements
|
|
121
|
+
|
|
122
|
+
All diagrams in specs must use **Mermaid** syntax for consistency and GitHub rendering support.
|
|
123
|
+
|
|
124
|
+
## Related Files
|
|
125
|
+
|
|
126
|
+
- `.github/ISSUE_TEMPLATE/feature-to-spec.yml` — Issue template for creating specs
|
|
127
|
+
- `.github/workflows/assign-copilot.yml` — Workflow for auto-assigning Copilot
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: "src/**/*.{test,spec}.ts"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Testing Conventions for CLI
|
|
6
|
+
|
|
7
|
+
## MANDATORY: After Test Changes
|
|
8
|
+
|
|
9
|
+
Run `npm test` after modifying or creating tests to verify all tests pass.
|
|
10
|
+
|
|
11
|
+
## Test File Structure
|
|
12
|
+
|
|
13
|
+
Use this structure for all test files:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { describe, it, expect } from 'vitest';
|
|
17
|
+
|
|
18
|
+
describe('ComponentName', () => {
|
|
19
|
+
describe('when [condition]', () => {
|
|
20
|
+
it('should [expected behavior]', () => {
|
|
21
|
+
// Arrange
|
|
22
|
+
const input = 'test-value';
|
|
23
|
+
|
|
24
|
+
// Act
|
|
25
|
+
const result = functionUnderTest(input);
|
|
26
|
+
|
|
27
|
+
// Assert
|
|
28
|
+
expect(result).toBe('expected-value');
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Test Data
|
|
35
|
+
|
|
36
|
+
- Use Chance.js to generate random test data when actual input values are not important.
|
|
37
|
+
- Generate Chance.js data that produces readable assertion failure messages.
|
|
38
|
+
- Use simple strings or numbers - avoid overly complex Chance.js configurations.
|
|
39
|
+
|
|
40
|
+
## Test Design Rules
|
|
41
|
+
|
|
42
|
+
1. Follow the Arrange-Act-Assert (AAA) pattern for ALL tests.
|
|
43
|
+
2. Use spec-style tests with `describe` and `it` blocks.
|
|
44
|
+
3. Write test descriptions as user stories: "should [do something] when [condition]".
|
|
45
|
+
4. Focus on behavior, NOT implementation details.
|
|
46
|
+
5. Extract fixture values to variables - NEVER hardcode values in both setup and assertions.
|
|
47
|
+
6. Use `msw` to mock external HTTP APIs - do NOT mock fetch directly.
|
|
48
|
+
7. Avoid mocking third-party dependencies when possible.
|
|
49
|
+
8. Tests MUST be isolated - no shared state between tests.
|
|
50
|
+
9. Tests MUST be deterministic - same result every run.
|
|
51
|
+
10. Tests MUST run identically locally and in CI.
|
|
52
|
+
11. NEVER use partial mocks.
|
|
53
|
+
12. Test ALL conditional paths with meaningful assertions.
|
|
54
|
+
13. Test unhappy paths and edge cases, not just happy paths.
|
|
55
|
+
14. Every assertion should explain the expected behavior.
|
|
56
|
+
15. Write tests that would FAIL if production code regressed.
|
|
57
|
+
16. **NEVER export functions, methods, or variables from production code solely for testing purposes.**
|
|
58
|
+
17. **NEVER use module-level mutable state for dependency injection in production code.**
|
|
59
|
+
|
|
60
|
+
## Dependency Injection for Testing
|
|
61
|
+
|
|
62
|
+
When you need to inject dependencies for testing:
|
|
63
|
+
|
|
64
|
+
- **DO** use constructor parameters, function parameters, or factory functions.
|
|
65
|
+
- **DO** pass test doubles through the existing public API of the code under test.
|
|
66
|
+
- **DO NOT** export special test-only functions like `_setTestDependencies()` or `_resetTestDependencies()`.
|
|
67
|
+
- **DO NOT** modify module-level state from tests.
|
|
68
|
+
|
|
69
|
+
### Good Example (Dependency Injection via Factory Function)
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
// Production code - use-cases/process-input.ts
|
|
73
|
+
export interface InputReader {
|
|
74
|
+
read(source: string): Promise<string>;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function createInputProcessor(reader: InputReader) {
|
|
78
|
+
return {
|
|
79
|
+
async execute(source: string) {
|
|
80
|
+
const content = await reader.read(source);
|
|
81
|
+
if (!content.trim()) {
|
|
82
|
+
throw new Error('Empty input');
|
|
83
|
+
}
|
|
84
|
+
return content;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Test code
|
|
90
|
+
it("should process valid input", async () => {
|
|
91
|
+
const mockReader = {
|
|
92
|
+
read: vi.fn().mockResolvedValue("valid content")
|
|
93
|
+
};
|
|
94
|
+
const processor = createInputProcessor(mockReader);
|
|
95
|
+
|
|
96
|
+
const result = await processor.execute("source.txt");
|
|
97
|
+
|
|
98
|
+
expect(result).toBe("valid content");
|
|
99
|
+
expect(mockReader.read).toHaveBeenCalledWith("source.txt");
|
|
100
|
+
});
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Bad Example (Test-Only Exports)
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
// ❌ BAD: Production code
|
|
107
|
+
let _readerOverride: any;
|
|
108
|
+
|
|
109
|
+
export function _setTestDependencies(deps: any) {
|
|
110
|
+
_readerOverride = deps.reader;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function processInput(source: string) {
|
|
114
|
+
const reader = _readerOverride || defaultReader;
|
|
115
|
+
return reader.read(source);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ❌ BAD: Test code
|
|
119
|
+
import { _setTestDependencies, processInput } from "./process-input";
|
|
120
|
+
|
|
121
|
+
beforeEach(() => {
|
|
122
|
+
_setTestDependencies({ reader: mockReader });
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## CLI Command Testing
|
|
127
|
+
|
|
128
|
+
Test citty commands by providing mock context:
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
132
|
+
import { myCommand } from './my-command';
|
|
133
|
+
|
|
134
|
+
describe('My Command', () => {
|
|
135
|
+
describe('given valid arguments', () => {
|
|
136
|
+
it('should execute the expected action', async () => {
|
|
137
|
+
// Arrange
|
|
138
|
+
const mockPrompt = vi.fn().mockResolvedValue('user-input');
|
|
139
|
+
|
|
140
|
+
// Act
|
|
141
|
+
await myCommand.run({
|
|
142
|
+
rawArgs: ['--name', 'test'],
|
|
143
|
+
args: { _: [], name: 'test' },
|
|
144
|
+
cmd: myCommand,
|
|
145
|
+
data: { prompt: mockPrompt },
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// Assert
|
|
149
|
+
expect(mockPrompt).not.toHaveBeenCalled();
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Dependencies
|
|
156
|
+
|
|
157
|
+
Install new test dependencies using: `npm install <package>@<exact-version>`
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Specifications Directory
|
|
2
|
+
|
|
3
|
+
This directory contains feature specifications created through the spec-driven development workflow.
|
|
4
|
+
|
|
5
|
+
## Workflow Overview
|
|
6
|
+
|
|
7
|
+
1. **Create a Spec Issue** — Use the "Copilot Feature To Spec" issue template to define your feature
|
|
8
|
+
2. **Auto-Assignment** — Issues with the `copilot-ready` label automatically trigger Copilot assignment
|
|
9
|
+
3. **Spec Creation** — Copilot creates a structured specification in this directory
|
|
10
|
+
4. **Implementation** — Follow the tasks in the spec to implement the feature
|
|
11
|
+
|
|
12
|
+
## Spec File Structure
|
|
13
|
+
|
|
14
|
+
Each spec follows this structure:
|
|
15
|
+
|
|
16
|
+
```markdown
|
|
17
|
+
# Feature: <name>
|
|
18
|
+
|
|
19
|
+
## Problem Statement
|
|
20
|
+
<2-3 sentences describing the problem>
|
|
21
|
+
|
|
22
|
+
## Personas
|
|
23
|
+
| Persona | Impact | Notes |
|
|
24
|
+
|---------|--------|-------|
|
|
25
|
+
|
|
26
|
+
## Value Assessment
|
|
27
|
+
- **Primary value**: <type> — <explanation>
|
|
28
|
+
|
|
29
|
+
## User Stories
|
|
30
|
+
|
|
31
|
+
### Story 1: <Title>
|
|
32
|
+
As a **<persona>**,
|
|
33
|
+
I want **<capability>**,
|
|
34
|
+
so that I can **<outcome>**.
|
|
35
|
+
|
|
36
|
+
#### Acceptance Criteria
|
|
37
|
+
- When <trigger>, the <system> shall <response>
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Design
|
|
42
|
+
|
|
43
|
+
### Components Affected
|
|
44
|
+
### Dependencies
|
|
45
|
+
### Open Questions
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Tasks
|
|
50
|
+
|
|
51
|
+
### Task 1: <Title>
|
|
52
|
+
**Objective**: ...
|
|
53
|
+
**Verification**: ...
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## EARS Syntax for Acceptance Criteria
|
|
57
|
+
|
|
58
|
+
Use EARS (Easy Approach to Requirements Syntax) patterns:
|
|
59
|
+
|
|
60
|
+
| Pattern | Template | Use When |
|
|
61
|
+
|---------|----------|----------|
|
|
62
|
+
| Ubiquitous | The `<system>` shall `<response>` | Always true |
|
|
63
|
+
| Event-driven | When `<trigger>`, the `<system>` shall `<response>` | Responding to event |
|
|
64
|
+
| State-driven | While `<state>`, the `<system>` shall `<response>` | During a condition |
|
|
65
|
+
| Optional | Where `<feature>` is enabled, the `<system>` shall `<response>` | Configurable capability |
|
|
66
|
+
| Unwanted | If `<condition>`, then the `<system>` shall `<response>` | Error handling |
|
|
67
|
+
| Complex | While `<state>`, when `<trigger>`, the `<system>` shall `<response>` | Combining conditions |
|
|
68
|
+
|
|
69
|
+
### Examples
|
|
70
|
+
|
|
71
|
+
```markdown
|
|
72
|
+
- The CLI shall validate all input arguments
|
|
73
|
+
- When a user runs a command, the system shall display the result
|
|
74
|
+
- While verbose mode is enabled, the system shall log debug information
|
|
75
|
+
- Where custom configuration is provided, the system shall use it instead of defaults
|
|
76
|
+
- If the input is malformed, then the system shall return a descriptive error
|
|
77
|
+
- While strict mode is enabled, when an unknown argument is provided, the system shall reject the command
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Related Files
|
|
81
|
+
|
|
82
|
+
- `.github/ISSUE_TEMPLATE/feature-to-spec.yml` — Issue template for creating specs
|
|
83
|
+
- `.github/workflows/assign-copilot.yml` — Workflow for auto-assigning Copilot
|
|
84
|
+
- `.github/instructions/spec.instructions.md` — Detailed instructions for spec writing
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Auto-Assign Copilot on Spec Issues
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
issues:
|
|
6
|
+
types: [opened, edited]
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
issues: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
assign-agent:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- name: Assign and Instruct Copilot
|
|
16
|
+
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
|
17
|
+
with:
|
|
18
|
+
script: |
|
|
19
|
+
const issue = context.payload.issue;
|
|
20
|
+
|
|
21
|
+
// Check if issue has the copilot-ready label
|
|
22
|
+
const hasCopilotLabel = issue.labels.some(label => label.name === 'copilot-ready');
|
|
23
|
+
|
|
24
|
+
if (!hasCopilotLabel) {
|
|
25
|
+
console.log("Issue does not have 'copilot-ready' label. Skipping.");
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const body = issue.body || "";
|
|
30
|
+
const pattern = /### Extra Instructions\s+([\s\S]*?)(?=\n###|$)/;
|
|
31
|
+
const match = body.match(pattern);
|
|
32
|
+
|
|
33
|
+
// Always mention @copilot to trigger assignment and provide context
|
|
34
|
+
let comment = "@copilot";
|
|
35
|
+
|
|
36
|
+
if (match && match[1].trim().length > 0) {
|
|
37
|
+
let instructions = match[1].trim();
|
|
38
|
+
|
|
39
|
+
// Basic sanitization: limit length to prevent overly long comments
|
|
40
|
+
const MAX_LENGTH = 2000;
|
|
41
|
+
if (instructions.length > MAX_LENGTH) {
|
|
42
|
+
instructions = instructions.slice(0, MAX_LENGTH) + "\n\n[Instructions truncated]";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
comment = `@copilot ${instructions}`;
|
|
46
|
+
console.log("Found extra instructions, mentioning Copilot with instructions.");
|
|
47
|
+
} else {
|
|
48
|
+
comment = "@copilot Please work on this issue according to the specification provided.";
|
|
49
|
+
console.log("No extra instructions found, mentioning Copilot with default message.");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
await github.rest.issues.createComment({
|
|
53
|
+
owner: context.repo.owner,
|
|
54
|
+
repo: context.repo.repo,
|
|
55
|
+
issue_number: issue.number,
|
|
56
|
+
body: comment
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
console.log("Successfully mentioned Copilot in issue comment.");
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: CI
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [main]
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
lint:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- name: Checkout
|
|
18
|
+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
19
|
+
|
|
20
|
+
- name: Setup Node.js
|
|
21
|
+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
22
|
+
with:
|
|
23
|
+
node-version-file: '.nvmrc'
|
|
24
|
+
cache: 'npm'
|
|
25
|
+
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
run: npm ci
|
|
28
|
+
|
|
29
|
+
- name: Lint
|
|
30
|
+
run: npx biome check
|
|
31
|
+
|
|
32
|
+
test:
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
steps:
|
|
35
|
+
- name: Checkout
|
|
36
|
+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
37
|
+
|
|
38
|
+
- name: Setup Node.js
|
|
39
|
+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
40
|
+
with:
|
|
41
|
+
node-version-file: '.nvmrc'
|
|
42
|
+
cache: 'npm'
|
|
43
|
+
|
|
44
|
+
- name: Install dependencies
|
|
45
|
+
run: npm ci
|
|
46
|
+
|
|
47
|
+
- name: Run tests
|
|
48
|
+
run: npm test
|
|
49
|
+
|
|
50
|
+
build:
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
needs: [lint, test]
|
|
53
|
+
steps:
|
|
54
|
+
- name: Checkout
|
|
55
|
+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
56
|
+
|
|
57
|
+
- name: Setup Node.js
|
|
58
|
+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
59
|
+
with:
|
|
60
|
+
node-version-file: '.nvmrc'
|
|
61
|
+
cache: 'npm'
|
|
62
|
+
|
|
63
|
+
- name: Install dependencies
|
|
64
|
+
run: npm ci
|
|
65
|
+
|
|
66
|
+
- name: Build
|
|
67
|
+
run: npm run build
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
v24.13.0
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"recommendations": [
|
|
3
|
+
"biomejs.biome",
|
|
4
|
+
"editorconfig.editorconfig",
|
|
5
|
+
"vitest.explorer",
|
|
6
|
+
"ms-vscode-remote.remote-containers",
|
|
7
|
+
"GitHub.codespaces",
|
|
8
|
+
"GitHub.Copilot",
|
|
9
|
+
"GitHub.Copilot-Chat",
|
|
10
|
+
"GitHub.github-vscode-theme",
|
|
11
|
+
"redhat.vscode-yaml"
|
|
12
|
+
]
|
|
13
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.2.0",
|
|
3
|
+
"configurations": [
|
|
4
|
+
{
|
|
5
|
+
"name": "Start CLI Locally",
|
|
6
|
+
"type": "node",
|
|
7
|
+
"request": "launch",
|
|
8
|
+
"runtimeExecutable": "npm",
|
|
9
|
+
"runtimeArgs": ["run", "dev"],
|
|
10
|
+
"console": "integratedTerminal",
|
|
11
|
+
"cwd": "${workspaceFolder}"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "Debug Current Test File",
|
|
15
|
+
"type": "node",
|
|
16
|
+
"request": "launch",
|
|
17
|
+
"autoAttachChildProcesses": true,
|
|
18
|
+
"skipFiles": ["<node_internals>/**", "**/node_modules/**"],
|
|
19
|
+
"program": "${workspaceFolder}/node_modules/vitest/vitest.mjs",
|
|
20
|
+
"args": ["run", "${relativeFile}"],
|
|
21
|
+
"smartStep": true,
|
|
22
|
+
"console": "integratedTerminal"
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"servers": {
|
|
3
|
+
"context7": {
|
|
4
|
+
"type": "stdio",
|
|
5
|
+
"command": "npx",
|
|
6
|
+
"args": ["-y", "@upstash/context7-mcp"]
|
|
7
|
+
},
|
|
8
|
+
"sequential-thinking": {
|
|
9
|
+
"type": "stdio",
|
|
10
|
+
"command": "npx",
|
|
11
|
+
"args": ["-y", "@modelcontextprotocol/server-sequential-thinking"]
|
|
12
|
+
},
|
|
13
|
+
"lousy-agents": {
|
|
14
|
+
"type": "stdio",
|
|
15
|
+
"command": "npx",
|
|
16
|
+
"args": ["-y", "@lousy-agents/cli", "mcp"]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
extends: default
|
|
2
|
+
|
|
3
|
+
ignore: |
|
|
4
|
+
node_modules/
|
|
5
|
+
dist/
|
|
6
|
+
|
|
7
|
+
rules:
|
|
8
|
+
indentation:
|
|
9
|
+
spaces: 2
|
|
10
|
+
indent-sequences: true
|
|
11
|
+
line-length:
|
|
12
|
+
max: 120
|
|
13
|
+
level: warning
|
|
14
|
+
|
|
15
|
+
document-start: disable
|
|
16
|
+
truthy: disable
|
|
17
|
+
comments:
|
|
18
|
+
min-spaces-from-content: 1
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"root": false,
|
|
3
|
+
"$schema": "https://biomejs.dev/schemas/2.3.13/schema.json",
|
|
4
|
+
"vcs": {
|
|
5
|
+
"enabled": true,
|
|
6
|
+
"clientKind": "git",
|
|
7
|
+
"useIgnoreFile": true
|
|
8
|
+
},
|
|
9
|
+
"files": {
|
|
10
|
+
"ignoreUnknown": false
|
|
11
|
+
},
|
|
12
|
+
"formatter": {
|
|
13
|
+
"enabled": true,
|
|
14
|
+
"indentStyle": "space",
|
|
15
|
+
"indentWidth": 4
|
|
16
|
+
},
|
|
17
|
+
"linter": {
|
|
18
|
+
"enabled": true,
|
|
19
|
+
"rules": {
|
|
20
|
+
"recommended": true,
|
|
21
|
+
"style": {
|
|
22
|
+
"useConsistentCurlyBraces": "error"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"javascript": {
|
|
27
|
+
"formatter": {
|
|
28
|
+
"quoteStyle": "double"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "<%= it.projectName %>",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "tsx watch src/index.ts",
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"start": "node dist/index.js",
|
|
10
|
+
"test": "vitest run",
|
|
11
|
+
"lint": "biome check .",
|
|
12
|
+
"lint:fix": "biome check --write .",
|
|
13
|
+
"lint:workflows": "actionlint",
|
|
14
|
+
"lint:yaml": "yamllint ."
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"citty": "0.2.0",
|
|
18
|
+
"consola": "3.4.2",
|
|
19
|
+
"zod": "3.25.56"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@biomejs/biome": "2.3.8",
|
|
23
|
+
"@types/node": "22.16.4",
|
|
24
|
+
"chance": "1.1.12",
|
|
25
|
+
"tsx": "4.20.3",
|
|
26
|
+
"typescript": "5.8.3",
|
|
27
|
+
"vitest": "4.0.15"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"lib": ["ES2022"],
|
|
5
|
+
"module": "NodeNext",
|
|
6
|
+
"moduleResolution": "NodeNext",
|
|
7
|
+
"strict": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
|
11
|
+
"outDir": "./dist",
|
|
12
|
+
"rootDir": "./src",
|
|
13
|
+
"declaration": true,
|
|
14
|
+
"declarationMap": true,
|
|
15
|
+
"sourceMap": true,
|
|
16
|
+
"resolveJsonModule": true,
|
|
17
|
+
"noEmit": false,
|
|
18
|
+
"isolatedModules": true,
|
|
19
|
+
"noUnusedLocals": true,
|
|
20
|
+
"noUnusedParameters": true,
|
|
21
|
+
"noFallthroughCasesInSwitch": true,
|
|
22
|
+
"exactOptionalPropertyTypes": true,
|
|
23
|
+
"noImplicitReturns": true,
|
|
24
|
+
"noUncheckedIndexedAccess": true
|
|
25
|
+
},
|
|
26
|
+
"include": ["src/**/*.ts"],
|
|
27
|
+
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
|
|
28
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { defineConfig } from "vitest/config";
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
test: {
|
|
5
|
+
globals: true,
|
|
6
|
+
environment: "node",
|
|
7
|
+
setupFiles: ["./vitest.setup.ts"],
|
|
8
|
+
include: ["src/**/*.test.ts"],
|
|
9
|
+
coverage: {
|
|
10
|
+
provider: "v8",
|
|
11
|
+
reporter: ["text", "json", "html"],
|
|
12
|
+
exclude: ["node_modules/", "dist/", "**/*.test.ts"],
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
});
|