aget-file-issue

star 11

File GitHub issues with private-first routing (L638). ALL agents route to {private-tracker}. Public issues require promotion with principal approval.

aget-framework By aget-framework schedule Updated 4/5/2026

name: aget-file-issue description: File GitHub issues with private-first routing (L638). ALL agents route to {private-tracker}. Public issues require promotion with principal approval. archetype: universal allowed-tools: - Bash - Read - Grep

/aget-file-issue

File issues with private-first routing governance (L638). ALL issues go to {private-tracker}. Public issues on aget-framework/aget require explicit promotion.

Purpose

Structured issue filing with:

  • Private-first routing: ALL agents → {private-tracker} (L638)
  • Content sanitization at promotion boundary only
  • Template selection (enhancement, bug, feature)

Input

/aget-file-issue <type> [title]
Type Description Template
enhancement Feature enhancement ENHANCEMENT_REQUEST
bug Bug report BUG_REPORT
feature New feature FEATURE_REQUEST

Execution

Step 1: Detect Agent Type

# Check for private fleet markers
if grep -q "gmelli\|private-" <<< "$PWD"; then
  AGENT_TYPE="private"
elif grep -q '"fleet".*"private"' .aget/version.json 2>/dev/null; then
  AGENT_TYPE="private"
elif git remote -v 2>/dev/null | grep -q "gmelli/"; then
  AGENT_TYPE="private"
else
  AGENT_TYPE="public"
fi

Step 2: Route to Private Tracker

ALL agents route to {private-tracker} (L638 private-first routing).

Agent type detection is retained for metadata tagging, but does NOT affect routing destination. Under the v2.0.0 policy, all agents — private fleet and public/remote — file to the private tracker.

Step 3: Validate

Check required fields:

  • Title present
  • Type valid (enhancement, bug, feature)
  • Body not empty (for bugs)

Step 4: File Issue

# ALL agents — private-first routing (L638)
gh issue create \
  --repo {private-tracker} \
  --title "$TITLE" \
  --body "$BODY" \
  --label "type:$TYPE"

Step 5: Report

Output:

Issue filed: <URL>
Destination: {private-tracker}
Type: <type>

Output Format

## Issue Filed

| Field | Value |
|-------|-------|
| URL | https://github.com/{private-tracker}/issues/456 |
| Destination | {private-tracker} |
| Type | enhancement |

Promotion to Public (Separate Workflow)

To make a private issue publicly visible on aget-framework/aget:

  1. Get principal approval (R-ISSUE-011)
  2. Run sanitization check (R-ISSUE-012):
    echo "issue body" | python3 .aget/patterns/github/sanitize_issue_content.py --check
    
  3. Create public issue with source reference (R-ISSUE-013)
  4. Verify no private identifiers in promoted content (R-ISSUE-014)

Sanitization Patterns (Promotion Boundary Only)

