@antoneeo/mkt-agentic-sdlc-skill 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,18 @@
1
+ # Changelog
2
+
3
+ ## 0.2.0 — 2026-07-09 (v1.0 hardening)
4
+
5
+ - **Deterministic doctrine gate**: `scripts/test_skill_invariants.py` asserts the load-bearing invariants (three guarantees, review red-flags R1/R11b/R15, elicitation rules, research URL rule, parseable template tokens, sales-led funnel guidance, support-file wiring). Fails on a real regression.
6
+ - **Opt-in behavioral eval layer**: `evals/run_behavioral.py` (zero-LLM driver) + 6 scenarios (triage/escalation, owned-facts elicitation, no-number-without-ledger, swap-test enforced, low-cost-trap flagged, no-guaranteed-success). Mirrors the sibling skill.
7
+ - **Contrast validation (B2B sales-led)**: second synthetic eval on a business unlike the first — the Vision Alignment / amendment discipline caught and held a deliberate vision-divergence (self-serve tier) instead of absorbing it.
8
+ - **Calibration from the contrast run**: sales-led/B2B funnel guidance (funnel output = qualified demos not closed customers; separate pipeline build-up table; closed-won lag) in `frameworks.md` + `templates.md`; B2B firmographic-ICP + buying-committee variant in `templates.md`.
9
+ - ENFORCEMENT.md §5/§6 updated to run both deterministic batteries + the behavioral layer.
10
+
11
+ ## 0.1.0 — 2026-07-09
12
+
13
+ Initial release.
14
+
15
+ - Operating contract `SKILL.md`: Marketing Values, Rule Zero engagement triage (E1/E2/E3/Spike), dual operating modes (Standalone `mkt_docs/`, Hybrid devPNT), E3 nine-phase SOSTAC workflow with user gates, adversarial review gates and mechanical validation.
16
+ - Support files: `frameworks.md` (framework selection guide), `elicitation.md` (question waves, only-facts-you-own rule), `research.md` (research playbook + evidence ledger discipline), `templates.md` (all artifact templates), `review.md` (CMO review discipline + marketing red flags), `ENFORCEMENT.md`.
17
+ - Mechanical validator `scripts/mkt_check.py`: `check`, `validate`, `ledger`, `budget`, `funnel`, `trace`, `index`.
18
+ - npm packaging: `mkt-sdlc-init` (project scaffold), `mkt-sdlc-install-skill` (multi-client skill install: Claude Code, Gemini CLI, Codex, Google Antigravity).
package/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # Marketing Agentic SDLC Skill
2
+
3
+ Evidence-First marketing planning protocol for AI coding agents (Claude Code, Gemini CLI, Google Antigravity, Codex). The sibling of [`@antoneeo/agentic-sdlc-skill`](https://www.npmjs.com/package/@antoneeo/agentic-sdlc-skill), transplanted from software engineering to marketing strategy.
4
+
5
+ ## What it does
6
+
7
+ Turns an AI agent into a disciplined marketing strategist that produces a professional, professionally-recognized marketing plan (SOSTAC structure) with three engineered guarantees:
8
+
9
+ 1. **Evidence ledger** — every market number is classified FACT / BENCHMARK / ASSUMPTION and carries an `[EV-nn]` reference to its source. No invented numbers.
10
+ 2. **Mechanical validator** (`mkt_check.py`) — budget sums, funnel math and the objective→tactic→KPI chain are checked mechanically, not rhetorically.
11
+ 3. **Adversarial CMO review** — an independent, fresh-context reviewer attacks the strategy before the user sees it (generic-positioning swap test, untraced claims, orphan tactics).
12
+
13
+ The agent asks the user only for facts the user uniquely owns (product, price, budget, capacity); everything else — market sizing, competitor analysis, channel benchmarks — is derived from real web research.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ npm i -g @antoneeo/mkt-agentic-sdlc-skill
19
+ mkt-sdlc-install-skill # copies the skill into every detected AI client
20
+ ```
21
+
22
+ Initialize a project:
23
+
24
+ ```bash
25
+ cd my-business-project
26
+ npx mkt-sdlc-init # creates mkt_docs/ + protocol pointers
27
+ ```
28
+
29
+ ## Engagement levels (Rule Zero)
30
+
31
+ | Level | Scope | Process |
32
+ |---|---|---|
33
+ | E1 Quick | single question / asset feedback | direct answer, sourced numbers |
34
+ | E2 Campaign | one campaign or channel plan | mini-brief + targeted research + campaign doc |
35
+ | E3 Full Plan | complete marketing plan | full SOSTAC workflow, 9 phases, all gates |
36
+ | Research Spike | time-boxed market question | `mkt_docs/spikes/RESEARCH_[topic].md` |
37
+
38
+ ## Modes
39
+
40
+ - **Standalone** — everything on the filesystem under `mkt_docs/`.
41
+ - **Hybrid with devPNT** — plans and strategy artifacts governed as versioned devPNT documents (MKT-VISION, ICP/Personas, Threat Map, Strategy, Tactical Plan, Measurement Plan), with proposal/approval workflow and independent review gates.
42
+
43
+ ## License
44
+
45
+ MIT — Antonio Pinto
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "mkt-agentic-sdlc",
3
+ "version": "0.2.0",
4
+ "description": "Evidence-First marketing planning protocol with engagement triage, SOSTAC workflow, evidence ledger and optional devPNT integration.",
5
+ "author": "Antonio Pinto (https://github.com/Antoneeo)"
6
+ }
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@antoneeo/mkt-agentic-sdlc-skill",
3
+ "version": "0.2.0",
4
+ "description": "Evidence-First marketing planning protocol for Claude Code, Gemini CLI, Google Antigravity and Codex: engagement triage, SOSTAC workflow, evidence ledger, mechanical validator and optional devPNT integration.",
5
+ "keywords": [
6
+ "claude-code",
7
+ "claude-skill",
8
+ "gemini-cli",
9
+ "skill",
10
+ "marketing",
11
+ "marketing-plan",
12
+ "sostac",
13
+ "ai-agent"
14
+ ],
15
+ "author": "Antonio Pinto (https://github.com/Antoneeo)",
16
+ "license": "MIT",
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "bin": {
21
+ "mkt-sdlc-init": "scripts/init.js",
22
+ "mkt-sdlc-install-skill": "scripts/postinstall.js"
23
+ },
24
+ "scripts": {
25
+ "postinstall": "node scripts/postinstall.js",
26
+ "preuninstall": "node scripts/preuninstall.js"
27
+ },
28
+ "files": [
29
+ "skills/mkt-agentic-sdlc/SKILL.md",
30
+ "skills/mkt-agentic-sdlc/frameworks.md",
31
+ "skills/mkt-agentic-sdlc/elicitation.md",
32
+ "skills/mkt-agentic-sdlc/research.md",
33
+ "skills/mkt-agentic-sdlc/templates.md",
34
+ "skills/mkt-agentic-sdlc/review.md",
35
+ "skills/mkt-agentic-sdlc/ENFORCEMENT.md",
36
+ "skills/mkt-agentic-sdlc/scripts/mkt_check.py",
37
+ "gemini-extension.json",
38
+ "README.md",
39
+ "CHANGELOG.md",
40
+ "scripts/lib.js",
41
+ "scripts/init.js",
42
+ "scripts/postinstall.js",
43
+ "scripts/preuninstall.js"
44
+ ]
45
+ }
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { execSync } = require('child_process');
6
+ const { SKILL_SOURCE, CLIENTS, clientDetected, loadTemplates, templateFor } = require('./lib');
7
+
8
+ const cwd = process.cwd();
9
+
10
+ // 1. Directory layout (canonical mkt_docs structure)
11
+ const directories = [
12
+ 'mkt_docs',
13
+ 'mkt_docs/vision',
14
+ 'mkt_docs/research',
15
+ 'mkt_docs/strategy',
16
+ 'mkt_docs/tactics',
17
+ 'mkt_docs/deliverables',
18
+ 'mkt_docs/audit',
19
+ 'mkt_docs/spikes',
20
+ ].map((d) => path.join(cwd, d));
21
+
22
+ // 2. Project protocol (thin pointer — the operating contract is the skill).
23
+ // Deliberately short: duplicating the skill's rules here made them drift.
24
+ const protocolContent = `# Marketing Agentic SDLC — Project Protocol (pointer)
25
+
26
+ This project follows the Marketing Agentic SDLC Evidence-First process. The full
27
+ operating contract is the \`mkt-agentic-sdlc\` skill (installed in your agent's
28
+ skills directory); this file is only the minimal always-on pointer.
29
+
30
+ ## Rule Zero — Triage every request
31
+ - E1 Quick: single question or asset feedback (positioning opinion, copy critique). Answer directly; numbers still need a source.
32
+ - E2 Campaign: single-campaign or single-channel plan. Light path: mini-brief + targeted research + campaign document.
33
+ - E3 Full Plan: complete marketing plan. Full SOSTAC workflow via the skill: Discovery -> Research -> Situation -> Objectives -> Strategy -> Tactics -> Action -> Control -> Packaging.
34
+ - Research Spike: time-boxed market question; outcome in \`mkt_docs/spikes/RESEARCH_[topic].md\`.
35
+ - When in doubt, pick the higher level. Declare the chosen level when starting.
36
+
37
+ ## The three non-negotiables
38
+ 1. Evidence ledger: every market number carries an [EV-nn] reference (FACT / BENCHMARK / ASSUMPTION). No invented numbers, ever.
39
+ 2. Ask only what the user owns: facts come from the user, analysis comes from research. Never ask the user to do the analysis.
40
+ 3. Internal consistency: budget sums, funnel math and the objective->tactic->KPI chain are validated mechanically before delivery.
41
+
42
+ ## Where things live
43
+ - Vision (gate for E3): \`mkt_docs/vision/MKT_VISION.md\` — \`Status: DRAFT\` informs, \`Status: APPROVED\` binds.
44
+ - Evidence: \`mkt_docs/research/evidence_ledger.md\` (the single source for every number).
45
+ - Strategy artifacts: \`mkt_docs/strategy/\`; tactical artifacts: \`mkt_docs/tactics/\`; final deliverables: \`mkt_docs/deliverables/\`.
46
+ - Must-reads: \`mkt_docs/README.md\`; full generated manifest: \`mkt_docs/INDEX.md\`.
47
+ - If devPNT is available for this project, its M-VISION / plans / governed artifacts take over (Hybrid mode — see the skill).
48
+
49
+ ## Closure gate
50
+ Deliverables ship only after \`python <skill_dir>/scripts/mkt_check.py check\` is
51
+ CLEAN (where the validator is adopted) and the CMO review passed.
52
+
53
+ If the mkt-agentic-sdlc skill is not available in this client, ask the user to install it:
54
+ \`npm i -g @antoneeo/mkt-agentic-sdlc-skill && mkt-sdlc-install-skill\`
55
+ `;
56
+
57
+ console.log('🚀 Initializing Marketing Agentic SDLC workflow...');
58
+
59
+ // 3. Load templates from the single source (skill's templates.md)
60
+ let sections;
61
+ try {
62
+ sections = loadTemplates();
63
+ } catch (err) {
64
+ console.error(`❌ Cannot load templates: ${err.message}`);
65
+ process.exit(1);
66
+ }
67
+
68
+ let seedFiles;
69
+ try {
70
+ seedFiles = [
71
+ ['mkt_docs/README.md', templateFor(sections, 'mkt_docs/README.md')],
72
+ ['mkt_docs/vision/MKT_VISION.md', templateFor(sections, 'MKT_VISION.md')],
73
+ ['mkt_docs/vision/principles.md', templateFor(sections, 'principles.md')],
74
+ ['mkt_docs/research/evidence_ledger.md', templateFor(sections, 'evidence_ledger.md')],
75
+ // NOTE: INDEX.md is NOT seeded — it is generated by `mkt_check.py index`
76
+ // and would immediately fail validate.
77
+ ];
78
+ } catch (err) {
79
+ console.error(`❌ ${err.message}`);
80
+ process.exit(1);
81
+ }
82
+
83
+ // 4. Create directories
84
+ directories.forEach((dir) => {
85
+ if (!fs.existsSync(dir)) {
86
+ fs.mkdirSync(dir, { recursive: true });
87
+ console.log(`📁 Created directory: ${path.relative(cwd, dir)}`);
88
+ }
89
+ });
90
+
91
+ // 5. Write seed files (never overwrite)
92
+ const writeIfNotExists = (relPath, content, description) => {
93
+ const filePath = path.join(cwd, relPath);
94
+ if (!fs.existsSync(filePath)) {
95
+ fs.writeFileSync(filePath, content, 'utf8');
96
+ console.log(`📄 Created file: ${relPath}${description ? ` (${description})` : ''}`);
97
+ return true;
98
+ }
99
+ console.log(`⏭️ Skipped: ${relPath} already exists.`);
100
+ return false;
101
+ };
102
+
103
+ seedFiles.forEach(([relPath, content]) => writeIfNotExists(relPath, content));
104
+
105
+ // 6. Client discovery and protocol pointers
106
+ console.log('\n--- Environment Analysis ---');
107
+
108
+ const protocolFiles = {
109
+ claude: 'CLAUDE.md',
110
+ gemini: 'GEMINI.md',
111
+ codex: 'AGENTS.md',
112
+ antigravity: 'AGENTS.md', // Antigravity CLI reads AGENTS.md; single protocolContent reused.
113
+ };
114
+
115
+ for (const client of CLIENTS) {
116
+ if (clientDetected(client)) {
117
+ console.log(`✅ ${client.label} detected.`);
118
+ writeIfNotExists(protocolFiles[client.key], protocolContent, `${client.label} protocol pointer`);
119
+ }
120
+ }
121
+
122
+ // Cursor/Windsurf (always recommended)
123
+ writeIfNotExists('.cursorrules', protocolContent, 'Cursor/Windsurf rules');
124
+
125
+ // 7. Generate mkt_docs/INDEX.md so the very first `validate` is already clean.
126
+ // The manifest is generated, never seeded: delegate to the validator if Python is available.
127
+ const validator = path.join(SKILL_SOURCE, 'scripts', 'mkt_check.py');
128
+ let indexed = false;
129
+ for (const py of ['python', 'python3', 'py']) {
130
+ try {
131
+ execSync(`${py} "${validator}" index --root "${cwd}"`, { stdio: 'ignore' });
132
+ console.log('📇 Generated mkt_docs/INDEX.md (document manifest).');
133
+ indexed = true;
134
+ break;
135
+ } catch (e) { /* try the next interpreter */ }
136
+ }
137
+ if (!indexed) {
138
+ console.log('ℹ️ Python not found: generate the manifest later with '
139
+ + '"python <skill_dir>/scripts/mkt_check.py index" (validate reports it until then).');
140
+ }
141
+
142
+ console.log('\n✅ Setup completed successfully!');
143
+ console.log('💡 Next steps:');
144
+ console.log(' 1. Make sure the mkt-agentic-sdlc skill is installed (mkt-sdlc-install-skill).');
145
+ console.log(' 2. Restart/open the project in your AI client so it reads the protocol pointer.');
146
+ console.log(' 3. Start an E3 engagement: the skill runs Discovery (its questions) before anything else.');
package/scripts/lib.js ADDED
@@ -0,0 +1,170 @@
1
+ // Shared helpers for the Marketing Agentic SDLC npm scripts (init / postinstall / preuninstall).
2
+ // Single source for client detection and skill-target paths: init and postinstall
3
+ // must never disagree on what "Claude Code is installed" means.
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+ const os = require('os');
8
+ const { execSync } = require('child_process');
9
+
10
+ const PACKAGE_ROOT = path.resolve(__dirname, '..');
11
+ const SKILL_SOURCE = path.join(PACKAGE_ROOT, 'skills', 'mkt-agentic-sdlc');
12
+ const TEMPLATES_PATH = path.join(SKILL_SOURCE, 'templates.md');
13
+ const SKILL_DIR_NAME = 'mkt-agentic-sdlc';
14
+
15
+ // One entry per supported AI client. `home` may be overridden by an env var
16
+ // (Claude Desktop / portable installs); presence of the home dir counts as
17
+ // detection even when the CLI is not on PATH.
18
+ const CLIENTS = [
19
+ {
20
+ key: 'claude',
21
+ label: 'Claude Code',
22
+ cmd: 'claude',
23
+ home: process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), '.claude'),
24
+ envVar: 'CLAUDE_CONFIG_DIR',
25
+ reload: 'Restart Claude Code to load it. Invoke via Skill tool as "mkt-agentic-sdlc".',
26
+ },
27
+ {
28
+ key: 'gemini',
29
+ label: 'Gemini CLI',
30
+ cmd: 'gemini',
31
+ home: process.env.GEMINI_HOME || path.join(os.homedir(), '.gemini'),
32
+ envVar: 'GEMINI_HOME',
33
+ reload: 'Run "gemini skills reload" or restart Gemini CLI to load it.',
34
+ },
35
+ {
36
+ key: 'codex',
37
+ label: 'Codex AI',
38
+ cmd: 'codex',
39
+ home: process.env.CODEX_HOME || path.join(os.homedir(), '.codex'),
40
+ envVar: 'CODEX_HOME',
41
+ reload: 'Restart Codex to load it. Invoke it as "$mkt-agentic-sdlc" or by asking for the Marketing SDLC skill.',
42
+ },
43
+ {
44
+ // Google Antigravity 2.0 discovers global agent skills under
45
+ // ~/.gemini/config/skills/ -- the SAME home the legacy Gemini CLI claims.
46
+ // To avoid a shared-home double-install, this entry sets:
47
+ // - skillsSubdir 'config/skills': distinct target from gemini's ~/.gemini/skills
48
+ // - homeMarker on ~/.gemini/config/skills: detection never fires on bare
49
+ // ~/.gemini (which every Antigravity user has); only the Antigravity skills
50
+ // dir, the `agy` CLI, or ANTIGRAVITY_HOME count as "Antigravity installed".
51
+ key: 'antigravity',
52
+ label: 'Google Antigravity',
53
+ cmd: 'agy',
54
+ home: process.env.ANTIGRAVITY_HOME || path.join(os.homedir(), '.gemini'),
55
+ envVar: 'ANTIGRAVITY_HOME',
56
+ skillsSubdir: 'config/skills',
57
+ homeMarker: path.join(
58
+ process.env.ANTIGRAVITY_HOME || path.join(os.homedir(), '.gemini'),
59
+ 'config',
60
+ 'skills',
61
+ ),
62
+ reload: 'Restart Antigravity, or run "agy skills reload", to load it. Invoke by asking for the Marketing SDLC skill.',
63
+ },
64
+ ];
65
+
66
+ function commandExists(cmd) {
67
+ try {
68
+ execSync(`${cmd} --version`, { stdio: 'ignore' });
69
+ return true;
70
+ } catch (e) {
71
+ return false;
72
+ }
73
+ }
74
+
75
+ function clientDetected(client) {
76
+ // An entry may override the fs-existence probe with a `homeMarker` (a more
77
+ // specific path than the bare home) so two clients sharing a home dir do not
78
+ // both fire on its mere existence. Entries without a marker check `home`
79
+ // exactly as before (backward-compatible).
80
+ const homePathToCheck = client.homeMarker || client.home;
81
+ return commandExists(client.cmd)
82
+ || Boolean(process.env[client.envVar])
83
+ || fs.existsSync(homePathToCheck);
84
+ }
85
+
86
+ function skillTarget(client) {
87
+ // An entry may override the default `skills` sub-path with `skillsSubdir`
88
+ // (split on '/' to keep cross-platform path.join correctness). Entries
89
+ // without it resolve to <home>/skills/mkt-agentic-sdlc exactly as before.
90
+ const subdir = client.skillsSubdir ? client.skillsSubdir.split('/') : ['skills'];
91
+ return path.join(client.home, ...subdir, SKILL_DIR_NAME);
92
+ }
93
+
94
+ function copyRecursive(src, dest) {
95
+ if (typeof fs.cpSync === 'function') {
96
+ fs.cpSync(src, dest, { recursive: true, force: true });
97
+ return;
98
+ }
99
+ // Fallback for Node < 16.7
100
+ if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
101
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
102
+ const s = path.join(src, entry.name);
103
+ const d = path.join(dest, entry.name);
104
+ if (entry.isDirectory()) copyRecursive(s, d);
105
+ else fs.copyFileSync(s, d);
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Parse templates.md into { headingText: [fencedBlock, ...] }.
111
+ * Templates are single-sourced there: the init script must extract them
112
+ * instead of carrying its own inline copies (which historically drifted).
113
+ */
114
+ function loadTemplates() {
115
+ const text = fs.readFileSync(TEMPLATES_PATH, 'utf8');
116
+ const lines = text.split(/\r?\n/);
117
+ const sections = {};
118
+ let heading = null;
119
+ let block = null;
120
+ for (const line of lines) {
121
+ const h = line.match(/^##\s+(.*)$/);
122
+ if (h && block === null) {
123
+ heading = h[1].trim();
124
+ sections[heading] = sections[heading] || [];
125
+ continue;
126
+ }
127
+ if (/^```/.test(line)) {
128
+ if (block === null) {
129
+ block = [];
130
+ } else {
131
+ if (heading) sections[heading].push(block.join('\n') + '\n');
132
+ block = null;
133
+ }
134
+ continue;
135
+ }
136
+ if (block !== null) block.push(line);
137
+ }
138
+ return sections;
139
+ }
140
+
141
+ /**
142
+ * Return the Nth fenced block of the section whose heading contains `needle`.
143
+ * Throws with a clear message when missing: writing a wrong or empty
144
+ * boilerplate silently would be worse than failing the init.
145
+ */
146
+ function templateFor(sections, needle, index = 0) {
147
+ const heading = Object.keys(sections).find((h) => h.includes(needle));
148
+ const blocks = heading ? sections[heading] : undefined;
149
+ if (!blocks || !blocks[index]) {
150
+ throw new Error(
151
+ `Template section containing "${needle}" (block ${index}) not found in ${TEMPLATES_PATH}. ` +
152
+ 'The package is corrupted or templates.md was restructured: fix templates.md, do not improvise content.'
153
+ );
154
+ }
155
+ return blocks[index];
156
+ }
157
+
158
+ module.exports = {
159
+ PACKAGE_ROOT,
160
+ SKILL_SOURCE,
161
+ TEMPLATES_PATH,
162
+ SKILL_DIR_NAME,
163
+ CLIENTS,
164
+ commandExists,
165
+ clientDetected,
166
+ skillTarget,
167
+ copyRecursive,
168
+ loadTemplates,
169
+ templateFor,
170
+ };
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const { SKILL_SOURCE, CLIENTS, clientDetected, skillTarget, copyRecursive } = require('./lib');
5
+
6
+ function installSkill(client) {
7
+ if (!fs.existsSync(SKILL_SOURCE)) {
8
+ console.log(`⚠️ Skill source not found at ${SKILL_SOURCE}; skipping ${client.label} install.`);
9
+ return false;
10
+ }
11
+ const target = skillTarget(client);
12
+ try {
13
+ fs.mkdirSync(target, { recursive: true });
14
+ copyRecursive(SKILL_SOURCE, target);
15
+ console.log(`📦 Installed ${client.label} skill at: ${target}`);
16
+ console.log(` ${client.reload}`);
17
+ return true;
18
+ } catch (err) {
19
+ console.log(`⚠️ Failed to install ${client.label} skill: ${err.message}`);
20
+ console.log(` Manual install: copy "${SKILL_SOURCE}" to "${target}".`);
21
+ return false;
22
+ }
23
+ }
24
+
25
+ console.log('\n--- Marketing Agentic SDLC Skill Discovery ---');
26
+
27
+ let detected = false;
28
+ for (const client of CLIENTS) {
29
+ if (clientDetected(client)) {
30
+ console.log(`✅ Detected: ${client.label}`);
31
+ detected = true;
32
+ installSkill(client);
33
+ }
34
+ }
35
+
36
+ if (!detected) {
37
+ console.log('ℹ️ No specific AI CLI detected globally, but you can still use the skill.');
38
+ }
39
+
40
+ console.log('\nTo initialize a project with the marketing protocol, run:');
41
+ console.log('👉 npx mkt-sdlc-init');
42
+ console.log('------------------------------------\n');
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const { CLIENTS, skillTarget } = require('./lib');
5
+
6
+ function removeSkill(client) {
7
+ const target = skillTarget(client);
8
+ if (!fs.existsSync(target)) return;
9
+ try {
10
+ fs.rmSync(target, { recursive: true, force: true });
11
+ console.log(`🧹 Removed ${client.label} skill at: ${target}`);
12
+ } catch (err) {
13
+ console.log(`⚠️ Could not remove ${target}: ${err.message}`);
14
+ }
15
+ }
16
+
17
+ CLIENTS.forEach(removeSkill);
@@ -0,0 +1,82 @@
1
+ # Mechanical Enforcement (optional)
2
+
3
+ The prompt is not enforcement. Where the project needs repeatable guarantees,
4
+ wire the validator into the workflow. Everything here is optional: the skill
5
+ must stay usable without Python or hooks, declaring what it cannot verify.
6
+
7
+ ## 1. Pre-delivery gate (the one that matters)
8
+
9
+ Before presenting any E2/E3 deliverable as finished:
10
+
11
+ ```bash
12
+ python <skill_dir>/scripts/mkt_check.py check --root <project_root>
13
+ ```
14
+
15
+ `check` runs `validate + ledger + budget + funnel + trace`. Errors block the
16
+ delivery; warnings ship only with explicit user acknowledgment. This is the
17
+ marketing twin of "tests must pass before DONE".
18
+
19
+ ## 2. CI
20
+
21
+ For a marketing repo kept under version control:
22
+
23
+ ```yaml
24
+ # e.g. GitHub Actions step
25
+ - run: python skills/mkt-agentic-sdlc/scripts/mkt_check.py validate --strict --root .
26
+ - run: python skills/mkt-agentic-sdlc/scripts/mkt_check.py ledger --root .
27
+ ```
28
+
29
+ Use `--strict` only in CI: locally, warnings are guidance; in CI they are
30
+ drift.
31
+
32
+ ## 3. Git hook (pre-commit)
33
+
34
+ ```bash
35
+ #!/bin/sh
36
+ python skills/mkt-agentic-sdlc/scripts/mkt_check.py check --root . || {
37
+ echo "mkt_check failed — fix the plan before committing."; exit 1; }
38
+ ```
39
+
40
+ ## 4. What the validator cannot check (honesty list)
41
+
42
+ - Whether a BENCHMARK's URL actually supports the claimed number (it checks
43
+ presence, not truth) — that is the review's R2/R3 territory.
44
+ - Whether the positioning passes the swap test (R1) — adversarial review only.
45
+ - Whether kill/scale thresholds are sensible — review, with ledger evidence.
46
+ - Whether the deliverable language matches the target market — Discovery
47
+ record + review.
48
+
49
+ Declare these residuals when reporting a CLEAN check: mechanical CLEAN plus
50
+ review PASS is the full gate, neither alone.
51
+
52
+ ## 5. Skill self-test (skill development only)
53
+
54
+ Two deterministic batteries — the release gate. Run both:
55
+
56
+ ```bash
57
+ python -m unittest discover -s skills/mkt-agentic-sdlc/scripts -p "test_*.py"
58
+ ```
59
+
60
+ - `test_mkt_check.py` — the validator itself; gate for changes to
61
+ `mkt_check.py` or to the parseable template formats in `templates.md` (the
62
+ two must move together: a template format change without a validator change
63
+ is drift).
64
+ - `test_skill_invariants.py` — the doctrine invariants: asserts the
65
+ load-bearing rules are still present in `SKILL.md` and the support files
66
+ (the three guarantees, the review red-flags R1/R11b/R15, the elicitation
67
+ rules, the research URL rule, the parseable template tokens, every support
68
+ file wired). Fails when a rule is deleted or weakened — a real regression,
69
+ never flakiness.
70
+
71
+ ## 6. Behavioral eval layer (opt-in, non-gating)
72
+
73
+ ```bash
74
+ python skills/mkt-agentic-sdlc/evals/run_behavioral.py skills/mkt-agentic-sdlc/evals/scenarios/<scenario>.md
75
+ ```
76
+
77
+ Declarative scenarios exercise real agent *adherence* (elicitation asks only
78
+ owned facts, no number without a ledger entry, swap-test enforced, low-cost
79
+ trap flagged, E2-without-strategy escalates, no guaranteed-success promise).
80
+ The driver seeds a throwaway fixture, prints the prompt + pass criteria, makes
81
+ NO model call, and never gates — LLM nondeterminism is why the deterministic
82
+ gate stays §5. See `evals/scenarios/README.md`.