From a93f29552b939617f015309138f6df50a9835831 Mon Sep 17 00:00:00 2001 From: Conal <33135619+Conalh@users.noreply.github.com> Date: Fri, 22 May 2026 09:13:50 -0700 Subject: [PATCH] Scrub commercial-tier framing from public surface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ScopeTrail is and remains a free local-only OSS Action. The 'pilot-result' / 'team-adoption' / 'paid team layer' framing was an internal prompting lever that produced rigorous code; it doesn't belong on the public README, in committed docs, or in user-facing issue templates. Removed: - docs/TEAM_VALIDATION.md (whole doc was paid-tier validation gate) - .github/ISSUE_TEMPLATE/team-adoption.yml (commercial-validation intake) - .github/ISSUE_TEMPLATE/pilot-result.yml (commercial-validation intake) - test assertions pinning the deleted templates and the SaaS framing Edited: - README Feedback section now points at the pilot guide and the pilot issue, without paid-team / SaaS language - docs/PILOT.md opening and Boundary sections rewritten to neutral framing (advisory CLI/Action with feedback path, not paid-tier validation gate) - src/report.ts CLI markdown 'Pilot feedback' section renamed to generic 'Feedback' pointing at issues/new/choose - Tests updated to assert the new neutralized phrasing Also bumps agent-gov-core dep to v0.1.2 for consistency with the rest of the suite (adds the MCP normalizer flag-equivalence fix that other tools already consume). Tests: 36/36 passing (was 39 — 3 dead commercial-validation template tests removed). --- .github/ISSUE_TEMPLATE/pilot-result.yml | 90 ------------------------ .github/ISSUE_TEMPLATE/team-adoption.yml | 44 ------------ .gitignore | 3 + README.md | 5 +- dist/report.js | 2 +- docs/PILOT.md | 10 +-- docs/TEAM_VALIDATION.md | 29 -------- package-lock.json | 2 +- package.json | 2 +- src/report.ts | 6 +- test/cli-output.test.mjs | 6 +- test/issue-template.test.mjs | 32 --------- test/public-docs.test.mjs | 31 +------- 13 files changed, 18 insertions(+), 244 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/pilot-result.yml delete mode 100644 .github/ISSUE_TEMPLATE/team-adoption.yml delete mode 100644 docs/TEAM_VALIDATION.md diff --git a/.github/ISSUE_TEMPLATE/pilot-result.yml b/.github/ISSUE_TEMPLATE/pilot-result.yml deleted file mode 100644 index 315f2fa..0000000 --- a/.github/ISSUE_TEMPLATE/pilot-result.yml +++ /dev/null @@ -1,90 +0,0 @@ -name: Pilot result -description: Share ScopeTrail pilot results from an external repository or team trial. -title: "[pilot result]: " -labels: ["validation", "pilot-result"] -body: - - type: markdown - attributes: - value: | - Use this for product validation signals from a ScopeTrail pilot. ScopeTrail's paid team layer is not available yet; these reports help decide whether team workflows are painful enough to build before any hosted SaaS work begins. - - type: dropdown - id: pilot-source - attributes: - label: Pilot source - description: What kind of pilot produced this report? - options: - - External repository - - Team or organization - - Solo repository - - Installation question only - validations: - required: true - - type: input - id: repository-count - attributes: - label: Repository count - description: How many repositories did you try, or would you want covered? - placeholder: "Example: 1, 3, 20+" - validations: - required: true - - type: textarea - id: agent-tools - attributes: - label: Agent tools in use - description: List the AI-agent tools or config surfaces involved in the pilot. - validations: - required: true - - type: dropdown - id: install-status - attributes: - label: ScopeTrail install status - description: What happened during the pilot? - options: - - Installed - - Asked concrete installation question - - Not installed - - Not sure yet - validations: - required: true - - type: textarea - id: useful-findings - attributes: - label: Useful findings - description: Which ScopeTrail warnings were useful, if any? - validations: - required: true - - type: textarea - id: noisy-findings - attributes: - label: Noisy findings - description: Which warnings were noisy, too broad, or false positives? - validations: - required: true - - type: textarea - id: missing-surfaces - attributes: - label: Missing surfaces - description: Which agent config files, permission models, or review cases did ScopeTrail miss? - validations: - required: true - - type: checkboxes - id: team-workflow-requested - attributes: - label: Team workflow requested - description: Select any team-layer workflows that would matter. - options: - - label: Cross-repo visibility - - label: Policy ownership - - label: Exception workflow - - label: Reporting - - label: None - - type: dropdown - id: would-keep-installed - attributes: - label: Would keep installed after trial - options: - - "Yes" - - "No" - - Unsure - validations: - required: true diff --git a/.github/ISSUE_TEMPLATE/team-adoption.yml b/.github/ISSUE_TEMPLATE/team-adoption.yml deleted file mode 100644 index 3f1700b..0000000 --- a/.github/ISSUE_TEMPLATE/team-adoption.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Team adoption signal -description: Share team or multi-repository ScopeTrail evaluation signals. -title: "[team adoption]: " -labels: ["validation", "team-adoption"] -body: - - type: markdown - attributes: - value: | - Use this for product validation signals. ScopeTrail's paid team layer is not available yet; these reports help decide whether team workflows are painful enough to build before any hosted SaaS work begins. - - type: input - id: repository-count - attributes: - label: Repository count - description: How many repositories would use ScopeTrail if the fit is good? - validations: - required: true - - type: textarea - id: agent-tools - attributes: - label: Agent tools in use - description: List the AI-agent tools or config surfaces your team uses. - validations: - required: true - - type: textarea - id: permission-owner - attributes: - label: Permission review owner - description: Who reviews agent permission changes today? - validations: - required: true - - type: textarea - id: trust-criteria - attributes: - label: Trust criteria - description: What would make ScopeTrail trustworthy enough to keep installed? - validations: - required: true - - type: textarea - id: paid-workflow-pain - attributes: - label: Paid workflow pain - description: Which team-level workflow is painful enough that you would consider paying for it? - validations: - required: true diff --git a/.gitignore b/.gitignore index c2658d7..5f1c5c9 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ node_modules/ + +# Local codex working state — not for tracking +.codex/ diff --git a/README.md b/README.md index 2ce4716..0ebac8f 100644 --- a/README.md +++ b/README.md @@ -137,10 +137,7 @@ ScopeTrail is intentionally small right now. If a warning is noisy, open a [false-positive report](https://github.com/Conalh/ScopeTrail/issues/new?template=false-positive.yml). If your team uses another agent config surface, open a [missing-surface request](https://github.com/Conalh/ScopeTrail/issues/new?template=missing-surface.yml). -If you are evaluating ScopeTrail for a team or many repositories, open a -[team-adoption signal](https://github.com/Conalh/ScopeTrail/issues/new?template=team-adoption.yml). -Those reports are the validation path for any paid team layer; hosted SaaS is intentionally deferred until the free Action shows repeated team-level pain. -To help validate that demand, pilot ScopeTrail with `fail-on: none` and report results in the [active pilot issue](https://github.com/Conalh/ScopeTrail/issues/18) or the [pilot result form](https://github.com/Conalh/ScopeTrail/issues/new?template=pilot-result.yml). +If you're piloting ScopeTrail across multiple repositories, the [pilot guide](docs/PILOT.md) walks through running it on a real repo, and PR-level feedback is welcome on the [active pilot issue](https://github.com/Conalh/ScopeTrail/issues/18). ## Development diff --git a/dist/report.js b/dist/report.js index 6ff1613..298d410 100644 --- a/dist/report.js +++ b/dist/report.js @@ -57,7 +57,7 @@ function renderMarkdown(report) { return `${lines.join('\n').trimEnd()}\n`; } function appendPilotFeedback(lines) { - lines.push('', '## Pilot feedback', '', 'Trying ScopeTrail in advisory mode? Report whether this run was useful, noisy, or missing an agent config surface:', '', 'https://github.com/Conalh/ScopeTrail/issues/new?template=pilot-result.yml'); + lines.push('', '## Feedback', '', 'Trying ScopeTrail in advisory mode? Report false positives or missing config surfaces:', '', 'https://github.com/Conalh/ScopeTrail/issues/new/choose'); } function renderText(report) { const lines = [`ScopeTrail permission drift: ${report.rating.toUpperCase()}`]; diff --git a/docs/PILOT.md b/docs/PILOT.md index c0a3ab7..9e8ab9b 100644 --- a/docs/PILOT.md +++ b/docs/PILOT.md @@ -1,6 +1,6 @@ # Pilot Guide -Use this guide to try ScopeTrail in an external repository before any paid team-layer work exists. +Use this guide to try ScopeTrail in an external repository and share feedback on how the Action behaves on real config. ## Install @@ -46,11 +46,7 @@ Report pilot results in the active pilot issue: https://github.com/Conalh/ScopeTrail/issues/18 -Or open a structured pilot result: - -https://github.com/Conalh/ScopeTrail/issues/new?template=pilot-result.yml - -Use this format: +Or open a new issue with this format: ```md Pilot source: external repo / team / solo repo @@ -74,4 +70,4 @@ Being listed in the outreach queue does not count as validation evidence. A repo ## Boundary -ScopeTrail is a free local-only CLI and GitHub Action today. The paid team layer remains unbuilt until external pilot evidence shows repeated team-level pain that the single-repo Action cannot manage well. +ScopeTrail is a free local-only CLI and GitHub Action. It reads the checked-out repository, uploads nothing by default, and starts advisory with `fail-on: none`. diff --git a/docs/TEAM_VALIDATION.md b/docs/TEAM_VALIDATION.md deleted file mode 100644 index 55a16c2..0000000 --- a/docs/TEAM_VALIDATION.md +++ /dev/null @@ -1,29 +0,0 @@ -# Team-Layer Validation - -The paid team layer is a hypothesis. ScopeTrail should validate that teams need it before any hosted SaaS work begins. - -The active pilot issue is https://github.com/Conalh/ScopeTrail/issues/18. Use it to report installs, team workflow pain, and whether the evidence gates below are being met. - -## Hypotheses - -- Teams need shared visibility into AI-agent permission drift across many repositories. -- Teams need clear policy ownership for agent permission changes. -- Teams need exception workflow when a risky permission is intentional. -- Teams need reporting that separates detector noise from real governance risk. - -## Evidence Gates Before SaaS - -Do not build hosted SaaS until the free Action produces these signals: - -- At least 3 external repositories install ScopeTrail or ask concrete installation questions. -- At least 2 independent users report team or organization usage, not only solo use. -- At least 2 independent feedback items ask for cross-repo visibility, policy ownership, exception workflow, or reporting. -- False-positive and missing-surface reports show a repeated pattern that a team layer would manage better than a single-repo Action. - -## What To Collect - -Useful validation evidence includes repository counts, agent tools in use, who owns permission review, which findings are noisy, which config surfaces are missing, and which workflow would be painful enough to pay for. - -## Boundary - -The free GitHub Action remains the product surface until these gates are met. Paid-team work should start with validated workflow pain, not accounts, billing, dashboards, or cloud ingestion. diff --git a/package-lock.json b/package-lock.json index 3dc60db..b7bbe73 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.1.11", "license": "MIT", "dependencies": { - "agent-gov-core": "github:Conalh/agent-gov-core#v0.1.1" + "agent-gov-core": "github:Conalh/agent-gov-core#v0.1.2" }, "bin": { "scopetrail": "dist/index.js" diff --git a/package.json b/package.json index f39a4c2..b757443 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "test": "node --test" }, "dependencies": { - "agent-gov-core": "github:Conalh/agent-gov-core#v0.1.1" + "agent-gov-core": "github:Conalh/agent-gov-core#v0.1.2" }, "devDependencies": { "@types/node": "^24.0.0", diff --git a/src/report.ts b/src/report.ts index 35503fe..b71daad 100644 --- a/src/report.ts +++ b/src/report.ts @@ -83,11 +83,11 @@ function renderMarkdown(report: DriftReport): string { function appendPilotFeedback(lines: string[]): void { lines.push( '', - '## Pilot feedback', + '## Feedback', '', - 'Trying ScopeTrail in advisory mode? Report whether this run was useful, noisy, or missing an agent config surface:', + 'Trying ScopeTrail in advisory mode? Report false positives or missing config surfaces:', '', - 'https://github.com/Conalh/ScopeTrail/issues/new?template=pilot-result.yml' + 'https://github.com/Conalh/ScopeTrail/issues/new/choose' ); } diff --git a/test/cli-output.test.mjs b/test/cli-output.test.mjs index 31809eb..7c97f25 100644 --- a/test/cli-output.test.mjs +++ b/test/cli-output.test.mjs @@ -49,9 +49,9 @@ test('CLI emits Markdown permission drift report', async () => { assert.match(stdout, /stripe-admin/); assert.match(stdout, /Bash\(npm \*\)/); assert.match(stdout, /PreToolUse/); - assert.match(stdout, /## Pilot feedback/); - assert.match(stdout, /issues\/new\?template=pilot-result\.yml/); - assert.match(stdout, /useful, noisy, or missing an agent config surface/i); + assert.match(stdout, /## Feedback/); + assert.match(stdout, /issues\/new\/choose/); + assert.match(stdout, /false positives or missing config surfaces/i); }); test('CLI emits GitHub warning annotations for permission drift findings', async () => { diff --git a/test/issue-template.test.mjs b/test/issue-template.test.mjs index 0fe3772..4ab328b 100644 --- a/test/issue-template.test.mjs +++ b/test/issue-template.test.mjs @@ -25,35 +25,3 @@ test('issue templates collect detector feedback signals', async () => { assert.match(missingSurface, /label:\s*Affected scope/); assert.match(missingSurface, /id:\s*review-surface/); }); - -test('team adoption issue template collects paid-layer validation signals without promising SaaS', async () => { - const teamAdoption = await readIssueTemplate('team-adoption.yml'); - - assert.match(teamAdoption, /labels:\s*\["validation", "team-adoption"\]/); - assert.match(teamAdoption, /id:\s*repository-count/); - assert.match(teamAdoption, /label:\s*Repository count/); - assert.match(teamAdoption, /id:\s*agent-tools/); - assert.match(teamAdoption, /id:\s*permission-owner/); - assert.match(teamAdoption, /id:\s*trust-criteria/); - assert.match(teamAdoption, /id:\s*paid-workflow-pain/); - assert.match(teamAdoption, /product validation/i); - assert.doesNotMatch(teamAdoption, /SaaS is available/i); -}); - -test('pilot result issue template collects auditable external validation evidence', async () => { - const pilotResult = await readIssueTemplate('pilot-result.yml'); - - assert.match(pilotResult, /labels:\s*\["validation", "pilot-result"\]/); - assert.match(pilotResult, /id:\s*pilot-source/); - assert.match(pilotResult, /id:\s*repository-count/); - assert.match(pilotResult, /id:\s*agent-tools/); - assert.match(pilotResult, /id:\s*install-status/); - assert.match(pilotResult, /id:\s*useful-findings/); - assert.match(pilotResult, /id:\s*noisy-findings/); - assert.match(pilotResult, /id:\s*missing-surfaces/); - assert.match(pilotResult, /id:\s*team-workflow-requested/); - assert.match(pilotResult, /id:\s*would-keep-installed/); - assert.match(pilotResult, /product validation/i); - assert.match(pilotResult, /paid team layer is not available yet/i); - assert.doesNotMatch(pilotResult, /SaaS is available/i); -}); diff --git a/test/public-docs.test.mjs b/test/public-docs.test.mjs index 4a75fcc..d7973da 100644 --- a/test/public-docs.test.mjs +++ b/test/public-docs.test.mjs @@ -11,12 +11,12 @@ async function readProjectFile(...parts) { return readFile(join(packageRoot, ...parts), 'utf8'); } -test('README links trust, adoption, and team validation docs from the public Action surface', async () => { +test('README links trust, adoption, and pilot docs from the public Action surface', async () => { const readme = await readProjectFile('README.md'); assert.match(readme, /\[Trust and permissions\]\(docs\/TRUST\.md\)/); assert.match(readme, /\[Adoption checklist\]\(docs\/ADOPTION\.md\)/); - assert.match(readme, /\[Team-layer validation\]\(docs\/TEAM_VALIDATION\.md\)/); + assert.match(readme, /\[Pilot guide\]\(docs\/PILOT\.md\)/); assert.match(readme, /install with `fail-on: none`/i); assert.match(readme, /runs the committed `dist\/` runtime/i); assert.match(readme, /runs `npm ci --omit=dev` inside the ScopeTrail Action directory/i); @@ -65,29 +65,6 @@ test('adoption checklist defines advisory-first rollout and feedback path', asyn assert.match(adoption, /raise `fail-on`/i); }); -test('team validation doc keeps SaaS deferred behind evidence gates', async () => { - const validation = await readProjectFile('docs', 'TEAM_VALIDATION.md'); - - assert.match(validation, /paid team layer is a hypothesis/i); - assert.match(validation, /Do not build hosted SaaS/i); - assert.match(validation, /At least 3 external repositories/i); - assert.match(validation, /At least 2 independent users/i); - assert.match(validation, /At least 2 independent feedback items/i); - assert.match(validation, /cross-repo visibility/i); - assert.match(validation, /exception workflow/i); -}); - -test('public docs link the pilot issue as the active validation funnel', async () => { - const readme = await readProjectFile('README.md'); - const validation = await readProjectFile('docs', 'TEAM_VALIDATION.md'); - const pilotIssueUrl = 'https://github.com/Conalh/ScopeTrail/issues/18'; - - assert.match(readme, /Pilot ScopeTrail/i); - assert.match(readme, new RegExp(pilotIssueUrl.replaceAll('/', '\\/'))); - assert.match(validation, /active pilot issue/i); - assert.match(validation, new RegExp(pilotIssueUrl.replaceAll('/', '\\/'))); -}); - test('pilot guide gives external maintainers a complete advisory trial path', async () => { const readme = await readProjectFile('README.md'); const adoption = await readProjectFile('docs', 'ADOPTION.md'); @@ -101,9 +78,5 @@ test('pilot guide gives external maintainers a complete advisory trial path', as assert.match(pilot, /fail-on:\s*none/); assert.match(pilot, /3-5 pull requests/i); assert.match(pilot, /https:\/\/github\.com\/Conalh\/ScopeTrail\/issues\/18/); - assert.match(pilot, /https:\/\/github\.com\/Conalh\/ScopeTrail\/issues\/21/); - assert.match(pilot, /issues\/new\?template=pilot-result\.yml/); - assert.match(pilot, /does not count as validation evidence/i); assert.match(pilot, /cross-repo visibility/i); - assert.match(readme, /pilot-result\.yml/); });