Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
28ab0a6
feat: add telemetry instrumentation for release validation and metric…
ashleyshaw Aug 30, 2026
5584923
feat: add telemetry infrastructure (client, schemas, tests, docs)
ashleyshaw Aug 30, 2026
24cc5c1
fix: Move telemetry scripts to correct location and add governance rules
ashleyshaw Sep 1, 2026
1571791
fix: Complete script relocation and add comprehensive test coverage
ashleyshaw Sep 1, 2026
c7b3d2e
docs(telemetry): align script coverage target with policy
ashleyshaw Sep 1, 2026
bdaf116
Potential fix for pull request finding 'Unused variable, import, func…
ashleyshaw Sep 2, 2026
e2ba4a8
Potential fix for pull request finding 'Unused variable, import, func…
ashleyshaw Sep 2, 2026
01aca5c
Potential fix for pull request finding 'Unused variable, import, func…
ashleyshaw Sep 2, 2026
ca298cb
fix: Address CodeRabbit review findings for telemetry instrumentation PR
ashleyshaw Sep 2, 2026
b776863
Merge branch 'develop' into ashleyshaw-feat/release-telemetry-instrum…
ashleyshaw Sep 2, 2026
290b094
Potential fix for pull request finding 'Unused variable, import, func…
ashleyshaw Sep 2, 2026
90aaba1
fix: Apply CodeRabbit review feedback for telemetry instrumentation
ashleyshaw Sep 2, 2026
1c591ce
fix: Add workflow orchestrator to AGENTS.md quick reference table
ashleyshaw Sep 2, 2026
9ecb076
Fix CodeRabbit issues in PR #2581
coderabbitai[bot] Sep 2, 2026
663d7b9
Fix CodeRabbit issues in PR #2581
coderabbitai[bot] Sep 2, 2026
2eb1dfb
Merge branch 'develop' into ashleyshaw-feat/release-telemetry-instrum…
ashleyshaw Sep 3, 2026
7c4938d
Apply batched suggestions from code review
ashleyshaw Sep 3, 2026
8a1bd25
Apply batched suggestions from code review
ashleyshaw Sep 3, 2026
a9cbd29
fix: correct schema paths, coverage wording and orchestrator test con…
Copilot Sep 3, 2026
22eeb58
fix: align orchestrator tests with generateReports contract and strip…
Copilot Sep 3, 2026
9185d0d
test: restore module-level spies between orchestrator tests
Copilot Sep 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions .github/agentic-workflows/release.agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
import fs from "fs";
import path from "path";
import { execSync } from "child_process";
import {
createTelemetryClient,
} from "../../scripts/telemetry/telemetry-client.js";
import { EVENT_SCHEMAS } from "../../scripts/telemetry/event-schemas.js";