Pattern Replacement
private-*-aget [PRIVATE-AGENT]
private-*-AGET [PRIVATE-AGENT]
gmelli/* [INTERNAL-REPO]
\d+ agents? in fleet [N agents]
SESSION_\d{4}-\d{2}-\d{2} [SESSION]
FLEET-\w+-\d+ [PROJECT-ID]

Constraints

These are INVIOLABLE:

  • C1: NEVER file directly to aget-framework/aget — ALL issues go to {private-tracker}
  • C2: NEVER include private agent names in promoted public issues
  • C3: NEVER include fleet size disclosures in promoted public issues
  • C4: NEVER include internal repo references in promoted public issues
  • C5: ALWAYS route to {private-tracker} regardless of agent type
  • C6: ALWAYS validate destination before filing

Examples

Example 1: Private Agent Filing Enhancement

/aget-file-issue enhancement Add skill validation

Result: Files to {private-tracker} (no sanitization needed)

Example 2: Public Agent Filing Bug

/aget-file-issue bug Template fails on Windows

Result: Files to {private-tracker} (same destination — L638 private-first)

Example 3: Promoting a Private Issue

After principal approval, sanitized content filed to aget-framework/aget with reference to source issue in {private-tracker}.

Error Handling

Error Response
No gh CLI "Error: gh CLI not installed. Install via: brew install gh"
Not authenticated "Error: gh not authenticated. Run: gh auth login"
Missing title "Error: Title required. Usage: /aget-file-issue "</td> </tr> <tr> <td>Invalid type</td> <td>"Error: Invalid type. Use: enhancement, bug, feature"</td> </tr> </tbody></table> <h2>Related</h2> <ul> <li>L520: Issue Governance Gap</li> <li>L638: Private-First Issue Routing</li> <li>AGET_ISSUE_GOVERNANCE_SPEC v2.0.0: R-ISSUE-001 through R-ISSUE-014</li> <li>SKILL-040: aget-file-issue specification v1.1.0</li> <li>validate_issue_destination.py</li> <li>sanitize_issue_content.py</li> </ul> <h2>Traceability</h2> <table> <thead> <tr> <th>Link</th> <th>Reference</th> </tr> </thead> <tbody><tr> <td>Spec</td> <td>SKILL-040_aget-file-issue.yaml v1.1.0</td> </tr> <tr> <td>L-doc</td> <td>L520 (Issue Governance Gap), L638 (Private-First Routing)</td> </tr> <tr> <td>Governing Spec</td> <td>AGET_ISSUE_GOVERNANCE_SPEC v2.0.0</td> </tr> </tbody></table> <hr> <p><em>aget-file-issue v1.1.0</em> <em>Category: Governance</em> <em>Archetype: Universal</em></p> </article> </div> <!-- Right: Metadata & Command Sidebar --> <div class="w-full lg:w-80 shrink-0 flex flex-col gap-6" data-astro-cid-7zzsworf> <!-- Install Card --> <div class="p-6 rounded-xl bg-surface-container border border-border/80 flex flex-col gap-4 shadow-sm" data-astro-cid-7zzsworf> <span class="text-xs font-bold uppercase tracking-widest text-on-surface-variant/60 font-mono" data-astro-cid-7zzsworf>Install via CLI</span> <div class="flex flex-col gap-2" data-astro-cid-7zzsworf> <div id="detail-install-cmd" class="font-mono text-[11px] p-3 rounded-lg bg-black/40 border border-border select-all break-all text-primary font-bold leading-relaxed" data-astro-cid-7zzsworf> npx skills add https://github.com/aget-framework/aget --skill aget-file-issue </div> <button id="detail-copy-btn" class="w-full py-2.5 rounded-lg bg-primary hover:bg-primary-hover text-on-primary font-sans font-bold text-sm shadow transition-all active:scale-95 flex items-center justify-center gap-1.5" data-astro-cid-7zzsworf> <span class="material-symbols-outlined text-[16px]" data-astro-cid-7zzsworf>content_copy</span> <span data-astro-cid-7zzsworf>Copy Command</span> </button> </div> </div> <!-- Details & Stats Card --> <div class="p-6 rounded-xl bg-surface-container border border-border/80 flex flex-col gap-4 shadow-sm text-on-surface" data-astro-cid-7zzsworf> <span class="text-xs font-bold uppercase tracking-widest text-on-surface-variant/60 font-sans" data-astro-cid-7zzsworf>Repository Details</span> <div class="flex flex-col gap-3.5" data-astro-cid-7zzsworf> <div class="flex justify-between items-center text-sm" data-astro-cid-7zzsworf> <span class="text-on-surface-variant/70 flex items-center gap-1.5" data-astro-cid-7zzsworf> <span class="material-symbols-outlined text-[16px] text-on-surface-variant/60" data-astro-cid-7zzsworf>star</span> Stars </span> <span class="font-mono font-bold text-on-surface" data-astro-cid-7zzsworf>11</span> </div> <div class="flex justify-between items-center text-sm" data-astro-cid-7zzsworf> <span class="text-on-surface-variant/70 flex items-center gap-1.5" data-astro-cid-7zzsworf> <span class="material-symbols-outlined text-[16px] text-on-surface-variant/60" data-astro-cid-7zzsworf>call_split</span> Forks </span> <span class="font-mono font-bold text-on-surface" data-astro-cid-7zzsworf>0</span> </div> <div class="flex justify-between items-center text-sm" data-astro-cid-7zzsworf> <span class="text-on-surface-variant/70 flex items-center gap-1.5" data-astro-cid-7zzsworf> <span class="material-symbols-outlined text-[16px] text-on-surface-variant/60" data-astro-cid-7zzsworf>navigation</span> Branch </span> <span class="font-mono bg-surface border border-border px-2 py-0.5 rounded text-[11px] text-on-surface-variant" data-astro-cid-7zzsworf>main</span> </div> <div class="flex justify-between items-start text-sm" data-astro-cid-7zzsworf> <span class="text-on-surface-variant/70 flex items-center gap-1.5 mt-0.5" data-astro-cid-7zzsworf> <span class="material-symbols-outlined text-[16px] text-on-surface-variant/60" data-astro-cid-7zzsworf>article</span> Path </span> <span class="font-mono bg-surface border border-border px-2 py-0.5 rounded text-[11px] text-on-surface-variant truncate max-w-[150px]" title="SKILL.md" data-astro-cid-7zzsworf>SKILL.md</span> </div> </div> </div> <!-- Occupations Tag Card --> <!-- Related Creators Card --> <div class="p-6 rounded-xl bg-surface-container border border-border/80 flex flex-col gap-3 shadow-sm" data-astro-cid-7zzsworf> <span class="text-xs font-bold uppercase tracking-widest text-on-surface-variant/60 font-sans" data-astro-cid-7zzsworf>More from Creator</span> <div class="flex items-center gap-2" data-astro-cid-7zzsworf> <img class="w-8 h-8 rounded-full border border-border" src="https://avatars.githubusercontent.com/u/235936140?v=4" alt="aget-framework" onerror="this.src='https://avatars.githubusercontent.com/u/9919?v=4'" data-astro-cid-7zzsworf> <div class="flex flex-col min-w-0" data-astro-cid-7zzsworf> <span class="font-bold text-sm truncate text-on-surface" data-astro-cid-7zzsworf>aget-framework</span> <a href="/?creator=aget-framework" class="text-xs text-primary hover:underline font-semibold transition-all" data-astro-cid-7zzsworf>Explore all skills →</a> </div> </div> </div> </div> </div> </div> </div> <script> const copyBtn = document.getElementById("detail-copy-btn"); const installCmd = document.getElementById("detail-install-cmd"); if (copyBtn && installCmd) { copyBtn.addEventListener("click", () => { const cmd = installCmd.textContent.trim(); navigator.clipboard.writeText(cmd).then(() => { const originalText = copyBtn.innerHTML; copyBtn.innerHTML = ` <span class="material-symbols-outlined text-[16px]">check</span> <span>Copied!</span> `; copyBtn.style.background = "#10b981"; copyBtn.style.borderColor = "#10b981"; setTimeout(() => { copyBtn.innerHTML = originalText; copyBtn.style.background = ""; copyBtn.style.borderColor = ""; }, 1500); }); }); } </script> </div> <!-- Footer --> <footer class="border-t border-border bg-surface-container-low text-on-surface-variant py-8 px-gutter mt-16 rounded-xl"> <div class="max-w-container-max mx-auto flex flex-col md:flex-row justify-between items-center gap-6"> <div class="flex items-center gap-2"> <div class="w-6 h-6 rounded bg-primary bg-opacity-20 flex items-center justify-center"> <span class="material-symbols-outlined text-primary text-sm">code_blocks</span> </div> <span class="font-bold text-on-surface text-sm">SkillMD</span> </div> <div class="flex flex-wrap justify-center gap-6 text-sm"> <a href="/about" class="hover:text-primary transition-colors">About Us</a> <a href="/contact" class="hover:text-primary transition-colors">Contact Us</a> <a href="/privacy" class="hover:text-primary transition-colors">Privacy Policy</a> <a href="/terms" class="hover:text-primary transition-colors">Terms of Service</a> <a href="/support" class="hover:text-primary transition-colors">Support</a> </div> <div class="text-xs text-on-surface-variant/80"> © 2026 SkillMD. All rights reserved. </div> </div> </footer> </main> <!-- Script for Theme Toggle, Mobile Menu, and Sidebar Filter Redirection --> <script> // Theme setup const savedTheme = localStorage.getItem("theme") || "dark"; function applyTheme(theme) { document.documentElement.classList.remove("dark", "green", "dracula", "nord"); if (theme === "dark") { document.documentElement.classList.add("dark"); } else if (theme === "green") { document.documentElement.classList.add("dark", "green"); } else if (theme === "dracula") { document.documentElement.classList.add("dark", "dracula"); } else if (theme === "nord") { document.documentElement.classList.add("dark", "nord"); } document.documentElement.setAttribute("data-theme", theme); const themeMoon = document.getElementById("theme-moon"); const themeSun = document.getElementById("theme-sun"); const themeLeaf = document.getElementById("theme-leaf"); const themeDracula = document.getElementById("theme-dracula"); const themeNord = document.getElementById("theme-nord"); if (themeMoon && themeSun && themeLeaf && themeDracula && themeNord) { themeMoon.style.display = theme === "dark" ? "inline" : "none"; themeSun.style.display = theme === "light" ? "inline" : "none"; themeLeaf.style.display = theme === "green" ? "inline" : "none"; themeDracula.style.display = theme === "dracula" ? "inline" : "none"; themeNord.style.display = theme === "nord" ? "inline" : "none"; } } applyTheme(savedTheme); const themeToggleBtn = document.getElementById("theme-toggle-btn"); if (themeToggleBtn) { themeToggleBtn.addEventListener("click", () => { const currentTheme = document.documentElement.getAttribute("data-theme") || "dark"; let newTheme = "dark"; if (currentTheme === "dark") { newTheme = "light"; } else if (currentTheme === "light") { newTheme = "green"; } else if (currentTheme === "green") { newTheme = "dracula"; } else if (currentTheme === "dracula") { newTheme = "nord"; } else { newTheme = "dark"; } applyTheme(newTheme); localStorage.setItem("theme", newTheme); }); } // Mobile menu toggle and sidebar logic const mobileMenuToggle = document.getElementById("mobile-menu-toggle"); const sidebarMenu = document.getElementById("sidebar-menu"); const sidebarOverlay = document.getElementById("sidebar-overlay"); function isMobile() { return window.innerWidth < 768; // 768px is the 'md' breakpoint in Tailwind } function openSidebar() { if (sidebarMenu) { sidebarMenu.classList.remove("-translate-x-full"); } if (sidebarOverlay) { sidebarOverlay.classList.remove("hidden"); } } function closeSidebar() { if (sidebarMenu && isMobile()) { sidebarMenu.classList.add("-translate-x-full"); } if (sidebarOverlay) { sidebarOverlay.classList.add("hidden"); } } if (mobileMenuToggle && sidebarMenu) { mobileMenuToggle.addEventListener("click", (e) => { e.stopPropagation(); if (isMobile()) { const isClosed = sidebarMenu.classList.contains("-translate-x-full"); if (isClosed) { openSidebar(); } else { closeSidebar(); } } }); document.addEventListener("click", (e) => { if (isMobile()) { if (!sidebarMenu.contains(e.target) && !mobileMenuToggle.contains(e.target)) { closeSidebar(); } } }); if (sidebarOverlay) { sidebarOverlay.addEventListener("click", () => { if (isMobile()) { closeSidebar(); } }); } // Collapse sidebar when clicking a filter button, creator button, or nav item inside it sidebarMenu.addEventListener("click", (e) => { if (isMobile()) { const clickTarget = e.target.closest("button, a"); if (clickTarget) { closeSidebar(); } } }); // Sync sidebar state on window resize window.addEventListener("resize", () => { if (!isMobile()) { // Desktop: sidebar should be visible, no overlay if (sidebarMenu) { sidebarMenu.classList.remove("-translate-x-full"); } if (sidebarOverlay) { sidebarOverlay.classList.add("hidden"); } } else { // Mobile: start collapsed if (sidebarMenu) { sidebarMenu.classList.add("-translate-x-full"); } if (sidebarOverlay) { sidebarOverlay.classList.add("hidden"); } } }); } // If not on homepage, redirect on sidebar filter click const isHomepage = window.location.pathname === "/"; document.querySelectorAll("#occupation-filters .filter-btn").forEach(btn => { btn.addEventListener("click", (e) => { const occ = e.currentTarget.getAttribute("data-occupation"); if (!isHomepage) { window.location.href = occ ? `/?occupation=${encodeURIComponent(occ)}` : "/"; } }); }); document.querySelectorAll("#creator-filters .creator-btn").forEach(btn => { btn.addEventListener("click", (e) => { const creator = e.currentTarget.getAttribute("data-creator"); if (!isHomepage) { window.location.href = `/?creator=${encodeURIComponent(creator)}`; } }); }); </script> </body> </html>