From 00f7b6613d1e1509019c41ad31106913a4d63afd Mon Sep 17 00:00:00 2001 From: Erdem Tuna Date: Thu, 26 Feb 2026 15:41:51 +0300 Subject: [PATCH 01/18] Initialize PAW workflow for GitHub Actions CI/CD Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../github-actions-cicd/WorkflowContext.md | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .paw/work/github-actions-cicd/WorkflowContext.md diff --git a/.paw/work/github-actions-cicd/WorkflowContext.md b/.paw/work/github-actions-cicd/WorkflowContext.md new file mode 100644 index 0000000..0ba20b4 --- /dev/null +++ b/.paw/work/github-actions-cicd/WorkflowContext.md @@ -0,0 +1,40 @@ +# WorkflowContext + +Work Title: GitHub Actions CI/CD +Work ID: github-actions-cicd +Base Branch: main +Target Branch: feature/github-actions-cicd +Workflow Mode: full +Review Strategy: local +Review Policy: milestones +Session Policy: continuous +Final Agent Review: enabled +Final Review Mode: single-model +Final Review Interactive: smart +Final Review Models: none +Final Review Specialists: all +Final Review Interaction Mode: parallel +Final Review Specialist Models: none +Plan Generation Mode: single-model +Plan Generation Models: none +Planning Docs Review: enabled +Planning Review Mode: single-model +Planning Review Interactive: smart +Planning Review Models: none +Custom Workflow Instructions: none +Initial Prompt: Create GitHub Actions workflows for markdown-commenter: PR checks (lint, compile, test), extension release (v* tags -> GitHub Release + VS Code Marketplace), and CLI publish (cli-v* tags -> npm). Model after PAW's existing workflows. +Issue URL: none +Remote: origin +Artifact Lifecycle: commit-and-clean +Artifact Paths: auto-derived +Additional Inputs: WorkShaping-GHActions.md + +## Stage Progress + +- [ ] Specification +- [ ] Code Research +- [ ] Planning +- [ ] Planning Docs Review +- [ ] Implementation +- [ ] Final Review +- [ ] Final PR From c14ac5d93048c7909fa6056724cca65abf999bcc Mon Sep 17 00:00:00 2001 From: Erdem Tuna Date: Thu, 26 Feb 2026 15:43:18 +0300 Subject: [PATCH 02/18] Add specification for GitHub Actions CI/CD Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .paw/work/github-actions-cicd/Spec.md | 180 ++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 .paw/work/github-actions-cicd/Spec.md diff --git a/.paw/work/github-actions-cicd/Spec.md b/.paw/work/github-actions-cicd/Spec.md new file mode 100644 index 0000000..df3c712 --- /dev/null +++ b/.paw/work/github-actions-cicd/Spec.md @@ -0,0 +1,180 @@ +# Feature Specification: GitHub Actions CI/CD + +**Branch**: feature/github-actions-cicd | **Created**: 2026-02-26 | **Status**: Draft +**Input Brief**: Automate build, test, and release pipelines for markdown-commenter VS Code extension and CLI + +## Overview + +The markdown-commenter project currently lacks automated CI/CD infrastructure. Every release requires manual execution of build commands, manual VSIX packaging, manual uploads to VS Code Marketplace, and manual npm publishing. This is error-prone, time-consuming, and doesn't scale as the project grows. + +This feature establishes GitHub Actions workflows that automate quality gates on pull requests and streamline the release process for both the VS Code extension and Copilot CLI. By modeling after PAW's mature CI/CD patterns, maintainers can confidently merge PRs knowing they've passed automated checks, and release new versions by simply pushing a git tag. + +The automation serves two user groups: contributors who benefit from immediate feedback on code quality, and maintainers who can release with confidence through a standardized, repeatable process. The workflows are designed for resilience—if VS Code Marketplace upload fails, the GitHub Release with downloadable VSIX is still created. + +## Objectives + +- Enable automated quality validation on every pull request (lint, compile, test) +- Provide one-command releases via git tags for both extension and CLI +- Publish VS Code extension to both GitHub Releases and VS Code Marketplace +- Publish CLI package to npm registry with provenance +- Enforce agent/skill token size limits to prevent oversized prompts +- Document secrets setup and release procedures inline in workflow files + +## User Scenarios & Testing + +### User Story P1 – Contributor Submits a Pull Request +**Narrative**: A contributor opens a PR with code changes. Within minutes, they receive feedback on whether their changes pass linting, compilation, and tests without needing to run commands locally. + +**Independent Test**: Open a PR with a TypeScript syntax error; verify the workflow fails and reports the error. + +**Acceptance Scenarios**: +1. Given a PR is opened to main, When the PR contains valid code, Then all checks pass and show green status +2. Given a PR is opened to main, When the PR contains a lint violation, Then the lint step fails with a clear error message +3. Given a PR is opened to main, When the PR contains a test failure, Then the test step fails showing which test failed +4. Given a PR modifies only documentation files, When no source files changed, Then the workflow is skipped (path filtering) + +### User Story P2 – Maintainer Releases VS Code Extension +**Narrative**: A maintainer pushes a version tag (e.g., `v1.0.0`). The workflow builds the extension, creates a GitHub Release with the VSIX attached, and publishes to VS Code Marketplace. + +**Independent Test**: Push a `v0.0.2` tag; verify GitHub Release is created with VSIX file attached. + +**Acceptance Scenarios**: +1. Given a `v*` tag is pushed, When the build succeeds, Then a GitHub Release is created with the VSIX attached +2. Given a `v*` tag is pushed, When Marketplace upload fails, Then GitHub Release is still created (with warning logged) +3. Given a `v0.3.0` tag (odd minor), When the release is created, Then it is marked as pre-release +4. Given a `v0.2.0` tag (even minor), When the release is created, Then it is marked as stable release +5. Given the same tag is pushed twice, When a release already exists, Then the workflow skips release creation (idempotent) + +### User Story P3 – Maintainer Releases CLI Package +**Narrative**: A maintainer pushes a CLI version tag (e.g., `cli-v1.0.0`). The workflow builds, tests, and publishes the CLI to npm, then creates a GitHub Release. + +**Independent Test**: Push a `cli-v0.0.2` tag; verify npm package is published and GitHub Release is created. + +**Acceptance Scenarios**: +1. Given a `cli-v*` tag is pushed, When build and tests pass, Then npm package is published with provenance +2. Given a `cli-v1.0.0-beta` tag, When published to npm, Then the package is tagged as `beta` (not `latest`) +3. Given a `cli-v*` tag is pushed, When npm publish succeeds, Then a GitHub Release is created +4. Given CLI tests fail, When the workflow runs, Then npm publish is skipped and workflow fails + +### User Story P4 – Contributor Adds Large Agent File +**Narrative**: A contributor adds or modifies an agent file that exceeds token limits. The PR checks catch this before merge to prevent oversized prompts in production. + +**Independent Test**: Add an agent file with 8000+ tokens; verify PR checks fail with token limit error. + +**Acceptance Scenarios**: +1. Given an agent file exceeds 7000 tokens, When PR checks run, Then the lint step fails with error +2. Given an agent file is between 5000-7000 tokens, When PR checks run, Then a warning is shown but checks pass +3. Given a skill file exceeds 12000 tokens, When PR checks run, Then the lint step fails with error + +### Edge Cases + +- **Package.json version mismatch**: Workflow extracts version from tag and updates package.json, ensuring tag is source of truth +- **Orphaned tags**: If workflow fails mid-execution, tag remains but no release exists; maintainer can re-trigger or delete tag +- **VSCE_PAT expired**: Marketplace upload fails; GitHub Release created anyway; maintainer renews PAT and can manually publish +- **npm OIDC misconfigured**: npm publish fails; workflow fails; maintainer must fix OIDC setup before retry +- **Feature branch tag**: Branch protection should prevent this; if bypassed, workflow runs but release may contain unexpected code + +## Requirements + +### Functional Requirements + +- FR-001: PR checks workflow triggers on pull requests to main branch (Stories: P1) +- FR-002: PR checks workflow runs TypeScript linting via `npm run lint` (Stories: P1) +- FR-003: PR checks workflow compiles extension via `npm run compile` (Stories: P1) +- FR-004: PR checks workflow runs VS Code extension tests with xvfb (Stories: P1) +- FR-005: PR checks workflow runs CLI tests via `cd cli && npm test` (Stories: P1) +- FR-006: PR checks workflow runs agent/skill token linting (Stories: P1, P4) +- FR-007: PR checks workflow uses path filtering to skip on non-code changes (Stories: P1) +- FR-008: Extension release workflow triggers on `v*` tag push (Stories: P2) +- FR-009: Extension release workflow extracts version from tag and updates package.json (Stories: P2) +- FR-010: Extension release workflow determines pre-release status from version number (Stories: P2) +- FR-011: Extension release workflow packages VSIX file (Stories: P2) +- FR-012: Extension release workflow creates GitHub Release with VSIX attached (Stories: P2) +- FR-013: Extension release workflow publishes to VS Code Marketplace (Stories: P2) +- FR-014: Extension release workflow continues on Marketplace failure (Stories: P2) +- FR-015: Extension release workflow skips if release already exists (Stories: P2) +- FR-016: CLI publish workflow triggers on `cli-v*` tag push (Stories: P3) +- FR-017: CLI publish workflow builds and tests CLI package (Stories: P3) +- FR-018: CLI publish workflow publishes to npm with OIDC provenance (Stories: P3) +- FR-019: CLI publish workflow creates GitHub Release after npm publish (Stories: P3) +- FR-020: CLI publish workflow determines npm tag from version suffix (Stories: P3) +- FR-021: Token linting script counts tokens using tiktoken library (Stories: P4) +- FR-022: Token linting script enforces configurable thresholds (Stories: P4) + +### Key Entities + +- **Workflow**: GitHub Actions YAML file defining automated jobs +- **Tag**: Git reference triggering release workflows (`v*` or `cli-v*`) +- **VSIX**: VS Code extension package file +- **Release**: GitHub Release with attached artifacts and notes + +### Cross-Cutting / Non-Functional + +- Workflows must complete within GitHub Actions timeout limits (6 hours default) +- Secrets (VSCE_PAT) must be documented but not committed +- npm publishing must use OIDC (no token secrets) +- All workflows must include descriptive comments explaining purpose and setup + +## Success Criteria + +- SC-001: PRs receive automated feedback within 5 minutes of opening (FR-001, FR-002, FR-003, FR-004, FR-005) +- SC-002: Pushing a `v*` tag results in a GitHub Release with downloadable VSIX within 10 minutes (FR-008, FR-011, FR-012) +- SC-003: VS Code Marketplace shows the extension after successful release (FR-013) +- SC-004: npm registry shows CLI package with provenance after `cli-v*` tag push (FR-016, FR-018) +- SC-005: Agent files exceeding 7000 tokens cause PR check failure (FR-006, FR-021, FR-022) +- SC-006: Workflows are self-documenting with inline comments explaining secrets setup (FR-013, FR-018) +- SC-007: Duplicate tag push does not create duplicate release (FR-015) + +## Assumptions + +- **Publisher ID**: VS Code Marketplace publisher is `erdem-tuna` (from package.json) +- **npm scope**: CLI package scope is `@erdem-tuna/markdown-commenter` (from cli/package.json) +- **Token thresholds**: Use PAW defaults (5K warn, 7K error for agents; 8K warn, 12K error for skills) +- **No docs workflow**: MkDocs documentation workflow not needed for initial release +- **Branch protection**: Repository will have branch protection enabled on main (documented requirement, not enforced by workflows) +- **tiktoken compatibility**: The `@dqbd/tiktoken` package works in GitHub Actions Node.js 20 environment + +## Scope + +**In Scope**: +- PR checks workflow (lint, compile, test, agent lint) +- Extension release workflow (build, GitHub Release, Marketplace) +- CLI publish workflow (build, test, npm, GitHub Release) +- Token linting scripts (lint-prompting.sh, count-tokens.js) +- Inline documentation in workflow files +- npm scripts for local linting + +**Out of Scope**: +- Documentation site workflow (MkDocs) +- Automatic changelog generation +- Release notes automation +- Slack/Discord notifications +- Code coverage reporting +- Security scanning (CodeQL, Dependabot) +- Matrix testing across Node versions +- Windows/macOS runner support + +## Dependencies + +- GitHub Actions (service) +- VS Code Marketplace API (service) +- npm registry with OIDC support (service) +- `@dqbd/tiktoken` npm package (library) +- `@vscode/vsce` for VSIX packaging (existing devDependency) +- Repository secrets: `VSCE_PAT` (for Marketplace publishing) + +## Risks & Mitigations + +- **VSCE_PAT expiration**: PATs expire periodically. **Mitigation**: Document renewal process in workflow comments; GitHub Release created even if Marketplace fails. +- **npm OIDC complexity**: OIDC setup requires npm package configuration. **Mitigation**: Document prerequisites clearly; test with dry-run before first real publish. +- **tiktoken version drift**: Token counting may vary across versions. **Mitigation**: Pin version in package.json. +- **Workflow maintenance burden**: Three workflows to maintain. **Mitigation**: Model closely after PAW patterns for consistency; consider composite actions in future. +- **Branch protection bypass**: Emergency hotfixes may bypass checks. **Mitigation**: Document bypass procedure; accept as intentional escape hatch. + +## References + +- WorkShaping: ./WorkShaping-GHActions.md +- PAW PR Checks: /home/erdemtuna/workspace/personal/phased-agent-workflow/.github/workflows/pr-checks.yml +- PAW Release: /home/erdemtuna/workspace/personal/phased-agent-workflow/.github/workflows/release.yml +- PAW CLI Publish: /home/erdemtuna/workspace/personal/phased-agent-workflow/.github/workflows/publish-cli.yml +- PAW Lint Script: /home/erdemtuna/workspace/personal/phased-agent-workflow/scripts/lint-prompting.sh From b2d6d4871e1a824a5ebaecaa4605b0b21e66509c Mon Sep 17 00:00:00 2001 From: Erdem Tuna Date: Thu, 26 Feb 2026 15:45:28 +0300 Subject: [PATCH 03/18] Add code research for GitHub Actions implementation Documents PAW workflow patterns and markdown-commenter structure. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .paw/work/github-actions-cicd/CodeResearch.md | 375 ++++++++++++++++++ 1 file changed, 375 insertions(+) create mode 100644 .paw/work/github-actions-cicd/CodeResearch.md diff --git a/.paw/work/github-actions-cicd/CodeResearch.md b/.paw/work/github-actions-cicd/CodeResearch.md new file mode 100644 index 0000000..0d0c243 --- /dev/null +++ b/.paw/work/github-actions-cicd/CodeResearch.md @@ -0,0 +1,375 @@ +--- +date: 2026-02-26T12:45:00+00:00 +git_commit: c14ac5d +branch: feature/github-actions-cicd +repository: markdown-commenter +topic: "GitHub Actions CI/CD Implementation Patterns" +tags: [research, codebase, github-actions, ci-cd, workflows] +status: complete +last_updated: 2026-02-26 +--- + +# Research: GitHub Actions CI/CD Implementation Patterns + +## Research Question + +What are the implementation patterns, file structures, and technical details needed to create GitHub Actions workflows for markdown-commenter, based on PAW's existing workflows? + +## Summary + +PAW provides mature GitHub Actions workflows that can be directly adapted for markdown-commenter. The three workflows (PR checks, extension release, CLI publish) follow consistent patterns: tag-triggered releases, version extraction from tags, pre-release detection, and idempotent release creation. The token linting infrastructure requires `@dqbd/tiktoken` dependency and two scripts. markdown-commenter already has the necessary npm scripts for lint/compile/test but lacks agent linting scripts. + +## Documentation System + +- **Framework**: markdown (README.md only) +- **Docs Directory**: N/A (no dedicated docs folder) +- **Navigation Config**: N/A +- **Style Conventions**: Standard GitHub README with badges, features list, installation instructions +- **Build Command**: N/A +- **Standard Files**: README.md (root), CHANGELOG.md (root), LICENSE (root) + +## Verification Commands + +- **Test Command**: `npm test` (extension), `cd cli && npm test` (CLI - currently no tests) +- **Lint Command**: `npm run lint` (eslint on src/) +- **Build Command**: `npm run compile` (TypeScript compilation) +- **Type Check**: Implicit via `npm run compile` (tsc) +- **Package Command**: `npm run package` (vsce package) + +## Detailed Findings + +### PAW PR Checks Workflow + +**Location**: `/home/erdemtuna/workspace/personal/phased-agent-workflow/.github/workflows/pr-checks.yml` + +**Trigger Configuration** (lines 6-16): +```yaml +on: + pull_request: + branches: + - main + - 'feature/**' + paths: + - 'src/**' + - 'agents/**' + - 'skills/**' + - 'scripts/**' + - '.github/workflows/pr-checks.yml' +``` + +**Job Structure** (lines 18-66): +- Single job named `test` on `ubuntu-latest` +- Node.js 20 with npm caching via `cache-dependency-path: package-lock.json` +- Steps: checkout → setup-node → npm ci → lint → compile → xvfb test → agent lint → summary + +**xvfb Pattern** (lines 43-54): +```bash +sudo apt-get update +sudo apt-get install -y xvfb +xvfb-run -a npm test +``` +Environment variable `DISPLAY: ':99.0'` set for headless testing. + +**Agent Linting** (line 57): +```bash +npm run lint:agent:all +``` + +### PAW Extension Release Workflow + +**Location**: `/home/erdemtuna/workspace/personal/phased-agent-workflow/.github/workflows/release.yml` + +**Trigger** (lines 6-9): +```yaml +on: + push: + tags: + - 'v*' +``` + +**Permissions** (lines 15-16): +```yaml +permissions: + contents: write # Required to create releases and upload assets +``` + +**Version Extraction Pattern** (lines 35-43): +```bash +TAG_NAME="${{ github.ref_name }}" +VERSION="${TAG_NAME#v}" # Remove 'v' prefix +echo "version=${VERSION}" >> $GITHUB_OUTPUT +``` + +**Package.json Version Update** (lines 45-53): +```bash +npm version ${TAG_VERSION} --no-git-tag-version --allow-same-version +``` +This makes the git tag the source of truth for versioning. + +**Pre-release Detection** (lines 55-71): +```bash +MINOR=$(echo $VERSION | cut -d. -f2) +if [ $((MINOR % 2)) -eq 1 ]; then + echo "is_prerelease=true" >> $GITHUB_OUTPUT +else + echo "is_prerelease=false" >> $GITHUB_OUTPUT +fi +``` +Odd minor versions (0.1.x, 0.3.x) are pre-releases. + +**VSIX Verification** (lines 78-89): +```bash +VSIX_FILE="paw-workflow-${{ steps.version.outputs.version }}.vsix" +if [ ! -f "$VSIX_FILE" ]; then + exit 1 +fi +``` +Package name from package.json determines VSIX filename. + +**Release Existence Check** (lines 91-101): +```bash +RELEASE_EXISTS=$(gh release view "${{ github.ref_name }}" --json id 2>/dev/null || echo "") +``` +Uses GitHub CLI to check; skips creation if exists (idempotent). + +**Release Creation** (lines 103-115): +Uses `softprops/action-gh-release@v1` action with: +- `files:` for VSIX attachment +- `prerelease:` from detection step +- `fail_on_unmatched_files: true` + +### PAW CLI Publish Workflow + +**Location**: `/home/erdemtuna/workspace/personal/phased-agent-workflow/.github/workflows/publish-cli.yml` + +**Trigger** (lines 3-6): +```yaml +on: + push: + tags: + - 'cli-v*' +``` + +**Permissions** (lines 8-10): +```yaml +permissions: + id-token: write # Required for OIDC trusted publishing + contents: write # Required to create GitHub releases +``` + +**Working Directory Default** (lines 15-17): +```yaml +defaults: + run: + working-directory: cli +``` + +**Node.js Setup with Registry** (lines 22-26): +```yaml +uses: actions/setup-node@v4 +with: + node-version: '24' + registry-url: 'https://registry.npmjs.org' +``` +Note: Uses Node 24 (newer than extension workflow). + +**CLI Version Extraction** (lines 28-34): +```bash +VERSION="${TAG_NAME#cli-v}" # Remove 'cli-v' prefix +``` + +**CLI Pre-release Detection** (lines 36-49): +```bash +if [[ "$VERSION" =~ -(alpha|beta|rc) ]]; then + echo "npm_tag=beta" >> $GITHUB_OUTPUT +else + echo "npm_tag=latest" >> $GITHUB_OUTPUT +fi +``` +Uses semver suffix pattern, not odd/even minor. + +**npm Publish with OIDC** (line 64): +```bash +npm publish --access public --tag ${{ steps.prerelease.outputs.npm_tag }} +``` +No `NPM_TOKEN` needed; OIDC provides authentication via `id-token: write` permission. + +### PAW Token Linting Scripts + +**lint-prompting.sh Location**: `/home/erdemtuna/workspace/personal/phased-agent-workflow/scripts/lint-prompting.sh` + +**Token Thresholds** (lines 10-16): +```bash +WARN_THRESHOLD=5000 +ERROR_THRESHOLD=7000 +SKILL_WARN_THRESHOLD=8000 +SKILL_ERROR_THRESHOLD=12000 +``` + +**Dependency Check** (lines 31-35): +```bash +if [ ! -d "node_modules/@dqbd/tiktoken" ]; then + echo -e "${RED}ERROR: Dependencies are not installed${NC}" + exit 1 +fi +``` + +**Agent File Pattern** (line 104): +```bash +local files=("$agent_dir"/*.agent.md) +``` +Expects `agents/*.agent.md` naming convention. + +**Skill File Pattern** (line 132): +```bash +find "$skill_dir" -name "SKILL.md" -type f -print0 +``` +Expects `skills/*/SKILL.md` naming convention. + +**CLI Arguments** (lines 161-175): +- No args: lint all agents +- `--skills`: lint only skills +- `--all`: lint both agents and skills + +**count-tokens.js Location**: `/home/erdemtuna/workspace/personal/phased-agent-workflow/scripts/count-tokens.js` + +**tiktoken Usage** (lines 9, 81): +```javascript +const { encoding_for_model } = require('@dqbd/tiktoken'); +const encoding = encoding_for_model(model); +``` +Uses `gpt-4o-mini` as default model (line 20). + +**PAW-Specific Template Expansion** (lines 62-72): +The script has PAW-specific logic to expand `{{PLACEHOLDER}}` patterns in agent files. This uses `ts-node` to load `src/agents/agentTemplateRenderer`. markdown-commenter does not have this pattern, so this section can be simplified or removed. + +### markdown-commenter Current Structure + +**package.json Location**: `/home/erdemtuna/workspace/personal/markdown-commenter/package.json` + +**Existing Scripts** (lines 111-123): +```json +"scripts": { + "vscode:prepublish": "npm run compile", + "compile": "tsc -p ./", + "watch": "tsc -watch -p ./", + "lint": "eslint src --ext ts", + "test": "node ./out/test/runTest.js", + "package": "vsce package" +} +``` + +**Missing Scripts**: +- `lint:agent` - single agent file linting +- `lint:agent:all` - lint all agents and skills +- `lint:skills` - lint only skills + +**Package Name** (line 2): `markdown-commenter` +VSIX will be named `markdown-commenter-.vsix` + +**Publisher** (line 7): `erdem-tuna` +Required for VS Code Marketplace publishing. + +**Existing DevDependencies** (lines 124-136): +- `@vscode/vsce` already present for VSIX packaging +- `@dqbd/tiktoken` NOT present (needs to be added) +- `ts-node` NOT present (only needed if using template expansion) + +**cli/package.json Location**: `/home/erdemtuna/workspace/personal/markdown-commenter/cli/package.json` + +**Package Scope** (line 2): `@erdem-tuna/markdown-commenter` +This is the npm package name for publishing. + +**CLI Scripts** (lines 17-21): +```json +"scripts": { + "build": "node scripts/build.js", + "test": "node --test lib/*.test.js", + "lint": "echo 'No lint configured for CLI package'" +} +``` + +**CLI Test Status**: No test files exist (`lib/*.test.js` pattern matches nothing). +PR checks can still run `npm test` which will pass with no tests. + +### Agent/Skill File Structure + +**Agent File**: `/home/erdemtuna/workspace/personal/markdown-commenter/agents/Annotate.agent.md` +- Single agent file +- Standard naming convention (matches `*.agent.md` pattern) + +**Skill File**: `/home/erdemtuna/workspace/personal/markdown-commenter/skills/annotate/SKILL.md` +- Single skill in `annotate/` subdirectory +- Matches `skills/*/SKILL.md` pattern expected by lint script + +## Code References + +### PAW Workflows +- `/home/erdemtuna/workspace/personal/phased-agent-workflow/.github/workflows/pr-checks.yml:1-66` - PR checks workflow +- `/home/erdemtuna/workspace/personal/phased-agent-workflow/.github/workflows/release.yml:1-116` - Extension release workflow +- `/home/erdemtuna/workspace/personal/phased-agent-workflow/.github/workflows/publish-cli.yml:1-92` - CLI publish workflow + +### PAW Linting Scripts +- `/home/erdemtuna/workspace/personal/phased-agent-workflow/scripts/lint-prompting.sh:1-227` - Token linting bash script +- `/home/erdemtuna/workspace/personal/phased-agent-workflow/scripts/count-tokens.js:1-97` - Token counting Node.js script + +### markdown-commenter Targets +- `/home/erdemtuna/workspace/personal/markdown-commenter/package.json:111-123` - Existing npm scripts +- `/home/erdemtuna/workspace/personal/markdown-commenter/cli/package.json:17-21` - CLI scripts +- `/home/erdemtuna/workspace/personal/markdown-commenter/agents/Annotate.agent.md` - Agent file to lint +- `/home/erdemtuna/workspace/personal/markdown-commenter/skills/annotate/SKILL.md` - Skill file to lint + +## Architecture Documentation + +### Workflow Patterns + +1. **Tag-Triggered Releases**: Both extension (`v*`) and CLI (`cli-v*`) use tag push triggers. This decouples versioning from code changes. + +2. **Version Source of Truth**: Git tag determines version; package.json is updated at build time via `npm version --no-git-tag-version`. + +3. **Idempotent Release Creation**: Check if release exists before creating; skip if already exists. Prevents duplicate releases on re-runs. + +4. **Pre-release Detection**: Extension uses odd/even minor version convention; CLI uses semver suffix (`-alpha`, `-beta`, `-rc`). + +5. **Graceful Degradation**: For Marketplace publishing, continue on failure so GitHub Release is still created (specified in WorkShaping, not implemented in PAW's current workflow—needs to be added). + +### Token Linting Patterns + +1. **Threshold Tiers**: Warning threshold allows PR to pass with notice; error threshold fails the build. + +2. **File Discovery**: Agent files via glob pattern; skill files via `find` command for nested structure. + +3. **Dependency Validation**: Script checks for `@dqbd/tiktoken` in node_modules before proceeding. + +## Adaptations Required for markdown-commenter + +### Simplifications from PAW + +1. **count-tokens.js**: Remove PAW-specific template expansion logic (lines 28-72). markdown-commenter agents don't use `{{PLACEHOLDER}}` patterns. + +2. **Node Version**: Can use Node 20 for CLI workflow (PAW uses 24, but 20 is sufficient and consistent with extension workflow). + +### Additions to PAW Patterns + +1. **VS Code Marketplace Publishing**: PAW's `release.yml` only creates GitHub Release. Need to add `vsce publish` step with `VSCE_PAT` secret. + +2. **Marketplace Failure Handling**: Add `continue-on-error: true` to Marketplace step so GitHub Release is still created on failure. + +3. **CLI Path in PR Checks**: PAW doesn't run CLI tests in PR checks. Need to add `cd cli && npm test` step. + +### Files to Create + +1. `.github/workflows/pr-checks.yml` - PR quality gates +2. `.github/workflows/release.yml` - Extension release + Marketplace +3. `.github/workflows/publish-cli.yml` - CLI npm publish +4. `scripts/lint-prompting.sh` - Token linting script +5. `scripts/count-tokens.js` - Token counting utility (simplified) + +### Package.json Updates + +1. Add `@dqbd/tiktoken` to devDependencies +2. Add npm scripts: `lint:agent`, `lint:agent:all`, `lint:skills` + +## Open Questions + +None - all implementation details are documented with sufficient precision for planning. From 5cef07bbfe9321b91a5107b2f6a993592f472d09 Mon Sep 17 00:00:00 2001 From: Erdem Tuna Date: Thu, 26 Feb 2026 15:46:46 +0300 Subject: [PATCH 04/18] Add implementation plan for GitHub Actions CI/CD 5 phases: token linting, PR checks, extension release, CLI publish, docs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../github-actions-cicd/ImplementationPlan.md | 250 ++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 .paw/work/github-actions-cicd/ImplementationPlan.md diff --git a/.paw/work/github-actions-cicd/ImplementationPlan.md b/.paw/work/github-actions-cicd/ImplementationPlan.md new file mode 100644 index 0000000..969f52f --- /dev/null +++ b/.paw/work/github-actions-cicd/ImplementationPlan.md @@ -0,0 +1,250 @@ +# GitHub Actions CI/CD Implementation Plan + +## Overview + +Implementing automated CI/CD infrastructure for markdown-commenter, consisting of three GitHub Actions workflows (PR checks, extension release, CLI publish) and supporting token linting scripts. The implementation directly adapts PAW's mature workflow patterns, customized for markdown-commenter's package structure and publishing requirements. + +## Current State Analysis + +**Existing infrastructure**: +- VS Code extension with `npm run lint`, `compile`, `test`, `package` scripts (package.json:111-123) +- CLI package with `npm run build`, `test` scripts (cli/package.json:17-21) +- Agent file at `agents/Annotate.agent.md` +- Skill file at `skills/annotate/SKILL.md` +- `@vscode/vsce` already in devDependencies for VSIX packaging + +**Gaps**: +- No `.github/workflows/` directory or workflow files +- No `scripts/` directory for linting utilities +- No `@dqbd/tiktoken` dependency for token counting +- No `lint:agent*` npm scripts + +**Key constraints**: +- VSIX filename will be `markdown-commenter-.vsix` (from package.json name) +- npm package scope is `@erdem-tuna/markdown-commenter` (cli/package.json:2) +- Publisher ID is `erdem-tuna` (package.json:7) + +## Desired End State + +1. **PR Checks**: Every PR to main runs lint, compile, extension tests, CLI tests, and agent linting +2. **Extension Release**: Pushing `v*` tag creates GitHub Release with VSIX and publishes to VS Code Marketplace +3. **CLI Publish**: Pushing `cli-v*` tag publishes to npm with OIDC provenance and creates GitHub Release +4. **Token Linting**: Local and CI execution of agent/skill token validation + +**Verification approach**: +- Create test PR to verify PR checks workflow +- Push test tag to verify release workflow (can use pre-release version like `v0.0.2`) +- Verify npm scripts work locally before pushing + +## What We're NOT Doing + +- MkDocs documentation workflow (no docs framework in use) +- Automatic changelog generation +- Release notes automation +- Slack/Discord notifications +- Code coverage reporting +- Security scanning (CodeQL, Dependabot) +- Matrix testing across Node versions +- Windows/macOS runner support + +## Phase Status + +- [ ] **Phase 1: Token Linting Infrastructure** - Add scripts and dependencies for agent/skill token validation +- [ ] **Phase 2: PR Checks Workflow** - Automated quality gates on pull requests +- [ ] **Phase 3: Extension Release Workflow** - Tag-triggered VSIX build, GitHub Release, and Marketplace publishing +- [ ] **Phase 4: CLI Publish Workflow** - Tag-triggered npm publish with OIDC +- [ ] **Phase 5: Documentation** - Technical reference and README updates + +## Phase Candidates + + + +--- + +## Phase 1: Token Linting Infrastructure + +### Changes Required + +- **`scripts/lint-prompting.sh`**: Copy from PAW (`/home/erdemtuna/workspace/personal/phased-agent-workflow/scripts/lint-prompting.sh`), no modifications needed—script is generic and works with standard `agents/*.agent.md` and `skills/*/SKILL.md` patterns + +- **`scripts/count-tokens.js`**: Simplified version of PAW's script, removing template expansion logic (lines 28-72 in PAW version). markdown-commenter agents don't use `{{PLACEHOLDER}}` patterns. Keep core functionality: + - tiktoken integration for token counting + - File path argument handling + - Model parameter (default: `gpt-4o-mini`) + +- **`package.json`**: + - Add `@dqbd/tiktoken` to devDependencies + - Add scripts: + ``` + "lint:agent": "./scripts/lint-prompting.sh", + "lint:agent:all": "./scripts/lint-prompting.sh --all", + "lint:skills": "./scripts/lint-prompting.sh --skills" + ``` + +### Success Criteria + +#### Automated Verification: +- [ ] `npm run lint:agent` passes (lints agents/Annotate.agent.md) +- [ ] `npm run lint:skills` passes (lints skills/annotate/SKILL.md) +- [ ] `npm run lint:agent:all` passes (lints both) + +#### Manual Verification: +- [ ] Output shows token counts with colored OK/WARN/ERROR status +- [ ] Script fails with exit code 1 when token threshold exceeded (can test by temporarily lowering threshold) + +--- + +## Phase 2: PR Checks Workflow + +### Changes Required + +- **`.github/workflows/pr-checks.yml`**: Create workflow adapted from PAW pattern with: + - Trigger: `pull_request` to `main` branch + - Path filtering: `src/**`, `agents/**`, `skills/**`, `cli/**`, `scripts/**`, `.github/workflows/pr-checks.yml` + - Job steps: + 1. Checkout code + 2. Setup Node.js 20 with npm cache + 3. `npm ci` (root dependencies) + 4. `npm run lint` (TypeScript linting) + 5. `npm run compile` (build extension) + 6. xvfb setup + `npm test` (VS Code extension tests) + 7. `cd cli && npm ci && npm test` (CLI tests) + 8. `npm run lint:agent:all` (agent/skill token linting) + 9. Summary message on success + +**Differences from PAW**: +- Add CLI test step (PAW doesn't run CLI tests in PR checks) +- Add `cli/**` to path filter + +### Success Criteria + +#### Automated Verification: +- [ ] Workflow YAML is valid (no syntax errors on push) +- [ ] All steps complete successfully on test PR + +#### Manual Verification: +- [ ] PR shows GitHub Actions check status +- [ ] Intentional lint error causes workflow failure +- [ ] Path filtering works (docs-only change skips workflow) + +--- + +## Phase 3: Extension Release Workflow + +### Changes Required + +- **`.github/workflows/release.yml`**: Create workflow adapted from PAW with Marketplace publishing added: + - Trigger: `push` tags matching `v*` + - Permissions: `contents: write` + - Job steps: + 1. Checkout code + 2. Setup Node.js 20 with npm cache + 3. `npm ci` + 4. `npm run compile` + 5. Extract version from tag (remove `v` prefix) + 6. Update package.json version via `npm version --no-git-tag-version` + 7. Determine pre-release status (odd minor = pre-release) + 8. `npm run package` (create VSIX) + 9. Verify VSIX exists with expected filename (`markdown-commenter-.vsix`) + 10. Check if GitHub Release exists (skip if yes) + 11. Create GitHub Release with VSIX attached (using `softprops/action-gh-release@v1`) + 12. Publish to VS Code Marketplace via `vsce publish` (with `continue-on-error: true`) + +**Marketplace publishing step** (new vs PAW): +```yaml +- name: Publish to VS Code Marketplace + continue-on-error: true # Don't fail workflow if Marketplace upload fails + run: npx vsce publish --pat ${{ secrets.VSCE_PAT }} + env: + VSCE_PAT: ${{ secrets.VSCE_PAT }} +``` + +**Inline documentation comments** to add: +- How to obtain VSCE_PAT (Azure DevOps PAT with Marketplace scope) +- Pre-release versioning convention explanation +- Why `continue-on-error` is used for Marketplace step + +### Success Criteria + +#### Automated Verification: +- [ ] Workflow YAML is valid +- [ ] Pushing test tag creates GitHub Release with VSIX attached + +#### Manual Verification: +- [ ] Pre-release tag (e.g., `v0.1.0`) creates pre-release +- [ ] Stable tag (e.g., `v0.2.0`) creates stable release +- [ ] Duplicate tag push skips release creation +- [ ] Marketplace failure logs warning but Release still created + +--- + +## Phase 4: CLI Publish Workflow + +### Changes Required + +- **`.github/workflows/publish-cli.yml`**: Create workflow adapted from PAW: + - Trigger: `push` tags matching `cli-v*` + - Permissions: `id-token: write` (OIDC), `contents: write` (releases) + - Default working directory: `cli` + - Job steps: + 1. Checkout code + 2. Setup Node.js 20 with registry-url for npm + 3. Extract version from tag (remove `cli-v` prefix) + 4. Determine pre-release status (check for `-alpha`, `-beta`, `-rc` suffix) + 5. Set package.json version via `npm version --no-git-tag-version` + 6. `npm ci` + 7. `npm run build` + 8. `npm test` + 9. `npm publish --access public --tag ` (OIDC auth) + 10. Check if GitHub Release exists (working-directory override to repo root) + 11. Create GitHub Release + +**Inline documentation comments** to add: +- npm OIDC setup requirements (package must be configured for provenance) +- Pre-release npm tag convention (`beta` vs `latest`) +- Why Node 20 (not 24 like PAW—consistency with extension workflow) + +### Success Criteria + +#### Automated Verification: +- [ ] Workflow YAML is valid +- [ ] Pushing test tag triggers workflow + +#### Manual Verification: +- [ ] npm package published with provenance +- [ ] GitHub Release created with npm package link +- [ ] Pre-release suffix correctly sets npm tag to `beta` + +--- + +## Phase 5: Documentation + +### Changes Required + +- **`.paw/work/github-actions-cicd/Docs.md`**: Technical reference covering: + - Overview of CI/CD infrastructure + - Workflow descriptions and triggers + - Token linting thresholds and usage + - Secrets configuration requirements + - Troubleshooting common issues + +- **`README.md`**: Add "Development" or "Contributing" section with: + - How to run tests locally + - How to lint agent files + - Release process overview (tag → workflow → artifacts) + +### Success Criteria + +- [ ] Docs.md follows `paw-docs-guidance` template +- [ ] README additions are concise and actionable +- [ ] No broken links or outdated information + +--- + +## References + +- Issue: none +- Spec: `.paw/work/github-actions-cicd/Spec.md` +- Research: `.paw/work/github-actions-cicd/CodeResearch.md` +- WorkShaping: `./WorkShaping-GHActions.md` +- PAW Workflows: `/home/erdemtuna/workspace/personal/phased-agent-workflow/.github/workflows/` From f5cd6c37154876cdfe15318c58be53d29d8326b8 Mon Sep 17 00:00:00 2001 From: Erdem Tuna Date: Thu, 26 Feb 2026 15:48:08 +0300 Subject: [PATCH 05/18] Address planning docs review findings - Note CLI tests step is placeholder (no test files exist) - Document npm OIDC prerequisites for publishConfig Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .paw/work/github-actions-cicd/ImplementationPlan.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.paw/work/github-actions-cicd/ImplementationPlan.md b/.paw/work/github-actions-cicd/ImplementationPlan.md index 969f52f..2a596e5 100644 --- a/.paw/work/github-actions-cicd/ImplementationPlan.md +++ b/.paw/work/github-actions-cicd/ImplementationPlan.md @@ -108,7 +108,7 @@ Implementing automated CI/CD infrastructure for markdown-commenter, consisting o 4. `npm run lint` (TypeScript linting) 5. `npm run compile` (build extension) 6. xvfb setup + `npm test` (VS Code extension tests) - 7. `cd cli && npm ci && npm test` (CLI tests) + 7. `cd cli && npm ci && npm test` (CLI tests — currently no test files exist, step passes vacuously) 8. `npm run lint:agent:all` (agent/skill token linting) 9. Summary message on success @@ -199,6 +199,11 @@ Implementing automated CI/CD infrastructure for markdown-commenter, consisting o 10. Check if GitHub Release exists (working-directory override to repo root) 11. Create GitHub Release +**Prerequisites for npm OIDC**: +- cli/package.json must have `"publishConfig": { "provenance": true }` for OIDC to work +- Package must be linked to GitHub repository in npm settings +- First publish may require manual setup on npmjs.com + **Inline documentation comments** to add: - npm OIDC setup requirements (package must be configured for provenance) - Pre-release npm tag convention (`beta` vs `latest`) From c5d9378344161ef3ffed75a001724745d5223b35 Mon Sep 17 00:00:00 2001 From: Erdem Tuna Date: Thu, 26 Feb 2026 15:50:25 +0300 Subject: [PATCH 06/18] Add token linting infrastructure (Phase 1) - Add scripts/lint-prompting.sh for agent/skill token validation - Add scripts/count-tokens.js using tiktoken for token counting - Add @dqbd/tiktoken devDependency - Add lint:agent, lint:agent:all, lint:skills npm scripts Thresholds: agents 5K warn/7K error, skills 8K warn/12K error Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- package-lock.json | 100 +---------------- package.json | 6 +- scripts/count-tokens.js | 52 +++++++++ scripts/lint-prompting.sh | 226 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 289 insertions(+), 95 deletions(-) create mode 100644 scripts/count-tokens.js create mode 100755 scripts/lint-prompting.sh diff --git a/package-lock.json b/package-lock.json index 74987f9..b276964 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,11 +9,11 @@ "version": "0.0.1-dev", "license": "MIT", "dependencies": { - "@fluentui/react-icons": "^2.0.319", "@fluentui/tokens": "^1.0.0-alpha.23", "@fluentui/web-components": "^3.0.0-beta.133" }, "devDependencies": { + "@dqbd/tiktoken": "^1.0.0", "@types/glob": "^8.1.0", "@types/mocha": "^10.0.6", "@types/node": "^20.11.0", @@ -199,19 +199,11 @@ "node": ">=16" } }, - "node_modules/@babel/runtime": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", - "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@emotion/hash": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", - "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "node_modules/@dqbd/tiktoken": { + "version": "1.0.22", + "resolved": "https://registry.npmjs.org/@dqbd/tiktoken/-/tiktoken-1.0.22.tgz", + "integrity": "sha512-RYhO8xeHkMNX5Ixqf4M1Ve3siCYJY/dI0yLnlX4M4oIEDOvjMIQ+E+3OUpAaZcWTaMtQJzGcDAghYfllpx3i/w==", + "dev": true, "license": "MIT" }, "node_modules/@eslint-community/eslint-utils": { @@ -301,19 +293,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@fluentui/react-icons": { - "version": "2.0.319", - "resolved": "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-2.0.319.tgz", - "integrity": "sha512-4yN0ovAxlOXL5jM3ULuYu6pAwvMWm1MjojDXn5tVKDkXQwlLpXCUFwf5Vgzp5jU6jJXrENj4v64MN6w7FJjotw==", - "license": "MIT", - "dependencies": { - "@griffel/react": "^1.0.0", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "react": ">=16.8.0 <20.0.0" - } - }, "node_modules/@fluentui/tokens": { "version": "1.0.0-alpha.23", "resolved": "https://registry.npmjs.org/@fluentui/tokens/-/tokens-1.0.0-alpha.23.tgz", @@ -350,42 +329,6 @@ "@swc/helpers": "^0.5.1" } }, - "node_modules/@griffel/core": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@griffel/core/-/core-1.19.2.tgz", - "integrity": "sha512-WkB/QQkjy9dE4vrNYGhQvRRUHFkYVOuaznVOMNTDT4pS9aTJ9XPrMTXXlkpcwaf0D3vNKoerj4zAwnU2lBzbOg==", - "license": "MIT", - "dependencies": { - "@emotion/hash": "^0.9.0", - "@griffel/style-types": "^1.3.0", - "csstype": "^3.1.3", - "rtl-css-js": "^1.16.1", - "stylis": "^4.2.0", - "tslib": "^2.1.0" - } - }, - "node_modules/@griffel/react": { - "version": "1.5.32", - "resolved": "https://registry.npmjs.org/@griffel/react/-/react-1.5.32.tgz", - "integrity": "sha512-jN3SmSwAUcWFUQuQ9jlhqZ5ELtKY21foaUR0q1mJtiAeSErVgjkpKJyMLRYpvaFGWrDql0Uz23nXUogXbsS2wQ==", - "license": "MIT", - "dependencies": { - "@griffel/core": "^1.19.2", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "react": ">=16.8.0 <20.0.0" - } - }, - "node_modules/@griffel/style-types": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@griffel/style-types/-/style-types-1.3.0.tgz", - "integrity": "sha512-bHwD3sUE84Xwv4dH011gOKe1jul77M1S6ZFN9Tnq8pvZ48UMdY//vtES6fv7GRS5wXYT4iqxQPBluAiYAfkpmw==", - "license": "MIT", - "dependencies": { - "csstype": "^3.1.3" - } - }, "node_modules/@humanwhocodes/config-array": { "version": "0.13.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", @@ -1645,12 +1588,6 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "license": "MIT" - }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -4301,16 +4238,6 @@ "node": ">=0.10.0" } }, - "node_modules/react": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", - "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/read": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", @@ -4425,15 +4352,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rtl-css-js": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz", - "integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.1.2" - } - }, "node_modules/run-applescript": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", @@ -4813,12 +4731,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/stylis": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", - "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", - "license": "MIT" - }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", diff --git a/package.json b/package.json index c75e8ff..46a2f17 100644 --- a/package.json +++ b/package.json @@ -119,9 +119,13 @@ "cli:build": "cd cli && npm run build", "cli:link": "cd cli && npm link", "cli:install-local": "npm run cli:build && node cli/bin/cli.js install copilot", - "cli:reinstall": "node cli/bin/cli.js uninstall; rm -rf ~/.paw/markdown-commenter; npm run cli:install-local" + "cli:reinstall": "node cli/bin/cli.js uninstall; rm -rf ~/.paw/markdown-commenter; npm run cli:install-local", + "lint:agent": "./scripts/lint-prompting.sh", + "lint:agent:all": "./scripts/lint-prompting.sh --all", + "lint:skills": "./scripts/lint-prompting.sh --skills" }, "devDependencies": { + "@dqbd/tiktoken": "^1.0.0", "@types/glob": "^8.1.0", "@types/mocha": "^10.0.6", "@types/node": "^20.11.0", diff --git a/scripts/count-tokens.js b/scripts/count-tokens.js new file mode 100644 index 0000000..e88aa8c --- /dev/null +++ b/scripts/count-tokens.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node +/** + * Count tokens in a file using tiktoken + * Usage: node scripts/count-tokens.js [model] + * + * This script counts tokens in markdown files (agents, skills) to ensure + * they don't exceed size limits that would degrade LLM performance. + */ + +const fs = require('fs'); +const path = require('path'); +const { encoding_for_model } = require('@dqbd/tiktoken'); + +// Get command line arguments +const args = process.argv.slice(2); + +if (args.length === 0) { + console.error('Usage: count-tokens.js [model]'); + process.exit(1); +} + +const filePath = args[0]; +const model = args[1] || 'gpt-4o-mini'; + +// Check if file exists +if (!fs.existsSync(filePath)) { + console.error(`Error: File not found: ${filePath}`); + process.exit(1); +} + +try { + // Read file content + const absolutePath = path.resolve(filePath); + const content = fs.readFileSync(absolutePath, 'utf-8'); + + // Get encoding for the model + const encoding = encoding_for_model(model); + + // Encode and count tokens + const tokens = encoding.encode(content); + const tokenCount = tokens.length; + + // Clean up + encoding.free(); + + // Output token count + console.log(tokenCount); + +} catch (error) { + console.error(`Error: ${error.message}`); + process.exit(1); +} diff --git a/scripts/lint-prompting.sh b/scripts/lint-prompting.sh new file mode 100755 index 0000000..e594310 --- /dev/null +++ b/scripts/lint-prompting.sh @@ -0,0 +1,226 @@ +#!/bin/bash +# Lint agent, skill, and custom agent files for token size +# Usage: ./scripts/lint-prompting.sh [file.agent.md | file/SKILL.md] +# ./scripts/lint-prompting.sh --skills # Lint only skills +# ./scripts/lint-prompting.sh --all # Lint both agents and skills +# If no file is provided, lints all agents in agents/ + +set -euo pipefail + +# Token thresholds for agents +WARN_THRESHOLD=5000 +ERROR_THRESHOLD=7000 + +# Token thresholds for skills (higher since loaded on-demand) +SKILL_WARN_THRESHOLD=8000 +SKILL_ERROR_THRESHOLD=12000 + +# Colors for output +RED='\033[0;31m' +YELLOW='\033[1;33m' +GREEN='\033[0;32m' +NC='\033[0m' # No Color + +# Check if Node.js is installed +if ! command -v node &> /dev/null; then + echo -e "${RED}ERROR: Node.js is not installed${NC}" + echo "Please install Node.js from https://nodejs.org/" + exit 1 +fi + +# Check if dependencies are installed +if [ ! -d "node_modules/@dqbd/tiktoken" ]; then + echo -e "${RED}ERROR: Dependencies are not installed${NC}" + echo "Run: npm install" + exit 1 +fi + +# Function to lint a single file +lint_file() { + local file="$1" + local filename=$(basename "$file") + + if [[ ! -f "$file" ]]; then + echo -e "${RED}ERROR: File not found: $file${NC}" + return 1 + fi + + # Count tokens using Node.js script + local token_count=$(node scripts/count-tokens.js "$file" 2>/dev/null || echo "0") + + # Use standard thresholds for all agents + local warn_threshold=$WARN_THRESHOLD + local error_threshold=$ERROR_THRESHOLD + + # Check thresholds + if (( token_count >= error_threshold )); then + echo -e "${RED}✗ ERROR${NC} $filename: ${RED}${token_count} tokens${NC} (exceeds ${error_threshold} token limit)" + return 1 + elif (( token_count >= warn_threshold )); then + echo -e "${YELLOW}⚠ WARN${NC} $filename: ${YELLOW}${token_count} tokens${NC} (exceeds ${warn_threshold} token warning threshold)" + return 0 + else + echo -e "${GREEN}✓ OK${NC} $filename: ${token_count} tokens" + return 0 + fi +} + +# Function to lint a skill file +lint_skill() { + local file="$1" + local skill_name=$(basename "$(dirname "$file")") + + if [[ ! -f "$file" ]]; then + echo -e "${RED}ERROR: File not found: $file${NC}" + return 1 + fi + + # Count tokens using Node.js script + local token_count=$(node scripts/count-tokens.js "$file" 2>/dev/null || echo "0") + + # Check thresholds (skills have higher limits since loaded on-demand) + if (( token_count >= SKILL_ERROR_THRESHOLD )); then + echo -e "${RED}✗ ERROR${NC} ${skill_name}/SKILL.md: ${RED}${token_count} tokens${NC} (exceeds ${SKILL_ERROR_THRESHOLD} token limit)" + return 1 + elif (( token_count >= SKILL_WARN_THRESHOLD )); then + echo -e "${YELLOW}⚠ WARN${NC} ${skill_name}/SKILL.md: ${YELLOW}${token_count} tokens${NC} (exceeds ${SKILL_WARN_THRESHOLD} token warning threshold)" + return 0 + else + echo -e "${GREEN}✓ OK${NC} ${skill_name}/SKILL.md: ${token_count} tokens" + return 0 + fi +} + +# Function to lint all agents +lint_all_agents() { + local exit_code=0 + local agent_dir="agents" + + if [[ ! -d "$agent_dir" ]]; then + echo -e "${RED}ERROR: Directory not found: $agent_dir${NC}" + return 1 + fi + + local files=("$agent_dir"/*.agent.md) + if [[ ! -e "${files[0]}" ]]; then + echo -e "${YELLOW}WARNING: No agent files found in $agent_dir${NC}" + return 0 + fi + + for file in "${files[@]}"; do + if ! lint_file "$file"; then + exit_code=1 + fi + done + + return $exit_code +} + +# Function to lint all skills +lint_all_skills() { + local exit_code=0 + local skill_dir="skills" + + if [[ ! -d "$skill_dir" ]]; then + echo -e "${YELLOW}WARNING: Directory not found: $skill_dir${NC}" + return 0 + fi + + # Find all SKILL.md files in skills subdirectories + local skill_files=() + while IFS= read -r -d '' file; do + skill_files+=("$file") + done < <(find "$skill_dir" -name "SKILL.md" -type f -print0 2>/dev/null) + + if [[ ${#skill_files[@]} -eq 0 ]]; then + echo -e "${YELLOW}WARNING: No skill files found in $skill_dir${NC}" + return 0 + fi + + for file in "${skill_files[@]}"; do + if ! lint_skill "$file"; then + exit_code=1 + fi + done + + return $exit_code +} + +# Main logic +main() { + local exit_code=0 + local lint_agents=false + local lint_skills=false + local files_to_lint=() + + # Parse arguments + if [[ $# -eq 0 ]]; then + # No arguments: lint all agents (backward compatible) + lint_agents=true + else + for arg in "$@"; do + case "$arg" in + --skills) + lint_skills=true + ;; + --all) + lint_agents=true + lint_skills=true + ;; + *) + files_to_lint+=("$arg") + ;; + esac + done + fi + + # Lint specific files if provided + if [[ ${#files_to_lint[@]} -gt 0 ]]; then + for file in "${files_to_lint[@]}"; do + # Determine if this is a skill or agent file (only SKILL.md files use skill thresholds) + if [[ "$file" == */SKILL.md ]]; then + if ! lint_skill "$file"; then + exit_code=1 + fi + else + if ! lint_file "$file"; then + exit_code=1 + fi + fi + done + else + # Lint all agents if requested + if [[ "$lint_agents" == true ]]; then + echo "Linting all agent files in agents/" + echo "" + + if ! lint_all_agents; then + exit_code=1 + fi + fi + + # Lint all skills if requested + if [[ "$lint_skills" == true ]]; then + if [[ "$lint_agents" == true ]]; then + echo "" + fi + echo "Linting all skill files in skills/" + echo "" + + if ! lint_all_skills; then + exit_code=1 + fi + fi + fi + + echo "" + if [[ $exit_code -eq 0 ]]; then + echo -e "${GREEN}All checks passed!${NC}" + else + echo -e "${RED}Some checks failed. Please reduce token count in agent/skill files.${NC}" + fi + + exit $exit_code +} + +main "$@" From e33153a2dd6787bdcbcf333b47cf444a4d4be30d Mon Sep 17 00:00:00 2001 From: Erdem Tuna Date: Thu, 26 Feb 2026 15:51:01 +0300 Subject: [PATCH 07/18] Add PR checks workflow (Phase 2) Automated quality gates on pull requests: - TypeScript linting - Extension compilation - VS Code extension tests (with xvfb) - CLI tests (placeholder until tests added) - Agent/skill token linting Triggers on PRs to main with path filtering for relevant files. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/pr-checks.yml | 78 +++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 .github/workflows/pr-checks.yml diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml new file mode 100644 index 0000000..5653382 --- /dev/null +++ b/.github/workflows/pr-checks.yml @@ -0,0 +1,78 @@ +# Runs automated quality checks on pull requests before merging. +# Validates code quality by running linting, compilation, tests, and agent file checks. +# Serves as a quality gate to prevent broken code or oversized agent files from being merged. +# +# Path filtering ensures workflow only runs when relevant files change. +# Uses xvfb for headless VS Code extension testing. +name: PR Checks + +on: + pull_request: + branches: + - main + paths: + - 'src/**' + - 'agents/**' + - 'skills/**' + - 'cli/**' + - 'scripts/**' + - '.github/workflows/pr-checks.yml' + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: package-lock.json + + - name: Install dependencies + run: npm ci + + - name: Lint code + run: npm run lint + + - name: Compile extension + run: npm run compile + + - name: Run extension unit tests + run: | + # Install xvfb for headless VS Code testing + # xvfb provides a virtual display server, required for VS Code's Electron environment + sudo apt-get update + sudo apt-get install -y xvfb + + # Run tests with virtual display + # xvfb-run -a automatically finds an available display number + xvfb-run -a npm test + env: + # Prevent VS Code from showing UI during tests + DISPLAY: ':99.0' + + - name: Install CLI dependencies + run: cd cli && npm ci + + - name: Run CLI tests + # Note: Currently no test files exist in cli/lib/*.test.js + # This step will pass vacuously until CLI tests are added + run: cd cli && npm test + + - name: Lint agent files + run: npm run lint:agent:all + + - name: PR checks summary + if: success() + run: | + echo "✅ All PR checks passed!" + echo "- Code linting: PASSED" + echo "- Compilation: PASSED" + echo "- Extension tests: PASSED" + echo "- CLI tests: PASSED" + echo "- Agent linting: PASSED" From 4a3640ffd40698494b455888a29cc68a368f0a75 Mon Sep 17 00:00:00 2001 From: Erdem Tuna Date: Thu, 26 Feb 2026 15:51:40 +0300 Subject: [PATCH 08/18] Add extension release workflow (Phase 3) Tag-triggered (v*) release workflow: - Extracts version from git tag (source of truth) - Detects pre-release via odd/even minor version - Packages VSIX with correct filename - Creates GitHub Release with VSIX attached - Publishes to VS Code Marketplace (with graceful fallback) Requires VSCE_PAT secret for Marketplace publishing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/release.yml | 155 ++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..e2cf731 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,155 @@ +# Automatically builds and releases the VS Code extension when version tags are pushed. +# Triggers on tags matching v* pattern (e.g., v0.2.0, v1.0.0). +# Builds extension, packages VSIX, creates GitHub Release, and publishes to VS Code Marketplace. +# +# Pre-release convention: odd minor versions (0.1.x, 0.3.x) are pre-releases, +# even minor versions (0.2.x, 0.4.x) are stable releases. +# +# SECRETS REQUIRED: +# - VSCE_PAT: Personal Access Token for VS Code Marketplace publishing +# To create: https://code.visualstudio.com/api/working-with-extensions/publishing-extension#get-a-personal-access-token +# Required scopes: Marketplace (Manage) +# Add to repository: Settings → Secrets and variables → Actions → New repository secret +# +# The workflow will create a GitHub Release even if Marketplace upload fails, +# ensuring users can always download the VSIX manually. +name: Release VSIX + +on: + push: + tags: + - 'v*' + +jobs: + release: + runs-on: ubuntu-latest + + permissions: + contents: write # Required to create releases and upload assets + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: 'package-lock.json' + + - name: Install dependencies + run: npm ci + + - name: Compile extension + run: npm run compile + + - name: Extract version from tag + id: version + run: | + # Extract semantic version from tag (e.g., v0.2.0 -> 0.2.0) + # This version becomes the source of truth for the release + TAG_NAME="${{ github.ref_name }}" + VERSION="${TAG_NAME#v}" # Remove 'v' prefix using bash parameter expansion + echo "version=${VERSION}" >> $GITHUB_OUTPUT + echo "Extracted version: ${VERSION}" + + - name: Update package.json version to match tag + run: | + # Set package.json version to match the git tag + # This eliminates the need for manual version updates before tagging + # Local development stays on "0.0.1-dev" so every activation reinstalls agents + # The release workflow overwrites that dev suffix with the semver tag + TAG_VERSION="${{ steps.version.outputs.version }}" + npm version ${TAG_VERSION} --no-git-tag-version --allow-same-version + echo "Updated package.json to version: ${TAG_VERSION}" + + - name: Determine pre-release status + id: prerelease + run: | + # VS Code extension convention: odd minor versions (0.1.x, 0.3.x) are pre-releases, + # even minor versions (0.2.x, 0.4.x) are stable releases + # This follows the VS Code pre-release extension best practices + VERSION="${{ steps.version.outputs.version }}" + # Extract minor version (second number in semver, e.g., 0.2.0 -> 2) + MINOR=$(echo $VERSION | cut -d. -f2) + # Check if minor version is odd (pre-release) or even (stable) + if [ $((MINOR % 2)) -eq 1 ]; then + echo "is_prerelease=true" >> $GITHUB_OUTPUT + echo "This is a pre-release version (minor=$MINOR is odd)" + else + echo "is_prerelease=false" >> $GITHUB_OUTPUT + echo "This is a stable release version (minor=$MINOR is even)" + fi + + - name: Package VSIX + run: npm run package + + - name: Verify VSIX created + id: vsix + run: | + # Verify the VSIX file was created with the expected filename format + # The package name comes from package.json: markdown-commenter-.vsix + VSIX_FILE="markdown-commenter-${{ steps.version.outputs.version }}.vsix" + if [ ! -f "$VSIX_FILE" ]; then + echo "Error: Expected VSIX file not found: $VSIX_FILE" + exit 1 + fi + # Export both the full path (for release upload) and filename (for display) + echo "vsix_path=${VSIX_FILE}" >> $GITHUB_OUTPUT + echo "vsix_name=${VSIX_FILE}" >> $GITHUB_OUTPUT + echo "VSIX created successfully: $VSIX_FILE" + + - name: Check if release exists + id: check_release + run: | + RELEASE_EXISTS=$(gh release view "${{ github.ref_name }}" --json id 2>/dev/null || echo "") + if [ -n "$RELEASE_EXISTS" ]; then + echo "exists=true" >> $GITHUB_OUTPUT + else + echo "exists=false" >> $GITHUB_OUTPUT + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Create GitHub Release + if: steps.check_release.outputs.exists == 'false' + uses: softprops/action-gh-release@v1 + with: + name: ${{ github.ref_name }} + tag_name: ${{ github.ref_name }} + body: | + Release notes will be added by the release preparation process. + + ## Installation + + Download the `.vsix` file and install via: + ```bash + code --install-extension ${{ steps.vsix.outputs.vsix_name }} + ``` + + Or install from VS Code Marketplace (if published successfully). + files: ${{ steps.vsix.outputs.vsix_path }} + prerelease: ${{ steps.prerelease.outputs.is_prerelease }} + fail_on_unmatched_files: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Publish to VS Code Marketplace + # continue-on-error ensures GitHub Release is created even if Marketplace fails + # This provides resilience: users can always download VSIX from GitHub + continue-on-error: true + run: | + echo "Publishing to VS Code Marketplace..." + npx vsce publish --pat ${{ secrets.VSCE_PAT }} + env: + VSCE_PAT: ${{ secrets.VSCE_PAT }} + + - name: Marketplace publish status + if: always() + run: | + if [ "${{ steps.marketplace.outcome }}" == "failure" ]; then + echo "⚠️ VS Code Marketplace publish failed" + echo "GitHub Release was still created with VSIX attached" + echo "You can manually publish later with: npx vsce publish" + fi From c939693920c76d2a2a6e16743c5c11a66cbc4c2b Mon Sep 17 00:00:00 2001 From: Erdem Tuna Date: Thu, 26 Feb 2026 15:52:11 +0300 Subject: [PATCH 09/18] Add CLI publish workflow (Phase 4) Tag-triggered (cli-v*) npm publish workflow: - Extracts version from git tag - Detects pre-release via semver suffix (-alpha, -beta, -rc) - Builds and tests CLI package - Publishes to npm with appropriate tag (latest/beta) - Creates GitHub Release with installation instructions Includes detailed documentation for npm OIDC setup prerequisites. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/publish-cli.yml | 126 ++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 .github/workflows/publish-cli.yml diff --git a/.github/workflows/publish-cli.yml b/.github/workflows/publish-cli.yml new file mode 100644 index 0000000..714a07e --- /dev/null +++ b/.github/workflows/publish-cli.yml @@ -0,0 +1,126 @@ +# Publishes the CLI package to npm when CLI version tags are pushed. +# Triggers on tags matching cli-v* pattern (e.g., cli-v1.0.0, cli-v0.2.0-beta). +# Builds, tests, publishes to npm with provenance, and creates GitHub Release. +# +# Pre-release convention: versions with -alpha, -beta, or -rc suffix are pre-releases +# and are published to npm with the 'beta' tag instead of 'latest'. +# +# AUTHENTICATION: +# Uses npm OIDC (OpenID Connect) for secure publishing without storing tokens. +# This requires the package to be configured for provenance on npmjs.com. +# +# PREREQUISITES (one-time setup): +# 1. Package must be published manually first time with: npm publish --access public +# 2. On npmjs.com, link the package to the GitHub repository +# 3. Enable "Require two-factor authentication or an automation token or granular access token" +# 4. In cli/package.json, add: "publishConfig": { "provenance": true } +# +# No NPM_TOKEN secret is needed - OIDC handles authentication via id-token permission. +name: Publish CLI + +on: + push: + tags: + - 'cli-v*' + +permissions: + id-token: write # Required for OIDC trusted publishing to npm + contents: write # Required to create GitHub releases + +jobs: + publish: + runs-on: ubuntu-latest + defaults: + run: + working-directory: cli + + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + # Using Node 20 for consistency with extension workflow + # PAW uses Node 24, but 20 is sufficient and more stable + node-version: '20' + registry-url: 'https://registry.npmjs.org' + + - name: Extract version from tag + id: version + run: | + TAG_NAME="${{ github.ref_name }}" + VERSION="${TAG_NAME#cli-v}" # Remove 'cli-v' prefix + echo "version=${VERSION}" >> $GITHUB_OUTPUT + echo "Extracted version: ${VERSION}" + + - name: Determine pre-release status + id: prerelease + run: | + VERSION="${{ steps.version.outputs.version }}" + # Check for pre-release suffixes: -alpha, -beta, -rc + # Examples: 1.0.0-beta, 0.2.0-alpha.1, 1.0.0-rc.1 + if [[ "$VERSION" =~ -(alpha|beta|rc) ]]; then + echo "is_prerelease=true" >> $GITHUB_OUTPUT + echo "npm_tag=beta" >> $GITHUB_OUTPUT + echo "This is a pre-release version" + else + echo "is_prerelease=false" >> $GITHUB_OUTPUT + echo "npm_tag=latest" >> $GITHUB_OUTPUT + echo "This is a stable release version" + fi + + - name: Set version from tag + run: npm version ${{ steps.version.outputs.version }} --no-git-tag-version + + - name: Install dependencies + run: npm ci + + - name: Build distribution + run: npm run build + + - name: Run tests + run: npm test + + - name: Publish to npm + run: npm publish --access public --tag ${{ steps.prerelease.outputs.npm_tag }} + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Check if release exists + id: check_release + working-directory: ${{ github.workspace }} + run: | + RELEASE_EXISTS=$(gh release view "${{ github.ref_name }}" --json id 2>/dev/null || echo "") + if [ -n "$RELEASE_EXISTS" ]; then + echo "exists=true" >> $GITHUB_OUTPUT + else + echo "exists=false" >> $GITHUB_OUTPUT + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Create GitHub Release + if: steps.check_release.outputs.exists == 'false' + uses: softprops/action-gh-release@v1 + with: + name: CLI ${{ steps.version.outputs.version }} + tag_name: ${{ github.ref_name }} + body: | + Published to npm: `@erdem-tuna/markdown-commenter@${{ steps.version.outputs.version }}` + + ## Installation + + ```bash + npx @erdem-tuna/markdown-commenter install copilot + ``` + + Or install globally: + ```bash + npm install -g @erdem-tuna/markdown-commenter + markdown-commenter install copilot + ``` + + Release notes will be added by the release preparation process. + prerelease: ${{ steps.prerelease.outputs.is_prerelease }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 5a6636c6f7a325f7050250019b2bcb26db8cadb0 Mon Sep 17 00:00:00 2001 From: Erdem Tuna Date: Thu, 26 Feb 2026 15:53:21 +0300 Subject: [PATCH 10/18] Add documentation for GitHub Actions CI/CD (Phase 5) - Create Docs.md with comprehensive technical reference - Update README Development section with linting and release process Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .paw/work/github-actions-cicd/Docs.md | 169 ++++++++++++++++++++++++++ README.md | 16 ++- 2 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 .paw/work/github-actions-cicd/Docs.md diff --git a/.paw/work/github-actions-cicd/Docs.md b/.paw/work/github-actions-cicd/Docs.md new file mode 100644 index 0000000..79f3bae --- /dev/null +++ b/.paw/work/github-actions-cicd/Docs.md @@ -0,0 +1,169 @@ +# GitHub Actions CI/CD + +## Overview + +This implementation adds automated CI/CD infrastructure to the markdown-commenter project, consisting of three GitHub Actions workflows and supporting token linting scripts. The workflows automate quality gates on pull requests and streamline the release process for both the VS Code extension and Copilot CLI package. + +The automation eliminates manual release steps, ensures consistent quality validation, and follows patterns established by the PAW (Phased Agent Workflow) project. Maintainers can now release new versions by simply pushing a git tag, while contributors receive immediate feedback on code quality through PR checks. + +## Architecture and Design + +### High-Level Architecture + +``` +GitHub Repository Events + │ + ├── PR to main ──────────► PR Checks Workflow + │ ├── lint + │ ├── compile + │ ├── extension tests + │ ├── CLI tests + │ └── agent linting + │ + ├── Push v* tag ─────────► Extension Release Workflow + │ ├── build VSIX + │ ├── GitHub Release + │ └── VS Code Marketplace + │ + └── Push cli-v* tag ─────► CLI Publish Workflow + ├── build & test + ├── npm publish + └── GitHub Release +``` + +### Design Decisions + +**Tag-triggered releases**: Releases are triggered by git tags rather than PR merges. This provides explicit control over when releases happen and separates versioning decisions from code changes. + +**Separate tag patterns**: Extension uses `v*` tags (e.g., `v1.0.0`), CLI uses `cli-v*` tags (e.g., `cli-v1.0.0`). This allows independent versioning of the two packages. + +**Tag as version source of truth**: Package.json versions are updated during the workflow from the git tag. Local development uses `0.0.1-dev`, ensuring agents are reinstalled on every activation during development. + +**Graceful Marketplace failure**: The extension release workflow uses `continue-on-error` for Marketplace publishing. If it fails, the GitHub Release is still created with the VSIX attached, ensuring users can always access the extension. + +**OIDC for npm**: CLI publishing uses npm's OIDC trusted publishing instead of access tokens. This is more secure and doesn't require storing npm tokens in repository secrets. + +### Integration Points + +**Token linting**: Uses `@dqbd/tiktoken` to count tokens in agent/skill files. Thresholds (5K/7K for agents, 8K/12K for skills) prevent oversized prompts that degrade LLM performance. + +**VS Code test infrastructure**: Uses `xvfb` to provide a virtual display for headless VS Code testing in GitHub Actions. + +## User Guide + +### Prerequisites + +**For PR checks** (automatic): +- No setup required — workflow runs automatically on PRs + +**For extension release**: +- `VSCE_PAT` secret: Personal Access Token for VS Code Marketplace + - Create at: https://dev.azure.com (Azure DevOps) + - Required scopes: Marketplace (Manage) + - Add to: Repository Settings → Secrets and variables → Actions + +**For CLI publish**: +- First-time manual publish to establish npm package +- Link package to GitHub repository on npmjs.com +- Add to cli/package.json: `"publishConfig": { "provenance": true }` + +### Basic Usage + +**Run local linting**: +```bash +npm run lint:agent # Lint agent files only +npm run lint:skills # Lint skill files only +npm run lint:agent:all # Lint both agents and skills +``` + +**Release a new extension version**: +```bash +git tag v0.2.0 +git push origin v0.2.0 +``` + +**Release a new CLI version**: +```bash +git tag cli-v0.2.0 +git push origin cli-v0.2.0 +``` + +### Advanced Usage + +**Pre-release versions**: +- Extension: Odd minor versions (v0.1.0, v0.3.0) are marked as pre-release +- CLI: Versions with `-alpha`, `-beta`, or `-rc` suffix (cli-v1.0.0-beta) + +**Re-running failed releases**: +If a release workflow fails partway through, it's safe to re-run: +- GitHub Release creation checks if release exists and skips if already present +- Marketplace/npm publish are idempotent for the same version + +## API Reference + +### Token Linting Scripts + +**lint-prompting.sh**: +```bash +./scripts/lint-prompting.sh # Lint all agents +./scripts/lint-prompting.sh --skills # Lint all skills +./scripts/lint-prompting.sh --all # Lint both +./scripts/lint-prompting.sh path/to/file # Lint specific file +``` + +**count-tokens.js**: +```bash +node scripts/count-tokens.js [model] +# model defaults to 'gpt-4o-mini' +``` + +### Configuration Options + +**Token thresholds** (in lint-prompting.sh): +| Type | Warning | Error | +|------|---------|-------| +| Agent | 5,000 | 7,000 | +| Skill | 8,000 | 12,000 | + +## Testing + +### How to Test + +**PR Checks**: +1. Create a branch with a code change +2. Open a PR to main +3. Verify workflow triggers and all checks pass/fail as expected + +**Token Linting**: +1. Run `npm run lint:agent:all` locally +2. Verify it reports correct token counts for agents/skills +3. Temporarily lower thresholds to verify failure behavior + +**Release Workflows** (dry run): +1. Push a pre-release tag (e.g., `v0.0.2` or `cli-v0.0.2-alpha`) +2. Verify GitHub Release is created +3. Check workflow logs for any warnings + +### Edge Cases + +| Scenario | Expected Behavior | +|----------|-------------------| +| Duplicate tag push | Release creation skipped (idempotent) | +| Marketplace PAT expired | Warning logged, GitHub Release still created | +| Agent exceeds 7K tokens | PR checks fail with clear error | +| npm OIDC not configured | CLI publish fails with auth error | +| No CLI test files | npm test passes (no tests = success) | + +## Limitations and Future Work + +**Current limitations**: +- No automatic changelog generation — release notes added manually +- No matrix testing across Node versions (only Node 20) +- No Windows/macOS runner support +- CLI tests don't exist yet (step passes vacuously) + +**Not implemented** (explicit scope exclusions): +- MkDocs documentation workflow +- Slack/Discord notifications +- Code coverage reporting +- Security scanning (CodeQL, Dependabot) diff --git a/README.md b/README.md index 03b825e..7e88fdb 100644 --- a/README.md +++ b/README.md @@ -135,7 +135,14 @@ npm run compile ### Run tests ```bash -npm test +npm test # Extension tests +cd cli && npm test # CLI tests +``` + +### Lint agent files + +```bash +npm run lint:agent:all # Lint agents and skills for token limits ``` ### Package extension @@ -144,6 +151,13 @@ npm test npm run package ``` +### Release process + +Releases are automated via GitHub Actions: + +- **Extension**: Push a `v*` tag (e.g., `git tag v1.0.0 && git push origin v1.0.0`) +- **CLI**: Push a `cli-v*` tag (e.g., `git tag cli-v1.0.0 && git push origin cli-v1.0.0`) + ## Contributing Contributions welcome! Please: From 8c37fd461415c4ea43b53040a5439a2152673b2f Mon Sep 17 00:00:00 2001 From: Erdem Tuna Date: Thu, 26 Feb 2026 15:54:03 +0300 Subject: [PATCH 11/18] Mark all implementation phases complete Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .paw/work/github-actions-cicd/ImplementationPlan.md | 10 +++++----- .paw/work/github-actions-cicd/WorkflowContext.md | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.paw/work/github-actions-cicd/ImplementationPlan.md b/.paw/work/github-actions-cicd/ImplementationPlan.md index 2a596e5..054d52e 100644 --- a/.paw/work/github-actions-cicd/ImplementationPlan.md +++ b/.paw/work/github-actions-cicd/ImplementationPlan.md @@ -49,11 +49,11 @@ Implementing automated CI/CD infrastructure for markdown-commenter, consisting o ## Phase Status -- [ ] **Phase 1: Token Linting Infrastructure** - Add scripts and dependencies for agent/skill token validation -- [ ] **Phase 2: PR Checks Workflow** - Automated quality gates on pull requests -- [ ] **Phase 3: Extension Release Workflow** - Tag-triggered VSIX build, GitHub Release, and Marketplace publishing -- [ ] **Phase 4: CLI Publish Workflow** - Tag-triggered npm publish with OIDC -- [ ] **Phase 5: Documentation** - Technical reference and README updates +- [x] **Phase 1: Token Linting Infrastructure** - Add scripts and dependencies for agent/skill token validation +- [x] **Phase 2: PR Checks Workflow** - Automated quality gates on pull requests +- [x] **Phase 3: Extension Release Workflow** - Tag-triggered VSIX build, GitHub Release, and Marketplace publishing +- [x] **Phase 4: CLI Publish Workflow** - Tag-triggered npm publish with OIDC +- [x] **Phase 5: Documentation** - Technical reference and README updates ## Phase Candidates diff --git a/.paw/work/github-actions-cicd/WorkflowContext.md b/.paw/work/github-actions-cicd/WorkflowContext.md index 0ba20b4..db02061 100644 --- a/.paw/work/github-actions-cicd/WorkflowContext.md +++ b/.paw/work/github-actions-cicd/WorkflowContext.md @@ -31,10 +31,10 @@ Additional Inputs: WorkShaping-GHActions.md ## Stage Progress -- [ ] Specification -- [ ] Code Research -- [ ] Planning -- [ ] Planning Docs Review -- [ ] Implementation +- [x] Specification +- [x] Code Research +- [x] Planning +- [x] Planning Docs Review +- [x] Implementation - [ ] Final Review - [ ] Final PR From e7bd0c0799bd67a91f72965f3abc9db3e1d92495 Mon Sep 17 00:00:00 2001 From: Erdem Tuna Date: Thu, 26 Feb 2026 15:55:23 +0300 Subject: [PATCH 12/18] Address final review findings - Clarify NPM_TOKEN authentication in CLI publish workflow - Add id to Marketplace publish step for status check Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/publish-cli.yml | 17 ++++++++++------- .github/workflows/release.yml | 1 + 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/publish-cli.yml b/.github/workflows/publish-cli.yml index 714a07e..92352e0 100644 --- a/.github/workflows/publish-cli.yml +++ b/.github/workflows/publish-cli.yml @@ -6,16 +6,19 @@ # and are published to npm with the 'beta' tag instead of 'latest'. # # AUTHENTICATION: -# Uses npm OIDC (OpenID Connect) for secure publishing without storing tokens. -# This requires the package to be configured for provenance on npmjs.com. +# This workflow uses NPM_TOKEN secret for npm authentication. +# To set up: +# 1. Generate an npm access token at https://www.npmjs.com/settings/tokens +# 2. Add as repository secret: Settings → Secrets → Actions → NPM_TOKEN # -# PREREQUISITES (one-time setup): -# 1. Package must be published manually first time with: npm publish --access public +# For enhanced security with provenance, you can also configure npm OIDC: +# 1. In cli/package.json, add: "publishConfig": { "provenance": true } # 2. On npmjs.com, link the package to the GitHub repository -# 3. Enable "Require two-factor authentication or an automation token or granular access token" -# 4. In cli/package.json, add: "publishConfig": { "provenance": true } +# 3. The id-token permission below enables OIDC attestation # -# No NPM_TOKEN secret is needed - OIDC handles authentication via id-token permission. +# PREREQUISITES (first-time setup): +# 1. Create NPM_TOKEN secret in repository settings +# 2. First publish may need to be manual: cd cli && npm publish --access public name: Publish CLI on: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e2cf731..6b2589f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -136,6 +136,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Publish to VS Code Marketplace + id: marketplace # continue-on-error ensures GitHub Release is created even if Marketplace fails # This provides resilience: users can always download VSIX from GitHub continue-on-error: true From 6d9b18db72fe690f8f53934b9eb4cf21e3b89be4 Mon Sep 17 00:00:00 2001 From: Erdem Tuna Date: Thu, 26 Feb 2026 15:56:51 +0300 Subject: [PATCH 13/18] Stop tracking PAW artifacts for github-actions-cicd Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .paw/work/github-actions-cicd/CodeResearch.md | 375 ------------------ .paw/work/github-actions-cicd/Docs.md | 169 -------- .../github-actions-cicd/ImplementationPlan.md | 255 ------------ .paw/work/github-actions-cicd/Spec.md | 180 --------- .../github-actions-cicd/WorkflowContext.md | 40 -- 5 files changed, 1019 deletions(-) delete mode 100644 .paw/work/github-actions-cicd/CodeResearch.md delete mode 100644 .paw/work/github-actions-cicd/Docs.md delete mode 100644 .paw/work/github-actions-cicd/ImplementationPlan.md delete mode 100644 .paw/work/github-actions-cicd/Spec.md delete mode 100644 .paw/work/github-actions-cicd/WorkflowContext.md diff --git a/.paw/work/github-actions-cicd/CodeResearch.md b/.paw/work/github-actions-cicd/CodeResearch.md deleted file mode 100644 index 0d0c243..0000000 --- a/.paw/work/github-actions-cicd/CodeResearch.md +++ /dev/null @@ -1,375 +0,0 @@ ---- -date: 2026-02-26T12:45:00+00:00 -git_commit: c14ac5d -branch: feature/github-actions-cicd -repository: markdown-commenter -topic: "GitHub Actions CI/CD Implementation Patterns" -tags: [research, codebase, github-actions, ci-cd, workflows] -status: complete -last_updated: 2026-02-26 ---- - -# Research: GitHub Actions CI/CD Implementation Patterns - -## Research Question - -What are the implementation patterns, file structures, and technical details needed to create GitHub Actions workflows for markdown-commenter, based on PAW's existing workflows? - -## Summary - -PAW provides mature GitHub Actions workflows that can be directly adapted for markdown-commenter. The three workflows (PR checks, extension release, CLI publish) follow consistent patterns: tag-triggered releases, version extraction from tags, pre-release detection, and idempotent release creation. The token linting infrastructure requires `@dqbd/tiktoken` dependency and two scripts. markdown-commenter already has the necessary npm scripts for lint/compile/test but lacks agent linting scripts. - -## Documentation System - -- **Framework**: markdown (README.md only) -- **Docs Directory**: N/A (no dedicated docs folder) -- **Navigation Config**: N/A -- **Style Conventions**: Standard GitHub README with badges, features list, installation instructions -- **Build Command**: N/A -- **Standard Files**: README.md (root), CHANGELOG.md (root), LICENSE (root) - -## Verification Commands - -- **Test Command**: `npm test` (extension), `cd cli && npm test` (CLI - currently no tests) -- **Lint Command**: `npm run lint` (eslint on src/) -- **Build Command**: `npm run compile` (TypeScript compilation) -- **Type Check**: Implicit via `npm run compile` (tsc) -- **Package Command**: `npm run package` (vsce package) - -## Detailed Findings - -### PAW PR Checks Workflow - -**Location**: `/home/erdemtuna/workspace/personal/phased-agent-workflow/.github/workflows/pr-checks.yml` - -**Trigger Configuration** (lines 6-16): -```yaml -on: - pull_request: - branches: - - main - - 'feature/**' - paths: - - 'src/**' - - 'agents/**' - - 'skills/**' - - 'scripts/**' - - '.github/workflows/pr-checks.yml' -``` - -**Job Structure** (lines 18-66): -- Single job named `test` on `ubuntu-latest` -- Node.js 20 with npm caching via `cache-dependency-path: package-lock.json` -- Steps: checkout → setup-node → npm ci → lint → compile → xvfb test → agent lint → summary - -**xvfb Pattern** (lines 43-54): -```bash -sudo apt-get update -sudo apt-get install -y xvfb -xvfb-run -a npm test -``` -Environment variable `DISPLAY: ':99.0'` set for headless testing. - -**Agent Linting** (line 57): -```bash -npm run lint:agent:all -``` - -### PAW Extension Release Workflow - -**Location**: `/home/erdemtuna/workspace/personal/phased-agent-workflow/.github/workflows/release.yml` - -**Trigger** (lines 6-9): -```yaml -on: - push: - tags: - - 'v*' -``` - -**Permissions** (lines 15-16): -```yaml -permissions: - contents: write # Required to create releases and upload assets -``` - -**Version Extraction Pattern** (lines 35-43): -```bash -TAG_NAME="${{ github.ref_name }}" -VERSION="${TAG_NAME#v}" # Remove 'v' prefix -echo "version=${VERSION}" >> $GITHUB_OUTPUT -``` - -**Package.json Version Update** (lines 45-53): -```bash -npm version ${TAG_VERSION} --no-git-tag-version --allow-same-version -``` -This makes the git tag the source of truth for versioning. - -**Pre-release Detection** (lines 55-71): -```bash -MINOR=$(echo $VERSION | cut -d. -f2) -if [ $((MINOR % 2)) -eq 1 ]; then - echo "is_prerelease=true" >> $GITHUB_OUTPUT -else - echo "is_prerelease=false" >> $GITHUB_OUTPUT -fi -``` -Odd minor versions (0.1.x, 0.3.x) are pre-releases. - -**VSIX Verification** (lines 78-89): -```bash -VSIX_FILE="paw-workflow-${{ steps.version.outputs.version }}.vsix" -if [ ! -f "$VSIX_FILE" ]; then - exit 1 -fi -``` -Package name from package.json determines VSIX filename. - -**Release Existence Check** (lines 91-101): -```bash -RELEASE_EXISTS=$(gh release view "${{ github.ref_name }}" --json id 2>/dev/null || echo "") -``` -Uses GitHub CLI to check; skips creation if exists (idempotent). - -**Release Creation** (lines 103-115): -Uses `softprops/action-gh-release@v1` action with: -- `files:` for VSIX attachment -- `prerelease:` from detection step -- `fail_on_unmatched_files: true` - -### PAW CLI Publish Workflow - -**Location**: `/home/erdemtuna/workspace/personal/phased-agent-workflow/.github/workflows/publish-cli.yml` - -**Trigger** (lines 3-6): -```yaml -on: - push: - tags: - - 'cli-v*' -``` - -**Permissions** (lines 8-10): -```yaml -permissions: - id-token: write # Required for OIDC trusted publishing - contents: write # Required to create GitHub releases -``` - -**Working Directory Default** (lines 15-17): -```yaml -defaults: - run: - working-directory: cli -``` - -**Node.js Setup with Registry** (lines 22-26): -```yaml -uses: actions/setup-node@v4 -with: - node-version: '24' - registry-url: 'https://registry.npmjs.org' -``` -Note: Uses Node 24 (newer than extension workflow). - -**CLI Version Extraction** (lines 28-34): -```bash -VERSION="${TAG_NAME#cli-v}" # Remove 'cli-v' prefix -``` - -**CLI Pre-release Detection** (lines 36-49): -```bash -if [[ "$VERSION" =~ -(alpha|beta|rc) ]]; then - echo "npm_tag=beta" >> $GITHUB_OUTPUT -else - echo "npm_tag=latest" >> $GITHUB_OUTPUT -fi -``` -Uses semver suffix pattern, not odd/even minor. - -**npm Publish with OIDC** (line 64): -```bash -npm publish --access public --tag ${{ steps.prerelease.outputs.npm_tag }} -``` -No `NPM_TOKEN` needed; OIDC provides authentication via `id-token: write` permission. - -### PAW Token Linting Scripts - -**lint-prompting.sh Location**: `/home/erdemtuna/workspace/personal/phased-agent-workflow/scripts/lint-prompting.sh` - -**Token Thresholds** (lines 10-16): -```bash -WARN_THRESHOLD=5000 -ERROR_THRESHOLD=7000 -SKILL_WARN_THRESHOLD=8000 -SKILL_ERROR_THRESHOLD=12000 -``` - -**Dependency Check** (lines 31-35): -```bash -if [ ! -d "node_modules/@dqbd/tiktoken" ]; then - echo -e "${RED}ERROR: Dependencies are not installed${NC}" - exit 1 -fi -``` - -**Agent File Pattern** (line 104): -```bash -local files=("$agent_dir"/*.agent.md) -``` -Expects `agents/*.agent.md` naming convention. - -**Skill File Pattern** (line 132): -```bash -find "$skill_dir" -name "SKILL.md" -type f -print0 -``` -Expects `skills/*/SKILL.md` naming convention. - -**CLI Arguments** (lines 161-175): -- No args: lint all agents -- `--skills`: lint only skills -- `--all`: lint both agents and skills - -**count-tokens.js Location**: `/home/erdemtuna/workspace/personal/phased-agent-workflow/scripts/count-tokens.js` - -**tiktoken Usage** (lines 9, 81): -```javascript -const { encoding_for_model } = require('@dqbd/tiktoken'); -const encoding = encoding_for_model(model); -``` -Uses `gpt-4o-mini` as default model (line 20). - -**PAW-Specific Template Expansion** (lines 62-72): -The script has PAW-specific logic to expand `{{PLACEHOLDER}}` patterns in agent files. This uses `ts-node` to load `src/agents/agentTemplateRenderer`. markdown-commenter does not have this pattern, so this section can be simplified or removed. - -### markdown-commenter Current Structure - -**package.json Location**: `/home/erdemtuna/workspace/personal/markdown-commenter/package.json` - -**Existing Scripts** (lines 111-123): -```json -"scripts": { - "vscode:prepublish": "npm run compile", - "compile": "tsc -p ./", - "watch": "tsc -watch -p ./", - "lint": "eslint src --ext ts", - "test": "node ./out/test/runTest.js", - "package": "vsce package" -} -``` - -**Missing Scripts**: -- `lint:agent` - single agent file linting -- `lint:agent:all` - lint all agents and skills -- `lint:skills` - lint only skills - -**Package Name** (line 2): `markdown-commenter` -VSIX will be named `markdown-commenter-.vsix` - -**Publisher** (line 7): `erdem-tuna` -Required for VS Code Marketplace publishing. - -**Existing DevDependencies** (lines 124-136): -- `@vscode/vsce` already present for VSIX packaging -- `@dqbd/tiktoken` NOT present (needs to be added) -- `ts-node` NOT present (only needed if using template expansion) - -**cli/package.json Location**: `/home/erdemtuna/workspace/personal/markdown-commenter/cli/package.json` - -**Package Scope** (line 2): `@erdem-tuna/markdown-commenter` -This is the npm package name for publishing. - -**CLI Scripts** (lines 17-21): -```json -"scripts": { - "build": "node scripts/build.js", - "test": "node --test lib/*.test.js", - "lint": "echo 'No lint configured for CLI package'" -} -``` - -**CLI Test Status**: No test files exist (`lib/*.test.js` pattern matches nothing). -PR checks can still run `npm test` which will pass with no tests. - -### Agent/Skill File Structure - -**Agent File**: `/home/erdemtuna/workspace/personal/markdown-commenter/agents/Annotate.agent.md` -- Single agent file -- Standard naming convention (matches `*.agent.md` pattern) - -**Skill File**: `/home/erdemtuna/workspace/personal/markdown-commenter/skills/annotate/SKILL.md` -- Single skill in `annotate/` subdirectory -- Matches `skills/*/SKILL.md` pattern expected by lint script - -## Code References - -### PAW Workflows -- `/home/erdemtuna/workspace/personal/phased-agent-workflow/.github/workflows/pr-checks.yml:1-66` - PR checks workflow -- `/home/erdemtuna/workspace/personal/phased-agent-workflow/.github/workflows/release.yml:1-116` - Extension release workflow -- `/home/erdemtuna/workspace/personal/phased-agent-workflow/.github/workflows/publish-cli.yml:1-92` - CLI publish workflow - -### PAW Linting Scripts -- `/home/erdemtuna/workspace/personal/phased-agent-workflow/scripts/lint-prompting.sh:1-227` - Token linting bash script -- `/home/erdemtuna/workspace/personal/phased-agent-workflow/scripts/count-tokens.js:1-97` - Token counting Node.js script - -### markdown-commenter Targets -- `/home/erdemtuna/workspace/personal/markdown-commenter/package.json:111-123` - Existing npm scripts -- `/home/erdemtuna/workspace/personal/markdown-commenter/cli/package.json:17-21` - CLI scripts -- `/home/erdemtuna/workspace/personal/markdown-commenter/agents/Annotate.agent.md` - Agent file to lint -- `/home/erdemtuna/workspace/personal/markdown-commenter/skills/annotate/SKILL.md` - Skill file to lint - -## Architecture Documentation - -### Workflow Patterns - -1. **Tag-Triggered Releases**: Both extension (`v*`) and CLI (`cli-v*`) use tag push triggers. This decouples versioning from code changes. - -2. **Version Source of Truth**: Git tag determines version; package.json is updated at build time via `npm version --no-git-tag-version`. - -3. **Idempotent Release Creation**: Check if release exists before creating; skip if already exists. Prevents duplicate releases on re-runs. - -4. **Pre-release Detection**: Extension uses odd/even minor version convention; CLI uses semver suffix (`-alpha`, `-beta`, `-rc`). - -5. **Graceful Degradation**: For Marketplace publishing, continue on failure so GitHub Release is still created (specified in WorkShaping, not implemented in PAW's current workflow—needs to be added). - -### Token Linting Patterns - -1. **Threshold Tiers**: Warning threshold allows PR to pass with notice; error threshold fails the build. - -2. **File Discovery**: Agent files via glob pattern; skill files via `find` command for nested structure. - -3. **Dependency Validation**: Script checks for `@dqbd/tiktoken` in node_modules before proceeding. - -## Adaptations Required for markdown-commenter - -### Simplifications from PAW - -1. **count-tokens.js**: Remove PAW-specific template expansion logic (lines 28-72). markdown-commenter agents don't use `{{PLACEHOLDER}}` patterns. - -2. **Node Version**: Can use Node 20 for CLI workflow (PAW uses 24, but 20 is sufficient and consistent with extension workflow). - -### Additions to PAW Patterns - -1. **VS Code Marketplace Publishing**: PAW's `release.yml` only creates GitHub Release. Need to add `vsce publish` step with `VSCE_PAT` secret. - -2. **Marketplace Failure Handling**: Add `continue-on-error: true` to Marketplace step so GitHub Release is still created on failure. - -3. **CLI Path in PR Checks**: PAW doesn't run CLI tests in PR checks. Need to add `cd cli && npm test` step. - -### Files to Create - -1. `.github/workflows/pr-checks.yml` - PR quality gates -2. `.github/workflows/release.yml` - Extension release + Marketplace -3. `.github/workflows/publish-cli.yml` - CLI npm publish -4. `scripts/lint-prompting.sh` - Token linting script -5. `scripts/count-tokens.js` - Token counting utility (simplified) - -### Package.json Updates - -1. Add `@dqbd/tiktoken` to devDependencies -2. Add npm scripts: `lint:agent`, `lint:agent:all`, `lint:skills` - -## Open Questions - -None - all implementation details are documented with sufficient precision for planning. diff --git a/.paw/work/github-actions-cicd/Docs.md b/.paw/work/github-actions-cicd/Docs.md deleted file mode 100644 index 79f3bae..0000000 --- a/.paw/work/github-actions-cicd/Docs.md +++ /dev/null @@ -1,169 +0,0 @@ -# GitHub Actions CI/CD - -## Overview - -This implementation adds automated CI/CD infrastructure to the markdown-commenter project, consisting of three GitHub Actions workflows and supporting token linting scripts. The workflows automate quality gates on pull requests and streamline the release process for both the VS Code extension and Copilot CLI package. - -The automation eliminates manual release steps, ensures consistent quality validation, and follows patterns established by the PAW (Phased Agent Workflow) project. Maintainers can now release new versions by simply pushing a git tag, while contributors receive immediate feedback on code quality through PR checks. - -## Architecture and Design - -### High-Level Architecture - -``` -GitHub Repository Events - │ - ├── PR to main ──────────► PR Checks Workflow - │ ├── lint - │ ├── compile - │ ├── extension tests - │ ├── CLI tests - │ └── agent linting - │ - ├── Push v* tag ─────────► Extension Release Workflow - │ ├── build VSIX - │ ├── GitHub Release - │ └── VS Code Marketplace - │ - └── Push cli-v* tag ─────► CLI Publish Workflow - ├── build & test - ├── npm publish - └── GitHub Release -``` - -### Design Decisions - -**Tag-triggered releases**: Releases are triggered by git tags rather than PR merges. This provides explicit control over when releases happen and separates versioning decisions from code changes. - -**Separate tag patterns**: Extension uses `v*` tags (e.g., `v1.0.0`), CLI uses `cli-v*` tags (e.g., `cli-v1.0.0`). This allows independent versioning of the two packages. - -**Tag as version source of truth**: Package.json versions are updated during the workflow from the git tag. Local development uses `0.0.1-dev`, ensuring agents are reinstalled on every activation during development. - -**Graceful Marketplace failure**: The extension release workflow uses `continue-on-error` for Marketplace publishing. If it fails, the GitHub Release is still created with the VSIX attached, ensuring users can always access the extension. - -**OIDC for npm**: CLI publishing uses npm's OIDC trusted publishing instead of access tokens. This is more secure and doesn't require storing npm tokens in repository secrets. - -### Integration Points - -**Token linting**: Uses `@dqbd/tiktoken` to count tokens in agent/skill files. Thresholds (5K/7K for agents, 8K/12K for skills) prevent oversized prompts that degrade LLM performance. - -**VS Code test infrastructure**: Uses `xvfb` to provide a virtual display for headless VS Code testing in GitHub Actions. - -## User Guide - -### Prerequisites - -**For PR checks** (automatic): -- No setup required — workflow runs automatically on PRs - -**For extension release**: -- `VSCE_PAT` secret: Personal Access Token for VS Code Marketplace - - Create at: https://dev.azure.com (Azure DevOps) - - Required scopes: Marketplace (Manage) - - Add to: Repository Settings → Secrets and variables → Actions - -**For CLI publish**: -- First-time manual publish to establish npm package -- Link package to GitHub repository on npmjs.com -- Add to cli/package.json: `"publishConfig": { "provenance": true }` - -### Basic Usage - -**Run local linting**: -```bash -npm run lint:agent # Lint agent files only -npm run lint:skills # Lint skill files only -npm run lint:agent:all # Lint both agents and skills -``` - -**Release a new extension version**: -```bash -git tag v0.2.0 -git push origin v0.2.0 -``` - -**Release a new CLI version**: -```bash -git tag cli-v0.2.0 -git push origin cli-v0.2.0 -``` - -### Advanced Usage - -**Pre-release versions**: -- Extension: Odd minor versions (v0.1.0, v0.3.0) are marked as pre-release -- CLI: Versions with `-alpha`, `-beta`, or `-rc` suffix (cli-v1.0.0-beta) - -**Re-running failed releases**: -If a release workflow fails partway through, it's safe to re-run: -- GitHub Release creation checks if release exists and skips if already present -- Marketplace/npm publish are idempotent for the same version - -## API Reference - -### Token Linting Scripts - -**lint-prompting.sh**: -```bash -./scripts/lint-prompting.sh # Lint all agents -./scripts/lint-prompting.sh --skills # Lint all skills -./scripts/lint-prompting.sh --all # Lint both -./scripts/lint-prompting.sh path/to/file # Lint specific file -``` - -**count-tokens.js**: -```bash -node scripts/count-tokens.js [model] -# model defaults to 'gpt-4o-mini' -``` - -### Configuration Options - -**Token thresholds** (in lint-prompting.sh): -| Type | Warning | Error | -|------|---------|-------| -| Agent | 5,000 | 7,000 | -| Skill | 8,000 | 12,000 | - -## Testing - -### How to Test - -**PR Checks**: -1. Create a branch with a code change -2. Open a PR to main -3. Verify workflow triggers and all checks pass/fail as expected - -**Token Linting**: -1. Run `npm run lint:agent:all` locally -2. Verify it reports correct token counts for agents/skills -3. Temporarily lower thresholds to verify failure behavior - -**Release Workflows** (dry run): -1. Push a pre-release tag (e.g., `v0.0.2` or `cli-v0.0.2-alpha`) -2. Verify GitHub Release is created -3. Check workflow logs for any warnings - -### Edge Cases - -| Scenario | Expected Behavior | -|----------|-------------------| -| Duplicate tag push | Release creation skipped (idempotent) | -| Marketplace PAT expired | Warning logged, GitHub Release still created | -| Agent exceeds 7K tokens | PR checks fail with clear error | -| npm OIDC not configured | CLI publish fails with auth error | -| No CLI test files | npm test passes (no tests = success) | - -## Limitations and Future Work - -**Current limitations**: -- No automatic changelog generation — release notes added manually -- No matrix testing across Node versions (only Node 20) -- No Windows/macOS runner support -- CLI tests don't exist yet (step passes vacuously) - -**Not implemented** (explicit scope exclusions): -- MkDocs documentation workflow -- Slack/Discord notifications -- Code coverage reporting -- Security scanning (CodeQL, Dependabot) diff --git a/.paw/work/github-actions-cicd/ImplementationPlan.md b/.paw/work/github-actions-cicd/ImplementationPlan.md deleted file mode 100644 index 054d52e..0000000 --- a/.paw/work/github-actions-cicd/ImplementationPlan.md +++ /dev/null @@ -1,255 +0,0 @@ -# GitHub Actions CI/CD Implementation Plan - -## Overview - -Implementing automated CI/CD infrastructure for markdown-commenter, consisting of three GitHub Actions workflows (PR checks, extension release, CLI publish) and supporting token linting scripts. The implementation directly adapts PAW's mature workflow patterns, customized for markdown-commenter's package structure and publishing requirements. - -## Current State Analysis - -**Existing infrastructure**: -- VS Code extension with `npm run lint`, `compile`, `test`, `package` scripts (package.json:111-123) -- CLI package with `npm run build`, `test` scripts (cli/package.json:17-21) -- Agent file at `agents/Annotate.agent.md` -- Skill file at `skills/annotate/SKILL.md` -- `@vscode/vsce` already in devDependencies for VSIX packaging - -**Gaps**: -- No `.github/workflows/` directory or workflow files -- No `scripts/` directory for linting utilities -- No `@dqbd/tiktoken` dependency for token counting -- No `lint:agent*` npm scripts - -**Key constraints**: -- VSIX filename will be `markdown-commenter-.vsix` (from package.json name) -- npm package scope is `@erdem-tuna/markdown-commenter` (cli/package.json:2) -- Publisher ID is `erdem-tuna` (package.json:7) - -## Desired End State - -1. **PR Checks**: Every PR to main runs lint, compile, extension tests, CLI tests, and agent linting -2. **Extension Release**: Pushing `v*` tag creates GitHub Release with VSIX and publishes to VS Code Marketplace -3. **CLI Publish**: Pushing `cli-v*` tag publishes to npm with OIDC provenance and creates GitHub Release -4. **Token Linting**: Local and CI execution of agent/skill token validation - -**Verification approach**: -- Create test PR to verify PR checks workflow -- Push test tag to verify release workflow (can use pre-release version like `v0.0.2`) -- Verify npm scripts work locally before pushing - -## What We're NOT Doing - -- MkDocs documentation workflow (no docs framework in use) -- Automatic changelog generation -- Release notes automation -- Slack/Discord notifications -- Code coverage reporting -- Security scanning (CodeQL, Dependabot) -- Matrix testing across Node versions -- Windows/macOS runner support - -## Phase Status - -- [x] **Phase 1: Token Linting Infrastructure** - Add scripts and dependencies for agent/skill token validation -- [x] **Phase 2: PR Checks Workflow** - Automated quality gates on pull requests -- [x] **Phase 3: Extension Release Workflow** - Tag-triggered VSIX build, GitHub Release, and Marketplace publishing -- [x] **Phase 4: CLI Publish Workflow** - Tag-triggered npm publish with OIDC -- [x] **Phase 5: Documentation** - Technical reference and README updates - -## Phase Candidates - - - ---- - -## Phase 1: Token Linting Infrastructure - -### Changes Required - -- **`scripts/lint-prompting.sh`**: Copy from PAW (`/home/erdemtuna/workspace/personal/phased-agent-workflow/scripts/lint-prompting.sh`), no modifications needed—script is generic and works with standard `agents/*.agent.md` and `skills/*/SKILL.md` patterns - -- **`scripts/count-tokens.js`**: Simplified version of PAW's script, removing template expansion logic (lines 28-72 in PAW version). markdown-commenter agents don't use `{{PLACEHOLDER}}` patterns. Keep core functionality: - - tiktoken integration for token counting - - File path argument handling - - Model parameter (default: `gpt-4o-mini`) - -- **`package.json`**: - - Add `@dqbd/tiktoken` to devDependencies - - Add scripts: - ``` - "lint:agent": "./scripts/lint-prompting.sh", - "lint:agent:all": "./scripts/lint-prompting.sh --all", - "lint:skills": "./scripts/lint-prompting.sh --skills" - ``` - -### Success Criteria - -#### Automated Verification: -- [ ] `npm run lint:agent` passes (lints agents/Annotate.agent.md) -- [ ] `npm run lint:skills` passes (lints skills/annotate/SKILL.md) -- [ ] `npm run lint:agent:all` passes (lints both) - -#### Manual Verification: -- [ ] Output shows token counts with colored OK/WARN/ERROR status -- [ ] Script fails with exit code 1 when token threshold exceeded (can test by temporarily lowering threshold) - ---- - -## Phase 2: PR Checks Workflow - -### Changes Required - -- **`.github/workflows/pr-checks.yml`**: Create workflow adapted from PAW pattern with: - - Trigger: `pull_request` to `main` branch - - Path filtering: `src/**`, `agents/**`, `skills/**`, `cli/**`, `scripts/**`, `.github/workflows/pr-checks.yml` - - Job steps: - 1. Checkout code - 2. Setup Node.js 20 with npm cache - 3. `npm ci` (root dependencies) - 4. `npm run lint` (TypeScript linting) - 5. `npm run compile` (build extension) - 6. xvfb setup + `npm test` (VS Code extension tests) - 7. `cd cli && npm ci && npm test` (CLI tests — currently no test files exist, step passes vacuously) - 8. `npm run lint:agent:all` (agent/skill token linting) - 9. Summary message on success - -**Differences from PAW**: -- Add CLI test step (PAW doesn't run CLI tests in PR checks) -- Add `cli/**` to path filter - -### Success Criteria - -#### Automated Verification: -- [ ] Workflow YAML is valid (no syntax errors on push) -- [ ] All steps complete successfully on test PR - -#### Manual Verification: -- [ ] PR shows GitHub Actions check status -- [ ] Intentional lint error causes workflow failure -- [ ] Path filtering works (docs-only change skips workflow) - ---- - -## Phase 3: Extension Release Workflow - -### Changes Required - -- **`.github/workflows/release.yml`**: Create workflow adapted from PAW with Marketplace publishing added: - - Trigger: `push` tags matching `v*` - - Permissions: `contents: write` - - Job steps: - 1. Checkout code - 2. Setup Node.js 20 with npm cache - 3. `npm ci` - 4. `npm run compile` - 5. Extract version from tag (remove `v` prefix) - 6. Update package.json version via `npm version --no-git-tag-version` - 7. Determine pre-release status (odd minor = pre-release) - 8. `npm run package` (create VSIX) - 9. Verify VSIX exists with expected filename (`markdown-commenter-.vsix`) - 10. Check if GitHub Release exists (skip if yes) - 11. Create GitHub Release with VSIX attached (using `softprops/action-gh-release@v1`) - 12. Publish to VS Code Marketplace via `vsce publish` (with `continue-on-error: true`) - -**Marketplace publishing step** (new vs PAW): -```yaml -- name: Publish to VS Code Marketplace - continue-on-error: true # Don't fail workflow if Marketplace upload fails - run: npx vsce publish --pat ${{ secrets.VSCE_PAT }} - env: - VSCE_PAT: ${{ secrets.VSCE_PAT }} -``` - -**Inline documentation comments** to add: -- How to obtain VSCE_PAT (Azure DevOps PAT with Marketplace scope) -- Pre-release versioning convention explanation -- Why `continue-on-error` is used for Marketplace step - -### Success Criteria - -#### Automated Verification: -- [ ] Workflow YAML is valid -- [ ] Pushing test tag creates GitHub Release with VSIX attached - -#### Manual Verification: -- [ ] Pre-release tag (e.g., `v0.1.0`) creates pre-release -- [ ] Stable tag (e.g., `v0.2.0`) creates stable release -- [ ] Duplicate tag push skips release creation -- [ ] Marketplace failure logs warning but Release still created - ---- - -## Phase 4: CLI Publish Workflow - -### Changes Required - -- **`.github/workflows/publish-cli.yml`**: Create workflow adapted from PAW: - - Trigger: `push` tags matching `cli-v*` - - Permissions: `id-token: write` (OIDC), `contents: write` (releases) - - Default working directory: `cli` - - Job steps: - 1. Checkout code - 2. Setup Node.js 20 with registry-url for npm - 3. Extract version from tag (remove `cli-v` prefix) - 4. Determine pre-release status (check for `-alpha`, `-beta`, `-rc` suffix) - 5. Set package.json version via `npm version --no-git-tag-version` - 6. `npm ci` - 7. `npm run build` - 8. `npm test` - 9. `npm publish --access public --tag ` (OIDC auth) - 10. Check if GitHub Release exists (working-directory override to repo root) - 11. Create GitHub Release - -**Prerequisites for npm OIDC**: -- cli/package.json must have `"publishConfig": { "provenance": true }` for OIDC to work -- Package must be linked to GitHub repository in npm settings -- First publish may require manual setup on npmjs.com - -**Inline documentation comments** to add: -- npm OIDC setup requirements (package must be configured for provenance) -- Pre-release npm tag convention (`beta` vs `latest`) -- Why Node 20 (not 24 like PAW—consistency with extension workflow) - -### Success Criteria - -#### Automated Verification: -- [ ] Workflow YAML is valid -- [ ] Pushing test tag triggers workflow - -#### Manual Verification: -- [ ] npm package published with provenance -- [ ] GitHub Release created with npm package link -- [ ] Pre-release suffix correctly sets npm tag to `beta` - ---- - -## Phase 5: Documentation - -### Changes Required - -- **`.paw/work/github-actions-cicd/Docs.md`**: Technical reference covering: - - Overview of CI/CD infrastructure - - Workflow descriptions and triggers - - Token linting thresholds and usage - - Secrets configuration requirements - - Troubleshooting common issues - -- **`README.md`**: Add "Development" or "Contributing" section with: - - How to run tests locally - - How to lint agent files - - Release process overview (tag → workflow → artifacts) - -### Success Criteria - -- [ ] Docs.md follows `paw-docs-guidance` template -- [ ] README additions are concise and actionable -- [ ] No broken links or outdated information - ---- - -## References - -- Issue: none -- Spec: `.paw/work/github-actions-cicd/Spec.md` -- Research: `.paw/work/github-actions-cicd/CodeResearch.md` -- WorkShaping: `./WorkShaping-GHActions.md` -- PAW Workflows: `/home/erdemtuna/workspace/personal/phased-agent-workflow/.github/workflows/` diff --git a/.paw/work/github-actions-cicd/Spec.md b/.paw/work/github-actions-cicd/Spec.md deleted file mode 100644 index df3c712..0000000 --- a/.paw/work/github-actions-cicd/Spec.md +++ /dev/null @@ -1,180 +0,0 @@ -# Feature Specification: GitHub Actions CI/CD - -**Branch**: feature/github-actions-cicd | **Created**: 2026-02-26 | **Status**: Draft -**Input Brief**: Automate build, test, and release pipelines for markdown-commenter VS Code extension and CLI - -## Overview - -The markdown-commenter project currently lacks automated CI/CD infrastructure. Every release requires manual execution of build commands, manual VSIX packaging, manual uploads to VS Code Marketplace, and manual npm publishing. This is error-prone, time-consuming, and doesn't scale as the project grows. - -This feature establishes GitHub Actions workflows that automate quality gates on pull requests and streamline the release process for both the VS Code extension and Copilot CLI. By modeling after PAW's mature CI/CD patterns, maintainers can confidently merge PRs knowing they've passed automated checks, and release new versions by simply pushing a git tag. - -The automation serves two user groups: contributors who benefit from immediate feedback on code quality, and maintainers who can release with confidence through a standardized, repeatable process. The workflows are designed for resilience—if VS Code Marketplace upload fails, the GitHub Release with downloadable VSIX is still created. - -## Objectives - -- Enable automated quality validation on every pull request (lint, compile, test) -- Provide one-command releases via git tags for both extension and CLI -- Publish VS Code extension to both GitHub Releases and VS Code Marketplace -- Publish CLI package to npm registry with provenance -- Enforce agent/skill token size limits to prevent oversized prompts -- Document secrets setup and release procedures inline in workflow files - -## User Scenarios & Testing - -### User Story P1 – Contributor Submits a Pull Request -**Narrative**: A contributor opens a PR with code changes. Within minutes, they receive feedback on whether their changes pass linting, compilation, and tests without needing to run commands locally. - -**Independent Test**: Open a PR with a TypeScript syntax error; verify the workflow fails and reports the error. - -**Acceptance Scenarios**: -1. Given a PR is opened to main, When the PR contains valid code, Then all checks pass and show green status -2. Given a PR is opened to main, When the PR contains a lint violation, Then the lint step fails with a clear error message -3. Given a PR is opened to main, When the PR contains a test failure, Then the test step fails showing which test failed -4. Given a PR modifies only documentation files, When no source files changed, Then the workflow is skipped (path filtering) - -### User Story P2 – Maintainer Releases VS Code Extension -**Narrative**: A maintainer pushes a version tag (e.g., `v1.0.0`). The workflow builds the extension, creates a GitHub Release with the VSIX attached, and publishes to VS Code Marketplace. - -**Independent Test**: Push a `v0.0.2` tag; verify GitHub Release is created with VSIX file attached. - -**Acceptance Scenarios**: -1. Given a `v*` tag is pushed, When the build succeeds, Then a GitHub Release is created with the VSIX attached -2. Given a `v*` tag is pushed, When Marketplace upload fails, Then GitHub Release is still created (with warning logged) -3. Given a `v0.3.0` tag (odd minor), When the release is created, Then it is marked as pre-release -4. Given a `v0.2.0` tag (even minor), When the release is created, Then it is marked as stable release -5. Given the same tag is pushed twice, When a release already exists, Then the workflow skips release creation (idempotent) - -### User Story P3 – Maintainer Releases CLI Package -**Narrative**: A maintainer pushes a CLI version tag (e.g., `cli-v1.0.0`). The workflow builds, tests, and publishes the CLI to npm, then creates a GitHub Release. - -**Independent Test**: Push a `cli-v0.0.2` tag; verify npm package is published and GitHub Release is created. - -**Acceptance Scenarios**: -1. Given a `cli-v*` tag is pushed, When build and tests pass, Then npm package is published with provenance -2. Given a `cli-v1.0.0-beta` tag, When published to npm, Then the package is tagged as `beta` (not `latest`) -3. Given a `cli-v*` tag is pushed, When npm publish succeeds, Then a GitHub Release is created -4. Given CLI tests fail, When the workflow runs, Then npm publish is skipped and workflow fails - -### User Story P4 – Contributor Adds Large Agent File -**Narrative**: A contributor adds or modifies an agent file that exceeds token limits. The PR checks catch this before merge to prevent oversized prompts in production. - -**Independent Test**: Add an agent file with 8000+ tokens; verify PR checks fail with token limit error. - -**Acceptance Scenarios**: -1. Given an agent file exceeds 7000 tokens, When PR checks run, Then the lint step fails with error -2. Given an agent file is between 5000-7000 tokens, When PR checks run, Then a warning is shown but checks pass -3. Given a skill file exceeds 12000 tokens, When PR checks run, Then the lint step fails with error - -### Edge Cases - -- **Package.json version mismatch**: Workflow extracts version from tag and updates package.json, ensuring tag is source of truth -- **Orphaned tags**: If workflow fails mid-execution, tag remains but no release exists; maintainer can re-trigger or delete tag -- **VSCE_PAT expired**: Marketplace upload fails; GitHub Release created anyway; maintainer renews PAT and can manually publish -- **npm OIDC misconfigured**: npm publish fails; workflow fails; maintainer must fix OIDC setup before retry -- **Feature branch tag**: Branch protection should prevent this; if bypassed, workflow runs but release may contain unexpected code - -## Requirements - -### Functional Requirements - -- FR-001: PR checks workflow triggers on pull requests to main branch (Stories: P1) -- FR-002: PR checks workflow runs TypeScript linting via `npm run lint` (Stories: P1) -- FR-003: PR checks workflow compiles extension via `npm run compile` (Stories: P1) -- FR-004: PR checks workflow runs VS Code extension tests with xvfb (Stories: P1) -- FR-005: PR checks workflow runs CLI tests via `cd cli && npm test` (Stories: P1) -- FR-006: PR checks workflow runs agent/skill token linting (Stories: P1, P4) -- FR-007: PR checks workflow uses path filtering to skip on non-code changes (Stories: P1) -- FR-008: Extension release workflow triggers on `v*` tag push (Stories: P2) -- FR-009: Extension release workflow extracts version from tag and updates package.json (Stories: P2) -- FR-010: Extension release workflow determines pre-release status from version number (Stories: P2) -- FR-011: Extension release workflow packages VSIX file (Stories: P2) -- FR-012: Extension release workflow creates GitHub Release with VSIX attached (Stories: P2) -- FR-013: Extension release workflow publishes to VS Code Marketplace (Stories: P2) -- FR-014: Extension release workflow continues on Marketplace failure (Stories: P2) -- FR-015: Extension release workflow skips if release already exists (Stories: P2) -- FR-016: CLI publish workflow triggers on `cli-v*` tag push (Stories: P3) -- FR-017: CLI publish workflow builds and tests CLI package (Stories: P3) -- FR-018: CLI publish workflow publishes to npm with OIDC provenance (Stories: P3) -- FR-019: CLI publish workflow creates GitHub Release after npm publish (Stories: P3) -- FR-020: CLI publish workflow determines npm tag from version suffix (Stories: P3) -- FR-021: Token linting script counts tokens using tiktoken library (Stories: P4) -- FR-022: Token linting script enforces configurable thresholds (Stories: P4) - -### Key Entities - -- **Workflow**: GitHub Actions YAML file defining automated jobs -- **Tag**: Git reference triggering release workflows (`v*` or `cli-v*`) -- **VSIX**: VS Code extension package file -- **Release**: GitHub Release with attached artifacts and notes - -### Cross-Cutting / Non-Functional - -- Workflows must complete within GitHub Actions timeout limits (6 hours default) -- Secrets (VSCE_PAT) must be documented but not committed -- npm publishing must use OIDC (no token secrets) -- All workflows must include descriptive comments explaining purpose and setup - -## Success Criteria - -- SC-001: PRs receive automated feedback within 5 minutes of opening (FR-001, FR-002, FR-003, FR-004, FR-005) -- SC-002: Pushing a `v*` tag results in a GitHub Release with downloadable VSIX within 10 minutes (FR-008, FR-011, FR-012) -- SC-003: VS Code Marketplace shows the extension after successful release (FR-013) -- SC-004: npm registry shows CLI package with provenance after `cli-v*` tag push (FR-016, FR-018) -- SC-005: Agent files exceeding 7000 tokens cause PR check failure (FR-006, FR-021, FR-022) -- SC-006: Workflows are self-documenting with inline comments explaining secrets setup (FR-013, FR-018) -- SC-007: Duplicate tag push does not create duplicate release (FR-015) - -## Assumptions - -- **Publisher ID**: VS Code Marketplace publisher is `erdem-tuna` (from package.json) -- **npm scope**: CLI package scope is `@erdem-tuna/markdown-commenter` (from cli/package.json) -- **Token thresholds**: Use PAW defaults (5K warn, 7K error for agents; 8K warn, 12K error for skills) -- **No docs workflow**: MkDocs documentation workflow not needed for initial release -- **Branch protection**: Repository will have branch protection enabled on main (documented requirement, not enforced by workflows) -- **tiktoken compatibility**: The `@dqbd/tiktoken` package works in GitHub Actions Node.js 20 environment - -## Scope - -**In Scope**: -- PR checks workflow (lint, compile, test, agent lint) -- Extension release workflow (build, GitHub Release, Marketplace) -- CLI publish workflow (build, test, npm, GitHub Release) -- Token linting scripts (lint-prompting.sh, count-tokens.js) -- Inline documentation in workflow files -- npm scripts for local linting - -**Out of Scope**: -- Documentation site workflow (MkDocs) -- Automatic changelog generation -- Release notes automation -- Slack/Discord notifications -- Code coverage reporting -- Security scanning (CodeQL, Dependabot) -- Matrix testing across Node versions -- Windows/macOS runner support - -## Dependencies - -- GitHub Actions (service) -- VS Code Marketplace API (service) -- npm registry with OIDC support (service) -- `@dqbd/tiktoken` npm package (library) -- `@vscode/vsce` for VSIX packaging (existing devDependency) -- Repository secrets: `VSCE_PAT` (for Marketplace publishing) - -## Risks & Mitigations - -- **VSCE_PAT expiration**: PATs expire periodically. **Mitigation**: Document renewal process in workflow comments; GitHub Release created even if Marketplace fails. -- **npm OIDC complexity**: OIDC setup requires npm package configuration. **Mitigation**: Document prerequisites clearly; test with dry-run before first real publish. -- **tiktoken version drift**: Token counting may vary across versions. **Mitigation**: Pin version in package.json. -- **Workflow maintenance burden**: Three workflows to maintain. **Mitigation**: Model closely after PAW patterns for consistency; consider composite actions in future. -- **Branch protection bypass**: Emergency hotfixes may bypass checks. **Mitigation**: Document bypass procedure; accept as intentional escape hatch. - -## References - -- WorkShaping: ./WorkShaping-GHActions.md -- PAW PR Checks: /home/erdemtuna/workspace/personal/phased-agent-workflow/.github/workflows/pr-checks.yml -- PAW Release: /home/erdemtuna/workspace/personal/phased-agent-workflow/.github/workflows/release.yml -- PAW CLI Publish: /home/erdemtuna/workspace/personal/phased-agent-workflow/.github/workflows/publish-cli.yml -- PAW Lint Script: /home/erdemtuna/workspace/personal/phased-agent-workflow/scripts/lint-prompting.sh diff --git a/.paw/work/github-actions-cicd/WorkflowContext.md b/.paw/work/github-actions-cicd/WorkflowContext.md deleted file mode 100644 index db02061..0000000 --- a/.paw/work/github-actions-cicd/WorkflowContext.md +++ /dev/null @@ -1,40 +0,0 @@ -# WorkflowContext - -Work Title: GitHub Actions CI/CD -Work ID: github-actions-cicd -Base Branch: main -Target Branch: feature/github-actions-cicd -Workflow Mode: full -Review Strategy: local -Review Policy: milestones -Session Policy: continuous -Final Agent Review: enabled -Final Review Mode: single-model -Final Review Interactive: smart -Final Review Models: none -Final Review Specialists: all -Final Review Interaction Mode: parallel -Final Review Specialist Models: none -Plan Generation Mode: single-model -Plan Generation Models: none -Planning Docs Review: enabled -Planning Review Mode: single-model -Planning Review Interactive: smart -Planning Review Models: none -Custom Workflow Instructions: none -Initial Prompt: Create GitHub Actions workflows for markdown-commenter: PR checks (lint, compile, test), extension release (v* tags -> GitHub Release + VS Code Marketplace), and CLI publish (cli-v* tags -> npm). Model after PAW's existing workflows. -Issue URL: none -Remote: origin -Artifact Lifecycle: commit-and-clean -Artifact Paths: auto-derived -Additional Inputs: WorkShaping-GHActions.md - -## Stage Progress - -- [x] Specification -- [x] Code Research -- [x] Planning -- [x] Planning Docs Review -- [x] Implementation -- [ ] Final Review -- [ ] Final PR From 2e463a1976a718d972dbe7289a3abcadd9db7a85 Mon Sep 17 00:00:00 2001 From: Erdem Tuna Date: Thu, 26 Feb 2026 16:23:55 +0300 Subject: [PATCH 14/18] Add repository setup documentation for CI/CD secrets Documents VSCE_PAT and NPM_TOKEN secrets required for releases, plus first-time CLI publish instructions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/README.md b/README.md index 7e88fdb..b3ab9d9 100644 --- a/README.md +++ b/README.md @@ -158,6 +158,29 @@ Releases are automated via GitHub Actions: - **Extension**: Push a `v*` tag (e.g., `git tag v1.0.0 && git push origin v1.0.0`) - **CLI**: Push a `cli-v*` tag (e.g., `git tag cli-v1.0.0 && git push origin cli-v1.0.0`) +### Repository setup (Maintainers) + +The following GitHub Actions secrets must be configured for CI/CD to work: + +| Secret | Required For | How to Get | +|--------|--------------|------------| +| `VSCE_PAT` | Extension releases | [Azure DevOps](https://dev.azure.com) → User Settings → Personal Access Tokens → New Token with **Marketplace (Publish)** scope | +| `NPM_TOKEN` | CLI publishing | [npmjs.com](https://www.npmjs.com/settings/~/tokens) → Access Tokens → Generate New Token (Automation) | + +Set secrets at: **Settings → Secrets and variables → Actions → New repository secret** + +#### First-time CLI publish + +The first npm publish must be done manually to establish the package: + +```bash +cd cli +npm login +npm publish --access public +``` + +After this, subsequent publishes use the `NPM_TOKEN` secret automatically. + ## Contributing Contributions welcome! Please: From e1b6fef34400f671e4ab599bafd4cb7501d082d7 Mon Sep 17 00:00:00 2001 From: Erdem Tuna Date: Thu, 26 Feb 2026 16:36:25 +0300 Subject: [PATCH 15/18] Move maintainer docs to CONTRIBUTING.md - Create CONTRIBUTING.md with dev setup, PR workflow, release process - Add maintainer guide section with secrets, first-time publish, token limits - Simplify README to point to CONTRIBUTING.md Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- CONTRIBUTING.md | 114 ++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 23 +--------- 2 files changed, 115 insertions(+), 22 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..14ff835 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,114 @@ +# Contributing to Markdown Commenter + +Thank you for your interest in contributing! This guide covers development setup, workflows, and maintainer tasks. + +## Development Setup + +### Prerequisites + +- Node.js 18+ +- npm 9+ +- VS Code (for extension development) + +### Build from Source + +```bash +git clone https://github.com/erdemtuna/markdown-commenter +cd markdown-commenter +npm install +npm run compile +``` + +### Run Tests + +```bash +npm test # Extension tests (requires VS Code) +cd cli && npm test # CLI tests +``` + +### Lint + +```bash +npm run lint # TypeScript/ESLint +npm run lint:agent:all # Agent/skill token limits +``` + +### Package Extension + +```bash +npm run package # Creates .vsix file +``` + +## Pull Request Workflow + +1. Fork the repository +2. Create a feature branch from `main` +3. Make your changes with tests +4. Ensure all checks pass locally: + ```bash + npm run lint && npm run compile && npm test + ``` +5. Submit a pull request + +PRs trigger automated checks: lint, compile, test, and agent token linting. + +## Release Process + +Releases are automated via GitHub Actions using git tags: + +| Release Type | Tag Pattern | Example | +|--------------|-------------|---------| +| Extension | `v*` | `git tag v1.2.0 && git push origin v1.2.0` | +| CLI | `cli-v*` | `git tag cli-v1.2.0 && git push origin cli-v1.2.0` | + +### Version Conventions + +- **Extension**: Odd minor versions (e.g., `v1.1.0`) are pre-releases +- **CLI**: Use semver suffixes for pre-releases (e.g., `cli-v1.0.0-beta.1`) + +--- + +## Maintainer Guide + +### Repository Secrets + +The following GitHub Actions secrets must be configured for CI/CD: + +| Secret | Required For | How to Get | +|--------|--------------|------------| +| `VSCE_PAT` | Extension releases | [Azure DevOps](https://dev.azure.com) → User Settings → Personal Access Tokens → New Token with **Marketplace (Publish)** scope | +| `NPM_TOKEN` | CLI publishing | [npmjs.com](https://www.npmjs.com/settings/~/tokens) → Access Tokens → Generate New Token (Automation) | + +**Configure at:** Repository → Settings → Secrets and variables → Actions → New repository secret + +### First-Time CLI Publish + +The first npm publish must be done manually to establish the package: + +```bash +cd cli +npm login +npm publish --access public +``` + +Subsequent publishes use the `NPM_TOKEN` secret automatically. + +### Token Limits + +Agent and skill files have token limits enforced by CI: + +| File Type | Warning | Error | +|-----------|---------|-------| +| Agents (`agents/*.agent.md`) | 5,000 | 7,000 | +| Skills (`skills/*/SKILL.md`) | 8,000 | 12,000 | + +Check locally with: +```bash +npm run lint:agent:all +``` + +### Workflow Files + +- `.github/workflows/pr-checks.yml` — PR quality gates +- `.github/workflows/release.yml` — Extension release (v* tags) +- `.github/workflows/publish-cli.yml` — CLI npm publish (cli-v* tags) diff --git a/README.md b/README.md index b3ab9d9..ef686f7 100644 --- a/README.md +++ b/README.md @@ -158,28 +158,7 @@ Releases are automated via GitHub Actions: - **Extension**: Push a `v*` tag (e.g., `git tag v1.0.0 && git push origin v1.0.0`) - **CLI**: Push a `cli-v*` tag (e.g., `git tag cli-v1.0.0 && git push origin cli-v1.0.0`) -### Repository setup (Maintainers) - -The following GitHub Actions secrets must be configured for CI/CD to work: - -| Secret | Required For | How to Get | -|--------|--------------|------------| -| `VSCE_PAT` | Extension releases | [Azure DevOps](https://dev.azure.com) → User Settings → Personal Access Tokens → New Token with **Marketplace (Publish)** scope | -| `NPM_TOKEN` | CLI publishing | [npmjs.com](https://www.npmjs.com/settings/~/tokens) → Access Tokens → Generate New Token (Automation) | - -Set secrets at: **Settings → Secrets and variables → Actions → New repository secret** - -#### First-time CLI publish - -The first npm publish must be done manually to establish the package: - -```bash -cd cli -npm login -npm publish --access public -``` - -After this, subsequent publishes use the `NPM_TOKEN` secret automatically. +See [CONTRIBUTING.md](CONTRIBUTING.md) for maintainer setup (secrets, first-time publish, etc.). ## Contributing From 7f68f30b3a8fac8c5bd916482d9a32c8bf757d56 Mon Sep 17 00:00:00 2001 From: Erdem Tuna Date: Thu, 26 Feb 2026 16:39:57 +0300 Subject: [PATCH 16/18] Fix test failures: truncate edge case and WSL platform - truncate.ts: Handle maxLength < 3 by returning truncated ellipsis - platformDetection.test.ts: Include 'wsl' in valid platforms list Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- WorkShaping-GHActions.md | 226 ++++++++++++++++++ .../suite/agents/platformDetection.test.ts | 2 +- src/ui/utils/truncate.ts | 5 + 3 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 WorkShaping-GHActions.md diff --git a/WorkShaping-GHActions.md b/WorkShaping-GHActions.md new file mode 100644 index 0000000..d51ec5a --- /dev/null +++ b/WorkShaping-GHActions.md @@ -0,0 +1,226 @@ +# Work Shaping: GitHub Actions CI/CD for markdown-commenter + +## Problem Statement + +**Who benefits**: Maintainers and contributors of the markdown-commenter project. + +**What problem is solved**: Currently, markdown-commenter has no automated build, test, or release pipeline. Publishing the VS Code extension and Copilot CLI requires manual steps that are error-prone and time-consuming. This work establishes GitHub Actions workflows modeled after the PAW project to automate quality gates and releases. + +## Work Breakdown + +### Core Functionality + +1. **PR Checks Workflow** (`pr-checks.yml`) + - Triggered on PRs to `main` (and feature branches if applicable) + - Path filtering: `src/**`, `agents/**`, `skills/**`, `cli/**`, `.github/workflows/**` + - Steps: + - Checkout, setup Node.js 20, cache npm dependencies + - `npm run lint` — TypeScript linting + - `npm run compile` — build extension + - `xvfb-run -a npm test` — VS Code extension tests (headless) + - `cd cli && npm test` — CLI tests + - `npm run lint:agent:all` — agent/skill token linting + +2. **Extension Release Workflow** (`release.yml`) + - Triggered on `v*` tags (e.g., `v1.0.0`, `v0.3.0`) + - Steps: + - Extract version from tag, update package.json + - Determine pre-release status (odd minor = pre-release) + - Compile and package VSIX + - Verify VSIX file exists + - Check if GitHub Release already exists (skip if yes) + - Create GitHub Release with VSIX attached + - Publish to VS Code Marketplace (continue on failure, log warning) + - Secrets required: `VSCE_PAT` (documented in workflow comments) + +3. **CLI Publish Workflow** (`publish-cli.yml`) + - Triggered on `cli-v*` tags (e.g., `cli-v1.0.0`) + - Working directory: `cli/` + - Steps: + - Extract version from tag + - Determine pre-release status (semver suffixes: -alpha, -beta, -rc) + - Set package.json version from tag + - Install dependencies, build, run tests + - Verify dist/ contents are complete + - Publish to npm with OIDC trusted publishing (provenance) + - Check if GitHub Release exists (skip if yes) + - Create GitHub Release + - Authentication: npm OIDC (no token secret needed, requires npm package setup) + +### Supporting Infrastructure + +4. **Agent/Skill Linting Scripts** + - Copy and adapt from PAW: + - `scripts/lint-prompting.sh` — token size linter + - `scripts/count-tokens.js` — tiktoken-based counter + - Adapt for markdown-commenter paths and structure + - Add `@dqbd/tiktoken` as devDependency + - Add `lint:agent`, `lint:agent:all`, `lint:skills` npm scripts + +5. **Documentation** + - Inline comments in workflows explaining: + - How to obtain and set `VSCE_PAT` + - npm OIDC setup requirements + - Branch protection recommendations + - Pre-release versioning convention + +## Edge Cases & Expected Handling + +| Scenario | Handling | +|----------|----------| +| VS Code Marketplace upload fails | Continue workflow, log warning; GitHub Release still created with VSIX | +| VSIX packaging fails | Fail workflow entirely | +| CLI build produces incomplete dist/ | Fail workflow entirely | +| Missing changelog/release notes | Create release with placeholder text (user fills in later) | +| Same tag pushed twice | Skip release creation (idempotent) | +| package.json version ≠ tag | Tag is source of truth; workflow sets package.json version from tag | +| npm publish auth failure | Fail workflow (OIDC misconfiguration needs fixing) | +| Tag pushed from non-main branch | Use branch protection rules to prevent; document as requirement | + +## Rough Architecture + +``` +┌─────────────────────────────────────────────────────────────┐ +│ GitHub Repository │ +├─────────────────────────────────────────────────────────────┤ +│ │ +│ PR to main ─────────────────┐ │ +│ ▼ │ +│ ┌─────────────────┐ │ +│ │ PR Checks │ │ +│ │ (pr-checks.yml)│ │ +│ └────────┬────────┘ │ +│ │ │ +│ ▼ │ +│ ┌──────────────────────────┐ │ +│ │ lint → compile → test │ │ +│ │ extension + CLI + agents │ │ +│ └──────────────────────────┘ │ +│ │ +│ Push tag v* ────────────────┐ │ +│ ▼ │ +│ ┌─────────────────┐ │ +│ │ Extension │ │ +│ │ Release │ │ +│ │ (release.yml) │ │ +│ └────────┬────────┘ │ +│ │ │ +│ ▼ │ +│ ┌──────────────────────────┐ │ +│ │ Build VSIX │ │ +│ │ │ │ │ +│ │ ├─► GitHub │ │ +│ │ │ Release │ │ +│ │ │ │ │ +│ │ └─► VS Code │ │ +│ │ Marketplace │ │ +│ └──────────────────────────┘ │ +│ │ +│ Push tag cli-v* ────────────┐ │ +│ ▼ │ +│ ┌─────────────────┐ │ +│ │ CLI Publish │ │ +│ │(publish-cli.yml)│ │ +│ └────────┬────────┘ │ +│ │ │ +│ ▼ │ +│ ┌──────────────────────────┐ │ +│ │ Build CLI │ │ +│ │ │ │ │ +│ │ ├─► npm registry │ │ +│ │ │ │ │ +│ │ └─► GitHub │ │ +│ │ Release │ │ +│ └──────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────┘ +``` + +## Critical Analysis + +### Value Assessment + +**High value**: This automation eliminates manual release steps, ensures consistent quality gates, and aligns markdown-commenter with PAW's mature CI/CD practices. The one-time setup cost pays off quickly with every release. + +### Build vs. Modify Tradeoffs + +**Approach**: Model after PAW's existing workflows rather than starting from scratch. + +**Why copy/adapt vs. reusable templates**: +- These two projects have similar but not identical structures +- Directly importing workflows would create tight coupling +- Copy-and-adapt allows project-specific customization while sharing patterns +- Future: Consider extracting reusable composite actions if more projects adopt this pattern + +### Risks + +1. **VSCE_PAT expiration**: Personal Access Tokens expire; document renewal process +2. **npm OIDC setup**: Requires npm package configuration; document prerequisites +3. **tiktoken dependency**: External dependency for token counting; pin version +4. **Branch protection overhead**: May slow down emergency hotfixes; document bypass procedure + +## Codebase Fit + +### Similar Features in PAW + +- `/.github/workflows/pr-checks.yml` — quality gate workflow +- `/.github/workflows/release.yml` — VSIX release workflow +- `/.github/workflows/publish-cli.yml` — npm publish workflow +- `/scripts/lint-prompting.sh` — agent/skill linting +- `/scripts/count-tokens.js` — token counting utility + +### Reuse Opportunities + +| PAW File | Reuse Strategy | +|----------|----------------| +| `pr-checks.yml` | Copy, adapt paths and job names | +| `release.yml` | Copy, add Marketplace publish step, adapt package name | +| `publish-cli.yml` | Copy, adapt package name and scope | +| `lint-prompting.sh` | Copy as-is (generic enough) | +| `count-tokens.js` | Copy, remove PAW-specific template expansion if not needed | + +## Risk Assessment + +### Potential Negative Impacts + +1. **Failed releases leave orphaned tags**: Document tag cleanup procedure +2. **Marketplace publish failures could delay user access**: Mitigated by always creating GitHub Release first +3. **Token linting may block legitimate large agents**: Thresholds are warnings first, errors only at extreme sizes + +### Gotchas + +- **npm OIDC requires package.json `publishConfig`**: Document in workflow +- **VS Code extension tests need `xvfb`**: Already handled in PAW's PR checks +- **CLI working directory**: Workflows must use `working-directory: cli` +- **Package names differ**: markdown-commenter vs paw-workflow in VSIX filenames + +## Open Questions for Downstream Stages + +1. **Marketplace publisher ID**: Is `erdem-tuna` the correct publisher for VS Code Marketplace? +2. **npm package scope**: Confirm `@erdem-tuna/markdown-commenter` is the intended npm scope +3. **Token thresholds**: Use PAW's defaults (5K warn, 7K error for agents; 8K/12K for skills)? +4. **Should CLI tests run as part of PR checks?**: Currently planned as yes +5. **MkDocs workflow**: PAW has `docs.yml` for documentation — needed for markdown-commenter? + +## Session Notes + +### Key Decisions + +- **Tag-triggered releases**: Matches PAW pattern, allows deliberate releases +- **Separate tag patterns**: `v*` for extension, `cli-v*` for CLI (independent versioning) +- **Even/odd minor versioning**: Aligns with VS Code extension pre-release convention +- **OIDC over access tokens**: More secure npm authentication +- **Skip Marketplace on failure**: Resilience over strict consistency; GitHub Release is primary + +### Rejected Alternatives + +- **Reusable workflow templates**: Rejected in favor of copy/adapt for project independence +- **Auto-release on PR merge**: Rejected; tag-triggered gives more control +- **Single tag for both artifacts**: Rejected; independent versioning is more flexible +- **Access token for npm**: Rejected; OIDC is best practice + +### Surprising Discoveries + +- PAW already has comprehensive workflows that can serve as templates +- markdown-commenter's CLI structure closely mirrors PAW's CLI structure +- Agent linting infrastructure (tiktoken) requires a devDependency addition diff --git a/src/test/suite/agents/platformDetection.test.ts b/src/test/suite/agents/platformDetection.test.ts index 2ea6809..0a1ef24 100644 --- a/src/test/suite/agents/platformDetection.test.ts +++ b/src/test/suite/agents/platformDetection.test.ts @@ -5,7 +5,7 @@ suite('Platform Detection Test Suite', () => { suite('getPlatformInfo', () => { test('should return a valid platform', () => { const platform = getPlatformInfo(); - assert.ok(['darwin', 'win32', 'linux'].includes(platform)); + assert.ok(['darwin', 'win32', 'linux', 'wsl'].includes(platform)); }); }); diff --git a/src/ui/utils/truncate.ts b/src/ui/utils/truncate.ts index bebbbd5..13aa019 100644 --- a/src/ui/utils/truncate.ts +++ b/src/ui/utils/truncate.ts @@ -12,5 +12,10 @@ export function truncateForDisplay(text: string, maxLength = 50): string { return normalized; } + // Minimum meaningful maxLength is 3 (for "...") + if (maxLength < 3) { + return '...'.slice(0, maxLength); + } + return normalized.slice(0, maxLength - 3) + '...'; } From 7b19160c60be697e8a7be9d2b4f80fbbc20ca2a6 Mon Sep 17 00:00:00 2001 From: Erdem Tuna Date: Thu, 26 Feb 2026 16:50:57 +0300 Subject: [PATCH 17/18] Fix CLI test step to skip when no test files exist Node --test fails when glob matches nothing. Check for files first. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/pr-checks.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 5653382..e394c7e 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -60,9 +60,14 @@ jobs: run: cd cli && npm ci - name: Run CLI tests - # Note: Currently no test files exist in cli/lib/*.test.js - # This step will pass vacuously until CLI tests are added - run: cd cli && npm test + run: | + cd cli + # Check if test files exist before running + if ls lib/*.test.js 1> /dev/null 2>&1; then + npm test + else + echo "No CLI test files found (lib/*.test.js) - skipping" + fi - name: Lint agent files run: npm run lint:agent:all From 1bf2020b8d1467a2201210edb0a6e797890e2afe Mon Sep 17 00:00:00 2001 From: Erdem Tuna Date: Thu, 26 Feb 2026 17:09:13 +0300 Subject: [PATCH 18/18] Add extension icon for Marketplace - Add 256x256 PNG icon at images/icon.png - Remove placeholder SVG - Add icon field to package.json Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- images/icon.png | Bin 0 -> 5246 bytes images/icon.svg | 6 ------ package.json | 1 + 3 files changed, 1 insertion(+), 6 deletions(-) create mode 100644 images/icon.png delete mode 100644 images/icon.svg diff --git a/images/icon.png b/images/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..aaa26578f6274a1a5590946b8ace58dc795c3b5e GIT binary patch literal 5246 zcmd^D`8$+h_kWDF7)#l=VN4Ozpdyvs*vh_U-^sokg`toMH4IS^h3rcP5or>lWZ##u zCi|ppWt;Eg`@{Pmyg$9yHP3a=bLPx_miwIZIp=<4WS|W_&3_sI0I04G+5`Y-z^^m_ z69c%|1{J%5%c%ezt6%^yXg+ypg1zo=f<(R$&D$ZS{_Y_dryw@~gTbIY{k(%+oC4fX z{y`pD6h(dj;AGZCtC@voZ;&HGIL&hyH~m8y2g!FKkXCg_YNyoqn?|ijkuzMHYQ};d z>>3OVy3R()Z{cx#=#T*P2o0Z_ky=~~Yx!CL+ye?1yn31`I6Mw;)?rGC%T(P@rLZ@8 zQ&kmZ=?2V8v=a`FvRh$&p}&qaOQh}0>nTrNtsdSabS(VC03}4^%!RHXj4q*3hwvlC z?V7r85qd~Lm!L>Qj&>4lQMvv1o2lwxiTU#;O}nI?}!>Ec`hGx&KKD7@(Od$TNTsjA{ZfYh=baYeK%{ zGlmwrm>*$HxwM;-G0X1UI_Ui}hRveR&Q45U+nbh9+E0r?b#=FqQf^klm4Wxs1tchz z6m6@g_x+!@P(U~EcSVXyh5W6vALdAfFPOHc+3v3Uae z(q+T@96-r2>=+JU8z)r;I!ke#yhJ1$rinbhLtS6G1>ifjq^vU7XmGOm3h+yDgU;34 zK?;ITRh#_*B9e4E=Ma6haamPFX6>6l!YX5K=iZHjqhqmI78N+hkafj~UszM~X9$2L zshm~(_Xy2F**g%2WJ=S3It=KcaJXbS?ij>-GUX!?`AfcuAAV`7>LOs$UHJf~m+F=3 z_K&ruOa#90l^9t>ugX@#EDB$+LS_ha124N#akymhuAmR}s_EnL?5V#Ix`{;KZI&Gq z2cKbvTLL|FniURr(t$cKo`>I;0dRC*0Fg7iv@tr4ECBqz?Ef|){<$4cXKQY5&O`@E zoT&Am5w5VV8z_OB+zfheOB~lU>e`--Wt$r+F-@E(cObFWPX#3zaHX1jp!+ZQkeg5j ziDr}ZPAdBmhOmW=9%5O=Ttw*E+iB?QsL6y9D&(h8)Xx^9@6)Qp=j_CxoPiJ zZ7t{G;^JnwVn7p_iMi(UT)?Z)HF+JK<;1o&^!Cai3J{sgRZ|EYX}rm zrbddf3M=w%6Gr8;ptKAupKu(lvf-PKw~;@w)um-+tygCvW1#}_jt9F!U?!{8`wkXD zv0GWkyz)N03@p5k`@QP>CUwZapgfs~U8%&04+oSp1qB6H_N~-f&LgdebfE1wZ~c4T z?cVxK)JZGTb6}$31xEyf`f?tcTarV8FMoE?E~X)Oka!aFJoIUs!aDq=dw$1w55I zntE{KMfM>Ou)S=om#a)`Wz{R8++X4*a}i*LDJR#~R!bm}L$xyl115UUHm|(%Bi|!0 zL@L9Af<2sjvMs@*x>7*{oMvWD%{gX_q#o_P*t5$WU28A5l6KkO<|{5O9dJv2c?09T zy)0hs(JO4XFTVBc43NMoq^_k^=ojrIZT|tsO;#*WME-qe`V|-_C@8}!qK6pgGzh537`xwA7R*+>YchzHk}8u4bY=j}EcYah zn%dYTT`(=2Pk>=%eDnq~U*l<{?Hc1wR103};gg@Y=a-Ir3C?g_Pk8W%Y$ot zAd}*}W?_->^Ys~)+}?!empz<^OU)bcb-_!h4~Kuc8u7tm z;dAjkG9k-RiIaT%K$+zdeN?Q06lmP-YG?YK2+B21PEOk`qN;zy?t07q4)yWO5#^El zj;W<(LUuM!z6j~thZOsQKa`qZ8NT$gT_M~kH{$fo$iv?q3K6^I<8DTm`M3dC zRIN!`hmThS+0WI(@Y0cV`QXauqTFNr>h6uO^-rtAWpd>@N+62t9dx5&Uwj1x5(r|W zhk69WHiazk_3Kw09B&{WM;+`s?NP|xtau`kcpk5-qoYc~9;G}RgK}`B zrYr&{JYw26tG!22`Z?C+c1_%dN^*t$kK{%d_6}tIr?b?04L)$|68h@>9asbv09{?( zJ2M}Z^78VGz~f@(L7mi?gS}rJmJYrxc$MR^@@k3g=liIbVXyXLW4x%6lF-ZRp^ZNS z<>ci4{zx-?8?>n1sHnty>4%@ItLrO|-keb-zm6wDf5BS%)_as>h6gKdd}{(*zBXPs zabj^PTG$L{mxR#ey&fV#tf}FE!A6&5!7bHIOwI^n|2pYq$wO`4`LyS0CIuY+4IExD zxpUbUZUo|fN@hL(W%ut5l&@?6YXa>;2fkyX&bzM(mg=+jN|UzGTDGxz&xoUa19HF1kmo_Q=ivEH;{4TjfqUdw^KKUJ zZyIXY zI1^QG8aP8hh)PM_3T$#5+Xw?=Y4)jQdIjTatt$IwFyXRJ5`B5RCbKl`A;YKH7L4bF z1728(i&2$&{8;*Co<**5lvy3KyVh)b5>K^%E-{x4FflQ?0)78bE1CC+TUW-)uKW_0 z@8mo4$h3@f+4VCbl9Hzb11Ie85LGa*x$0L&E*cN=3$il$$Y;%mg@%Ue3!9pm6?j30 zHs{zb_~ple8300Bs8DRO(`{h6ddwA#j+>VUckKVbT4#9W1t>1B;W5aSBC1g$yQaUsdb&#o4dI{!1}X4eBt%e_q=OhsSNqvqm_3?D_>F; zQa-XU14;&pq1HXg?_4^bT<{w#G9<7*y;A8w!ajVgxi5nR6rP%0lMCLwfuWRZoO^sr zM@Pm7Il#yh#pcwaELmPvvL{*V>N=L9tRCbc(x|5ofPlYhq`NTm{ec;n=MZ}OtPr7A z7MG4fQ6%z;L33a6gGzYUB`)D1=vm+c9h0$g zuHi7}>}J3ML?py-onXxp!~Q0$`F>;L?5^36`rCu6Cd!?4O5hU7E;#LXw`@gI2y{w+q-9RGESm1QRFCELIO57(}^K^i?MufjAjC<{~o- zixYjHz&wE35KujAoz!h!tSNv~1KZ?K@7a8_!Bl`KRu3{fwOCwf9w}VFFkE+JrDum4R}k^xWJk zZ|bK-dWZeJUsVSRT7zCziWg-7_1jHh8|*MxQMg@WbBhrjh2mJ}*|@AG^9TxsD2(`6?huAzy-Ur=gi zZ=ZvT*awT?6EJK%r=_3A(y-4nK>6e3ebcL4mO*6o9w~pt4TD(E%Qqfs#6k}$}!JW?S*AyKiz8>HiXZ^eHufn zd-N0w=c@C-Xy37qkM}xm{p>EST9J~HlJ%Xqf;b=6isKNIar^`z5D42kl5=RN-0rU# zynfclHc(mfi?<57NHbMlE}R_k2?=G^ZaA7g^$^MwpP}M!n{um~cUDK~>4Gf}=$We> zThzyVNA0}+ zi#YJd{PJ?WwBtx+hZ_5pPz6D?jX<5(Nqc}bdlUJ|)#-3rumyI{e2|{bSx|7Nsb7*0 zPt*7LMD<(J&919jQejO(@87?lT3=-N1l+kV92J5nGLr|2{i1dzGC*l{q6P=Ly(G^1j>p(-0V~>h4}B>XIr8vQNEIi#>s- zsDo0Q8zQ_QIt4Es(}Vrfh%d_}M%r11z7kV$q{A`IbY!sb{CsV*yrI5+dt)f|(_5$3 zD;t^Wv`aKos+8tEdls;T2H{T=i&cK-J6X7@`D$}BprEi2esSXh*bvwx+`M3>gUY=1 z`x`4*q7pIjp2L!QTipn6Z*OCpGM|W298-t+phH#{*!Qs;?dBTeuk&Az*wv2QBV!Z- zUh%fKw@XOfI9)V&cQ{a1Ru*h7w1a{!?eE;u0++nJ7xwy{Ydd+B6hhvM^uww6`1tHo zyokEXH0Jc+@I*wmE(W!LpSb{$^XJbOj1-skuICG7LcKCtd&zarxgS)Bq{nC~(dfwE@CU2L5DmU6aT3FJq}N03X>VcKD@sO9HZsFu8%E z2}l|rW>0l`0(R2V_uPb4b534gThOGO`_J{n8DP%cQWM=+R%cy7UJr|irw7)<4o(45 z`lv))a`lv7y(JKX=*skfL@4I45|JaGF36D(_gC7ajSXanHIx$P6lAR1o2b zE-0dPa&p4Rh5ex&wc_ZU3ov7V+!qDpm(BS&R#t1kc@J6(-VjxWs^(_`P<$YGjRPD* zM6|kAaXLIazz;1gt&d6PEe=ng2QTo1@k^FOWG{mZYqqQoXQCGkG83`#G*@`->V;*X z;q%%~*q?)=voy){4kGZ=^ydHzP>(%9R_!;0hl#YWur~FRFX?85tulVm^=S|a6o6Ef zBRJgmJx#+o-Rs;;bRRPjp5if8a4|79)y4UbRJNAcaS4ISg - - - - - diff --git a/package.json b/package.json index 46a2f17..3439449 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "version": "0.0.1-dev", "publisher": "erdem-tuna", "license": "MIT", + "icon": "images/icon.png", "repository": { "type": "git", "url": "https://github.com/erdem-tuna/markdown-commenter"