// ============================================================================
// Configuration
Expand Down Expand Up @@ -68,6 +72,12 @@ class ReleaseAgent {
this.workflowId = `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
this.log = [];
this.decisions = {};

// Initialize telemetry client
this.telemetry = createTelemetryClient({
eventSchemas: EVENT_SCHEMAS,
});
this.validationStartTime = null;
}

// ========================================================================
Expand Down Expand Up @@ -477,6 +487,21 @@ Respond with JSON:

async execute() {
try {
// Emit: release.validation.started
this.validationStartTime = Date.now();
this.telemetry.emit('release.validation.started', {
safe: {
component: 'release-agent',
version: '1.0.0',
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
trigger: this.dryRun ? 'dry-run' : 'manual'
},
restricted: {
repositoryName: this.getRepositoryName(),
changelogPath: CHANGELOG_FILE,
versionFile: VERSION_FILE
}
});

// Step 1: Initialize & Pre-flight
await this.initialize();

Expand All @@ -486,12 +511,43 @@ Respond with JSON:
// Steps 3-9: Safety Gates
const gatesPass = await this.runSafetyGates();
if (!gatesPass) {
// Emit: release.gate.failure
this.telemetry.emit('release.gate.failure', {
safe: {
component: 'release-agent',
gateName: 'safety-gates',
failureReason: 'One or more safety gates failed',
recoverable: false
},
restricted: {
repositoryName: this.getRepositoryName(),
changelogPath: CHANGELOG_FILE,
errorDetails: 'Safety gates validation failed'
}
});
throw new Error("❌ One or more safety gates failed. Release aborted.");
}

// Step 10: Report & Cleanup
await this.report();

// Emit: release.validation.completed
const validationDuration = Date.now() - this.validationStartTime;
this.telemetry.emit('release.validation.completed', {
safe: {
component: 'release-agent',
version: this.nextVersion,
validationDuration,
gatesPassed: 7,
warningCount: 0
},
restricted: {
repositoryName: this.getRepositoryName(),
changelogPath: CHANGELOG_FILE,
validationResults: JSON.stringify(this.decisions)
}
});

console.log("\n✅ MVP Workflow Complete!\n");
console.log("Next Steps:");
console.log("1. Review the generated report");
Expand All @@ -502,7 +558,39 @@ Respond with JSON:
} catch (error) {
console.error(`\n❌ Workflow Failed: ${error.message}\n`);
this.addLog(`Error: ${error.message}`);

// Emit: release.gate.failure for unexpected errors
if (!error.message.includes('safety gates')) {
this.telemetry.emit('release.gate.failure', {
safe: {
component: 'release-agent',
gateName: 'execution',
failureReason: 'Unexpected error during release',
recoverable: false
},
restricted: {
repositoryName: this.getRepositoryName(),
errorDetails: error.message,
stackTrace: error.stack
}
});
}

throw error;
} finally {
// Flush telemetry data
await this.telemetry.flush();
}
}

getRepositoryName() {
try {
// Get repository name from git remote
const remote = execSync('git remote get-url origin', { encoding: 'utf-8' }).trim();
const match = remote.match(/github\.com[:/](.+?)(?:\.git)?$/);
return match ? match[1] : 'unknown/unknown';
} catch (_e) {
return 'unknown/unknown';
}
}
}
Expand Down
22 changes: 22 additions & 0 deletions .github/instructions/file-organisation.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,32 @@ projects, or plugin bundles.
| `skills/` | Self-contained skills. | Each skill uses `SKILL.md`; assets stay inside the skill folder. |
| `workflows/` | Portable agentic workflows. | GitHub Actions stay in `.github/workflows/`. |

## Repository Scripts Location (CRITICAL)

**ALL scripts belong in `scripts/` at the root, NOT in `.github/scripts/`.**

| Script Type | Correct Location | WRONG Location |
| --- | --- | --- |
| Repository automation scripts | `scripts/automation/` | ❌ `.github/scripts/automation/` |
| Metrics collection scripts | `scripts/metrics/` | ❌ `.github/scripts/metrics/` |
| Telemetry scripts | `scripts/telemetry/` | ❌ `.github/scripts/telemetry/` |
| Release scripts | `scripts/release/` | ❌ `.github/scripts/release/` |
| Validation scripts | `scripts/validation/` | ❌ `.github/scripts/validation/` |
| Badge generation scripts | `scripts/badges/` | ❌ `.github/scripts/badges/` |
| **ONLY EXCEPTION:** Website browser scripts | `.github/website/src/scripts/` | ✅ Correct location for browser-specific code |
Comment thread
coderabbitai[bot] marked this conversation as resolved.

**Rules:**
- `.github/` is for GitHub-native governance files only (templates, workflows, configs)
- All executable scripts belong in `scripts/` with appropriate subfolders
- The ONLY exception is `.github/website/src/scripts/` for website browser code
- When in doubt, check existing script locations in `scripts/` directory
- Never create new scripts under `.github/scripts/` - this path should not exist

## File Type Mapping

| File Type | Canonical Location | Rule |
| --- | --- | --- |
| **Repository scripts** | `scripts/{category}/` | **ALWAYS root `scripts/`, never `.github/scripts/`** |
| Repo GitHub workflow | `.github/workflows/` | Keep executable GitHub Actions here. |
| Portable agentic workflow | `workflows/` | Use for tool-neutral AI processes. |
| Repo community-health file | `.github/` | Keep issue, PR, support, security, and governance files in place. |
Expand Down
56 changes: 50 additions & 6 deletions .github/website/src/scripts/theme-toggle.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,26 @@
Sun = currently dark mode (click to go light)
*/

// Simple browser telemetry client
const telemetry = {
emit(eventType, properties) {
const event = {
eventType,
timestamp: new Date().toISOString(),
environment: 'browser',
...properties
};

// Log to console in development
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
console.log('[Telemetry]', event);
}

// Could send to analytics endpoint in production
// fetch('/api/telemetry', { method: 'POST', body: JSON.stringify(event) });
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
}
};

const SVG_MOON = `<svg viewBox="0 0 24 24" width="18" height="18" fill="none"
stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
<path d="M20 14.5A8 8 0 0 1 9.5 4 8 8 0 1 0 20 14.5z"/>
Expand Down Expand Up @@ -33,14 +53,38 @@ function updateAllIcons() {
}

function toggleTheme() {
const next = getTheme() === "dark" ? "light" : "dark";
document.documentElement.setAttribute("data-theme", next);
document.documentElement.style.colorScheme = next;
const fromTheme = getTheme();
const toTheme = fromTheme === "dark" ? "light" : "dark";

document.documentElement.setAttribute("data-theme", toTheme);
document.documentElement.style.colorScheme = toTheme;

try {
localStorage.setItem("ag-theme", next);
} catch (_e) {
// Ignore storage failures in private/locked contexts.
localStorage.setItem("ag-theme", toTheme);

// Emit: website.theme.toggled
telemetry.emit('website.theme.toggled', {
safe: {
fromTheme,
toTheme,
method: 'user-click'
}
});
} catch (e) {
// Emit: website.theme.storage.failure
telemetry.emit('website.theme.storage.failure', {
safe: {
failureType: e.name || 'StorageError',
theme: toTheme,
fallbackUsed: false
},
restricted: {
storageError: e.message,
browserInfo: navigator.userAgent
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
}
});
}

updateAllIcons();
document.dispatchEvent(new CustomEvent("theme-changed"));
}
Expand Down
49 changes: 49 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,55 @@ references:

---

## Repository Scripts Organisation (CRITICAL)

**ALL repository scripts MUST be placed in `scripts/` at the root, NOT in `.github/scripts/`.**

### Correct Script Locations

```text
✅ scripts/automation/ - Automation and workflow scripts
✅ scripts/metrics/ - Metrics collection and analysis
✅ scripts/telemetry/ - Telemetry instrumentation
✅ scripts/release/ - Release preparation and validation
✅ scripts/validation/ - Validation and linting scripts
✅ scripts/badges/ - Badge generation scripts
✅ scripts/agents/ - Agent runner scripts
Comment thread
coderabbitai[bot] marked this conversation as resolved.

❌ .github/scripts/ - DO NOT CREATE - Reserved for GitHub governance only
```

### The ONLY Exception

`.github/website/src/scripts/` - Website browser-specific JavaScript that runs client-side

### Why This Matters

- `.github/` is for **GitHub-native governance files** (templates, workflows, configs)
- `scripts/` is for **executable code** that powers the repository
- Mixing these creates confusion about file ownership and purpose
- Import paths become inconsistent when scripts are in the wrong location

### Enforcement

When creating any new script:
1. **Check the script type**: Is it automation, metrics, telemetry, release, etc.?
2. **Place in correct subfolder**: `scripts/{category}/script-name.js`
3. **Never use `.github/scripts/`** - This directory should not exist for new work
4. **Update imports**: Ensure all imports use correct paths from `scripts/`

### Quick Reference

| You're Creating | Put It In | NOT In |
| --- | --- | --- |
| A telemetry client | `scripts/telemetry/` | ~~`.github/scripts/telemetry/`~~ |
| An automation script | `scripts/automation/` | ~~`.github/scripts/automation/`~~ |
| A metrics collector | `scripts/metrics/` | ~~`.github/scripts/metrics/`~~ |
| A release validator | `scripts/release/` | ~~`.github/scripts/release/`~~ |
| Website JS (browser) | `.github/website/src/scripts/` | ✅ Exception - correct location |

---

## Contribution Guidelines & Indexes

| Area | File Reference | Notes / Usage |
Expand Down
44 changes: 44 additions & 0 deletions instructions/file-organisation.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,54 @@ projects, or plugin bundles.
| `skills/` | Self-contained skills. | Each skill uses `SKILL.md`; assets stay inside the skill folder. |
| `workflows/` | Portable agentic workflows. | GitHub Actions stay in `.github/workflows/`. |

## Repository Scripts Organisation (CRITICAL)

**ALL repository scripts MUST be placed in `scripts/` at the root, NOT in `.github/scripts/`.**

### Correct Script Locations

```text
✅ scripts/automation/ - Automation and workflow scripts
✅ scripts/metrics/ - Metrics collection and analysis
✅ scripts/telemetry/ - Telemetry instrumentation
✅ scripts/release/ - Release preparation and validation
✅ scripts/validation/ - Validation and linting scripts
✅ scripts/badges/ - Badge generation scripts
✅ scripts/workflows/ - Workflow orchestration scripts

❌ .github/scripts/ - DO NOT CREATE - Reserved for GitHub governance only
```

### The ONLY Exception

Website browser-specific JavaScript that runs client-side (location varies by project structure).

### Why This Matters

- `.github/` is for **GitHub-native governance files** (templates, workflows, configs)
- `scripts/` is for **executable code** that powers the repository
- Mixing these creates confusion about file ownership and purpose
- Import paths become inconsistent when scripts are in the wrong location

### Enforcement

When creating any new script:
1. **Check the script type**: Is it automation, metrics, telemetry, release, etc.?
2. **Place in correct subfolder**: `scripts/{category}/script-name.js`
3. **Create tests**: `scripts/{category}/__tests__/script-name.test.js`
4. **Never use `.github/scripts/`** - This directory should not exist for new work
5. **Update imports**: Ensure all imports use correct paths from `scripts/`

### Test Coverage

ALL scripts in `scripts/` and subfolders require 100% test coverage. Place tests in `__tests__/` subdirectories alongside the code.

Comment thread
ashleyshaw marked this conversation as resolved.
## File Type Mapping

| File Type | Canonical Location | Rule |
| --- | --- | --- |
| **Repository scripts** | `scripts/{category}/` | **ALWAYS root `scripts/`, never `.github/scripts/`** |
| Repository script tests | `scripts/{category}/__tests__/` | **100% coverage required** |
| Repo GitHub workflow | `.github/workflows/` | Keep executable GitHub Actions here. |
| Portable agentic workflow | `workflows/` | Use for tool-neutral AI processes. |
| Repo community-health file | `.github/` | Keep issue, PR, support, security, and governance files in place. |
Expand Down
Loading
Loading