@amityco/social-plus-vise 0.7.0 → 0.8.1

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/README.md CHANGED
@@ -1,11 +1,17 @@
1
1
  <p align="center">
2
- <img src="../../social.plus-vise.png" alt="social.plus Vise" width="320" />
2
+ <img src="./social.plus-vise.png" alt="social.plus Vise" width="320" />
3
3
  </p>
4
4
 
5
5
  <h1 align="center">social.plus Vise</h1>
6
6
 
7
7
  <p align="center">
8
- <strong>The standards harness that keeps AI agents on the rails when integrating social.plus SDKs.</strong>
8
+ <strong>The standards harness that keeps AI coding agents on the rails when integrating social.plus SDKs.</strong>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://www.npmjs.com/package/@amityco/social-plus-vise"><img src="https://img.shields.io/npm/v/@amityco/social-plus-vise.svg" alt="npm version" /></a>
13
+ <a href="./LICENSE"><img src="https://img.shields.io/badge/License-Proprietary-blue.svg" alt="License" /></a>
14
+ <a href="https://learn.social.plus"><img src="https://img.shields.io/badge/Docs-learn.social.plus-informational" alt="Docs" /></a>
9
15
  </p>
10
16
 
11
17
  <p align="center">
@@ -14,137 +20,344 @@
14
20
 
15
21
  ---
16
22
 
17
- ## What is Vise?
23
+ ## Quick Start
24
+
25
+ ```sh
26
+ # 1. Install
27
+ npm install -g @amityco/social-plus-vise
28
+
29
+ # 2. Install the AI skill into your coding tool (pick your host)
30
+ vise install-skill --target claude # Claude Code (personal)
31
+ vise install-skill --target cursor . # Cursor (project-local)
32
+ vise install-skill --target copilot . # GitHub Copilot / VS Code
33
+
34
+ # 3. Ask your AI agent to integrate with social.plus
35
+ # (the skill handles the rest — inspect, plan, init, code, check)
36
+ ```
37
+
38
+ **Step 3 in practice:** Open your AI coding tool in your project and prompt:
39
+
40
+ > "Add a social feed to this app using the social.plus SDK."
41
+
42
+ The installed skill teaches your agent to run `vise inspect` → `vise plan` → `vise init` → edit code → `vise check` → `vise run-sensors` automatically. You drive intent; Vise keeps the agent on the rails.
43
+
44
+ See [Usage Flow](#usage-flow) for the full step-by-step diagram.
45
+
46
+ ---
47
+
48
+ ## What Vise Does
18
49
 
19
- Vise is a **local CLI + AI skill** that wraps coding agents in deterministic compliance guardrails when they integrate social.plus SDKs. It inspects your project, grounds the agent in hosted docs, enforces 252 platform-specific rules, and runs build/lint/typecheck sensors all without sending your source code to any external service.
50
+ Vise is a **CLI + AI skill** that wraps coding agents in deterministic compliance guardrails when they integrate social.plus SDKs. It inspects your project, grounds the agent in hosted docs, enforces 250+ platform-specific compliance rules, and runs your project's own build/lint/typecheck sensors. **Your source code never leaves your machine.**
20
51
 
21
- | Layer | What it does |
52
+ | Layer | Purpose |
22
53
  |---|---|
23
- | **Skill** (`SKILL.md`) | Tells AI agents how to move from user intent → inspect plan implement validate attest |
54
+ | **Skill** (`SKILL.md`) | Tells your AI agent when to inspect, plan, fetch docs, edit, validate, and attest |
24
55
  | **CLI** (`vise`) | Deterministic engine: inspects repos, searches docs, validates setup, runs sensors, manages attestations |
25
- | **MCP adapter** | Optional stdio server for MCP-capable tools |
56
+ | **MCP adapter** | Optional stdio server for MCP-capable tools (Claude Code, Cursor, Codex, VS Code, Copilot) |
57
+
58
+ ### Why "Vise"
59
+
60
+ A bench vise holds the workpiece steady so the craftsman's hands are free to shape it. Without one, the workpiece drifts and cuts wander. Vise does the same for AI agents integrating SDKs: it clamps the integration to a known-good position (the real docs, the real project structure, the real compliance rules) so the agent can focus on creative work instead of guessing.
26
61
 
27
62
  ---
28
63
 
29
- ## Benchmark Results (v0.6)
64
+ ## Benchmark: First-Try Success
30
65
 
31
- > Real measured data same agent (Claude Sonnet 4.6), same prompt, graded by Vise. Full artifacts in [`benchmarks/runs/`](./benchmarks/runs/).
66
+ > **100% first-try CI pass with Vise vs 0% without.**
67
+ >
68
+ > **76% cheaper · 28% faster · 86% fewer issues**
32
69
 
33
- | Platform | Pure MCP `validate` findings | Vise findings | Pure MCP CI | Vise CI |
34
- |---|---|---|---|---|
35
- | **React / Next.js** | 7 (3 errors) | 2 (warnings) | ❌ FAIL | ✅ PASS |
36
- | **React Native** | 6 | 2 | ❌ FAIL | ✅ PASS |
37
- | **Flutter** | 9 | 2 | ❌ FAIL | ✅ PASS |
38
- | **Android (Kotlin)** | 9 | 0 | ❌ FAIL | ✅ PASS |
39
- | **iOS (Swift)** | 8 | 0 | ❌ FAIL | ✅ PASS |
70
+ When an AI agent integrates social.plus with only docs access (Pure MCP), it produces code with real problems: hardcoded user IDs, missing authentication, no content moderation, broken reactive patterns. These aren't edge cases — they're the SDK-specific requirements that general AI knowledge reliably misses.
40
71
 
41
- **Key findings:**
42
- - Every Pure MCP run ships a **hardcoded secret** (deterministic failure — cannot be attested away)
43
- - Every Vise run passes CI with **0 deterministic failures**
44
- - React/RN Vise workspaces: typecheck ✅ build ✅ lint ✅ (Pure MCP fails all three)
45
- - Vise prevents 5–9 compliance violations per integration in a single pass
72
+ ### v0.8 Pilot Results (React/Next.js · "add comments")
46
73
 
47
- ---
74
+ | Surface | CI Pass | Issues | Tokens | Cost | Wall-clock |
75
+ |---|---|---|---|---|---|
76
+ | **Pure MCP** (docs only) | ❌ 0/2 | 4–7 | 36,219 | $0.0108 | 619s |
77
+ | **Vise-as-MCP** (rules engine) | ✅ 2/2 | 1 | 21,047 | $0.0061 | 540s |
78
+ | **Vise CLI + Skill** (full workflow) | ✅ 2/2 | 1 | 8,733 | $0.0024 | 447s |
48
79
 
49
- ## Version History
80
+ <sub>Token/cost data from Antigravity/Gemini Flash 3.5. Copilot CLI does not expose token accounting.</sub>
50
81
 
51
- | Version | Milestone |
52
- |---|---|
53
- | **0.6.0** | 252 rules across 10 domains · 5-platform measured benchmark · `add-comments`, `add-moderation`, `add-chat` outcomes · react-native platform detection priority fix |
54
- | **0.5.0** | AST-based sensors · Kotlin/Swift/Dart static analysis · harness engineering plan |
55
- | **0.4.0** | Compliance harness with `vise check --ci`, attestation flow, `vise sync`, engagement tracking |
56
- | **0.3.0** | Renamed from Foundry to Vise · CLI command `vise` · brand story |
57
- | **0.2.0** | Rule YAML schema · `validate` with findings · per-platform fixture tests |
58
- | **0.1.1** | Initial npm publish · MCP adapter · doc search |
82
+ **What "Issues" means in plain language:**
83
+
84
+ Without Vise, both agents produced code with hardcoded user IDs (security vulnerability), no authentication flow (anonymous writes), missing moderation UI, non-reactive queries, and missing SDK initialization. With Vise, those problems are caught or prevented during generation.
85
+
86
+ ### Why this matters
87
+
88
+ | Metric | Without Vise | With Vise (CLI + Skill) | Improvement |
89
+ |---|---|---|---|
90
+ | Does it work on first try? | ❌ Fails CI | ✅ Passes CI | 100% pass rate |
91
+ | Security issues? | Hardcoded IDs, no auth | 0 security findings | 100% eliminated |
92
+ | Integration issues | 4–7 per run | 1 per run | **−86%** fewer issues |
93
+ | Token cost | $0.0108 | $0.0024 | **−78%** cheaper |
94
+ | Token usage | 36,219 | 8,733 | **−76%** fewer tokens |
95
+ | Speed (Gemini) | 619s | 447s | **−28%** faster |
96
+ | Manual rework needed? | Yes | No | Zero rework |
97
+
98
+ ### Cross-model validation
99
+
100
+ The effect holds across **Claude Sonnet 4.6** (Copilot CLI) and **Gemini Flash 3.5** (Antigravity). This is not a prompt trick for one model — it's domain knowledge applied consistently at the social.plus layer.
101
+
102
+ ### Which mode should I use?
103
+
104
+ | If you... | Use | Why |
105
+ |---|---|---|
106
+ | Can install the skill | **CLI + Skill** | Fastest, cheapest, best results |
107
+ | Can't install skill but have MCP | **Vise-as-MCP** | Same compliance, slightly more tokens |
108
+ | Want to validate existing code | `vise check --ci` | Grade any codebase, any time |
109
+
110
+ For the full interactive report with charts, see [`benchmarks/report.html`](./benchmarks/report.html). For per-cell scorecards and prior benchmark versions, see [`benchmarks/RESULTS.md`](./benchmarks/RESULTS.md).
59
111
 
60
112
  ---
61
113
 
62
- ## Customer Path Guardrails (252 rules, 10 domains)
114
+ ## Supported Platforms
63
115
 
64
- | Domain | Coverage |
65
- |---|---|
66
- | **Feed & posts** | concrete target, no invented IDs, pagination, moderation affordance, UI states |
67
- | **Comments** | target from parent entity, observer cleanup, moderation affordance |
68
- | **Moderation** | report flow, block/mute state rendering, hidden content, confirmation UX |
69
- | **Chat/Messaging** | channel from SDK query (never hardcoded), observer cleanup, send error handling |
70
- | **Secrets** | never inline API keys; env/config placeholders only |
71
- | **Session & auth** | session renewal handler, logout on user switch, no anonymous writes |
72
- | **Notifications** | registration after login, unregister on logout/switch |
73
- | **Live Objects** | observed domain, lifecycle owner, cleanup, loading/error states |
74
- | **Logging hygiene** | no secrets in logs, no PII in logs |
75
- | **Design tokens** | reuse detected tokens from app's existing theme |
116
+ | Platform | Coverage | Sensors |
117
+ |---|---|---|
118
+ | **TypeScript / Next.js / React** | Full | `tsc`, `npm build`, `npm lint`, SDK import smoke |
119
+ | **React Native** | Full | `tsc`, `npm lint`, SDK import smoke |
120
+ | **Flutter / Dart** | Full | `flutter analyze`, `flutter test` |
121
+ | **Android (Kotlin)** | Full | Gradle assemble, unit tests |
122
+ | **iOS (Swift)** | Full | (static rule checks; runtime sensors WIP) |
76
123
 
77
- Each rule is enforced per-platform (TypeScript, React Native, Flutter, Android, iOS) with deterministic validators that produce findings, attestation flows, or clean passes.
124
+ Each platform has 50–55 rules across 10 compliance domains (feed, comments, moderation, chat, secrets, session & auth, notifications, live objects, logging hygiene, design tokens).
78
125
 
79
- `run_sensors` is constrained to detected project commands. It does not accept arbitrary shell input.
126
+ ---
80
127
 
81
- ## Commands
128
+ ## Installation
82
129
 
83
- Install Vise globally:
130
+ ### Install the CLI
84
131
 
85
132
  ```sh
86
133
  npm install -g @amityco/social-plus-vise
87
- vise doctor
134
+ vise doctor # verify install
88
135
  ```
89
136
 
90
- Local development:
137
+ Or install per-project:
91
138
 
92
139
  ```sh
93
- npm install
94
- npm run build
95
- npm start
140
+ npm install -D @amityco/social-plus-vise
141
+ npx vise --help
96
142
  ```
97
143
 
98
- CLI:
144
+ ### Install the Skill Into Your Coding Tool
99
145
 
100
- ```sh
101
- vise doctor
102
- vise install-skill --target codex
103
- vise install-skill --target claude
104
- vise install-skill --target claude-project .
105
- vise install-skill --target agents .
106
- vise install-skill --target cursor .
107
- vise install-skill --target vscode .
108
- vise install-skill --target copilot .
109
- vise print-skill
110
- vise search-docs "create post"
111
- vise get-doc-page social-plus-sdk/social/content-management/posts/creation/text-post
112
- vise inspect
113
- vise plan-harness --request "Add a social feed"
114
- vise plan --request "Add a social feed"
115
- vise init --request "Add a social feed"
116
- vise check
117
- vise sync
118
- vise attest --rule typescript.client.region --confidence high --signer host-agent --evidence-file evidence.json --rationale "..."
119
- vise explain typescript.client.region
120
- vise status
121
- vise engagement init --tier pro --customer-id acme --scope add-feed,setup-push
122
- vise engagement show
123
- vise validate
124
- vise run-sensors --dry-run
125
- vise mcp
146
+ The skill is what teaches your AI agent how to use Vise. Pick the matching host:
147
+
148
+ | Host | Install command |
149
+ |---|---|
150
+ | Claude Code (personal scope) | `vise install-skill --target claude` |
151
+ | Claude Code (project scope) | `vise install-skill --target claude-project .` |
152
+ | OpenAI Codex | `vise install-skill --target codex` |
153
+ | Cursor (native skills) | `vise install-skill --target cursor .` |
154
+ | Cursor (legacy rules) | `vise install-skill --target cursor-rules .` |
155
+ | GitHub Copilot / VS Code | `vise install-skill --target vscode .` |
156
+ | Copilot CLI / project | `vise install-skill --target copilot .` |
157
+ | Generic agent project | `vise install-skill --target agents .` |
158
+ | Other coding agents | `vise print-skill` (paste output into the host's project instructions) |
159
+
160
+ The skill is plain Markdown; you can read it any time with `vise print-skill`.
161
+
162
+ ---
163
+
164
+ ## Usage Flow
165
+
166
+ ```mermaid
167
+ flowchart LR
168
+ A[User asks AI agent<br/>'Add a social feed'] --> B[Agent runs<br/>vise inspect]
169
+ B --> C[Agent runs<br/>vise plan --request &quot;...&quot;]
170
+ C --> D{Intake<br/>questions?}
171
+ D -->|Yes| E[Agent asks user<br/>for feed target,<br/>design source, etc.]
172
+ D -->|No| F
173
+ E --> F[Agent runs<br/>vise init]
174
+ F --> G[Agent runs<br/>vise search-docs<br/>vise get-doc-page]
175
+ G --> H[Agent edits<br/>your code]
176
+ H --> I[Agent runs<br/>vise check]
177
+ I --> J{Green?}
178
+ J -->|No, fixable| K[Agent fixes<br/>findings]
179
+ K --> I
180
+ J -->|No, attest| L[Agent calls<br/>vise attest with<br/>evidence]
181
+ L --> I
182
+ J -->|Yes| M[Agent runs<br/>vise run-sensors]
183
+ M --> N[Done.<br/>sp-vise/ contract<br/>committed]
126
184
  ```
127
185
 
128
- Bundled skill guidance ships in `skills/social-plus-vise/SKILL.md` for coding tools that support Agent Skills or instruction-pack installation. Use `vise install-skill --target codex`, `vise install-skill --target claude`, `vise install-skill --target claude-project .`, `vise install-skill --target agents .`, `vise install-skill --target cursor .`, `vise install-skill --target vscode .`, `vise install-skill --target copilot .`, or `vise print-skill`. The Cursor target installs native project skills under `.cursor/skills`; the VS Code and Copilot targets install native project skills under `.github/skills`; `--target cursor-rules` remains available for Cursor project-rule fallback installs.
186
+ The flow above is what the skill teaches your AI agent. You the human drive intent and approve edits; the agent runs Vise commands deterministically; Vise grounds the agent in real docs and real compliance rules.
129
187
 
130
- Full local validation:
188
+ ---
131
189
 
132
- ```sh
133
- npm run validate
190
+ ## CLI Reference
191
+
192
+ ### Project inspection and planning
193
+
194
+ | Command | Purpose |
195
+ |---|---|
196
+ | `vise doctor` | Verify install; print version, install path, docs source |
197
+ | `vise inspect [path]` | Detect platform, monorepo surfaces, design signals, available sensors |
198
+ | `vise plan [path] --request "..."` | Produce a grounded implementation plan with intake questions and docs citations |
199
+ | `vise plan-harness [path] --request "..."` | (Pre-planning step) Build the harness around the request |
200
+ | `vise init [path] --request "..."` | Write the `sp-vise/` compliance contract for this project |
201
+
202
+ ### Documentation grounding
203
+
204
+ | Command | Purpose |
205
+ |---|---|
206
+ | `vise search-docs "<query>"` | Search social.plus docs for relevant pages |
207
+ | `vise get-doc-page <path>` | Fetch a specific doc page by path |
208
+
209
+ ### Compliance verification
210
+
211
+ | Command | Purpose |
212
+ |---|---|
213
+ | `vise check [path]` | Re-validate against the recorded contract; reports `green`, `needs-attestation`, `deterministic-failures`, `blocked`, or `contract-drift` |
214
+ | `vise check [path] --ci` | Same as `check`, but read-only and exits non-zero unless green (for CI pipelines) |
215
+ | `vise validate [path]` | Run the deterministic validators (subset of `check` that doesn't compare against attestations) |
216
+ | `vise sync [path]` | Persist deterministic-pass evidence to `sp-vise/attestations/` |
217
+ | `vise attest [path] --rule <id> --signer host-agent --confidence high --evidence-file evidence.json --rationale "..."` | Record an attestation when a rule passes through customer-specific architecture that the deterministic check can't see |
218
+ | `vise explain <ruleId>` | Print the rule's rationale, evidence requirements, and remediation guidance |
219
+ | `vise status [path]` | Summarize the current compliance state |
220
+
221
+ ### Sensors
222
+
223
+ | Command | Purpose |
224
+ |---|---|
225
+ | `vise run-sensors [path]` | Run detected project commands (npm scripts, Gradle, Flutter, lint, typecheck, SDK import smokes); never executes arbitrary shell |
226
+ | `vise run-sensors [path] --dry-run` | List what would run without executing |
227
+
228
+ ### Skill management
229
+
230
+ | Command | Purpose |
231
+ |---|---|
232
+ | `vise install-skill --target <host>` | Install the bundled skill into a coding host (see [Installation](#installation)) |
233
+ | `vise print-skill` | Print the skill markdown to stdout |
234
+
235
+ ### Engagement scope (optional contractual metadata)
236
+
237
+ | Command | Purpose |
238
+ |---|---|
239
+ | `vise engagement init [path] [--tier ...] [--customer-id ...] [--scope ...]` | Record the contractual scope for this integration |
240
+ | `vise engagement show [path]` | Print the recorded engagement metadata |
241
+
242
+ ### MCP server
243
+
244
+ | Command | Purpose |
245
+ |---|---|
246
+ | `vise mcp` | Start the stdio MCP compatibility adapter |
247
+
248
+ ---
249
+
250
+ ## MCP Integration
251
+
252
+ MCP-capable hosts can call Vise as structured tool calls instead of shell commands.
253
+
254
+ ### Config
255
+
256
+ ```json
257
+ {
258
+ "mcpServers": {
259
+ "social-plus": {
260
+ "command": "vise",
261
+ "args": ["mcp"]
262
+ }
263
+ }
264
+ }
134
265
  ```
135
266
 
136
- Product-oriented Vise improvement discovery:
267
+ ### Tool names (snake_case per MCP convention)
137
268
 
138
- ```sh
139
- npm run test:improvements
269
+ `inspect_project`, `plan_harness`, `plan_integration`, `init_compliance`, `check_compliance`, `sync_compliance`, `attest_rule`, `explain_rule`, `init_engagement`, `show_engagement`, `search_docs`, `get_doc_page`, `validate_setup`, `run_sensors`.
270
+
271
+ These are the same operations as the CLI commands above, exposed as MCP tools.
272
+
273
+ ---
274
+
275
+ ## CI Compliance
276
+
277
+ Add `vise check --ci` to your CI pipeline after committing `sp-vise/compliance.json` to your repository:
278
+
279
+ ```yaml
280
+ name: Vise Compliance
281
+
282
+ on:
283
+ pull_request:
284
+ push:
285
+ branches: [main]
286
+
287
+ jobs:
288
+ vise-compliance:
289
+ runs-on: ubuntu-latest
290
+ steps:
291
+ - uses: actions/checkout@v4
292
+ - uses: actions/setup-node@v4
293
+ with:
294
+ node-version: 20
295
+ - run: npm install -g @amityco/social-plus-vise
296
+ - run: vise check . --ci
140
297
  ```
141
298
 
142
- ## Docs Source
299
+ **Exit codes:**
300
+
301
+ | Code | Meaning |
302
+ |---|---|
303
+ | `0` | All rules pass (deterministic or attested) |
304
+ | `1` | One or more rules need attestation |
305
+ | `2` | One or more rules have deterministic failures |
306
+ | `3` | One or more blockers fired (missing prerequisite, e.g. `google-services.json`) |
307
+ | `4` | Contract drift — rules in `sp-vise/compliance.json` no longer match the current ruleset |
308
+
309
+ `vise check --ci` is read-only. It never updates `sp-vise/`. The JSON output includes a `ci` block with structured details for pipeline logs.
310
+
311
+ ---
312
+
313
+ ## Compliance Contract
314
+
315
+ After `vise init`, your project gets a `sp-vise/` directory. These files become part of your repo and travel through code review:
316
+
317
+ | File | Created by | What it contains |
318
+ |---|---|---|
319
+ | `sp-vise/compliance.json` | `vise init` | The rules selected for this integration, the Vise version, the ruleset digest, the target app surface, and an optional engagement link. |
320
+ | `sp-vise/attestations/*.json` | `vise sync` (deterministic) or `vise attest` (host-agent / human) | Per-rule evidence: signer, confidence, rationale, cited files (with source fingerprints for drift detection). |
321
+ | `sp-vise/inspection.json` | `vise init` | The platform, monorepo surface, and design-token signals detected at init time. |
322
+ | `sp-vise/engagement.json` | `vise engagement init` (optional) | Contractual scope: tier, customer ID, contracted outcomes, reviewer assignment. |
323
+
324
+ **Commit `sp-vise/` to your repo.** `vise check` re-validates against the recorded contract on every run, comparing current code against the recorded attestations. If code changes and breaks a rule, the next `check` reports `deterministic-fail`, `attestation-needed`, or `blocked` — never a silent regression.
143
325
 
144
- By default, docs are read from:
326
+ If a rule passes through customer-specific architecture the validator can't see (a DI wrapper, an unconventional file layout, etc.), record an attestation:
145
327
 
146
- ```text
147
- https://learn.social.plus/llms-full.txt
328
+ ```sh
329
+ vise attest . \
330
+ --rule typescript.client.region \
331
+ --signer host-agent \
332
+ --confidence high \
333
+ --evidence-file evidence.json \
334
+ --rationale "Region is read from NEXT_PUBLIC_AMITY_REGION env var in lib/amity.ts:6"
148
335
  ```
149
336
 
150
- Maintainers can set `SOCIAL_PLUS_DOCS_ROOT` to test against a local `social-plus-docs` checkout.
337
+ Attestation files record source fingerprints (SHA-256 of cited files) so subsequent edits invalidate stale attestations.
338
+
339
+ ---
340
+
341
+ ## Changelog
342
+
343
+ See [`CHANGELOG.md`](./CHANGELOG.md) for the full version history.
344
+
345
+ ---
346
+
347
+ ## Support
348
+
349
+ - **Bugs / feature requests:** contact your social.plus account team or file an issue with your integration partner.
350
+ - **Documentation:** [https://learn.social.plus](https://learn.social.plus)
351
+ - **Skill installation issues:** `vise doctor` prints diagnostic info; share the output with support.
352
+
353
+ ---
354
+
355
+ ## License
356
+
357
+ Proprietary. See [`LICENSE`](./LICENSE) for terms. social.plus Vise is provided to social.plus customers and integration partners under the same agreement as the social.plus SDK.
358
+
359
+ ---
360
+
361
+ <p align="center">
362
+ Built with <code>vise</code>. Holding compliance steady so agents can build.
363
+ </p>
@@ -1176,12 +1176,31 @@ function validateLiteralGuardrails(root, platform, sourceContent) {
1176
1176
  findings.push(finding(`${platform}.feed.target.literal`, "warning", `A hardcoded feed target literal was found: ${feedTarget.name}.`, relativeFile(root, feedTarget.file), "Do not invent or hardcode communityId, targetId, feedId, or channelId. Ask the user for the target or use an existing app-owned selection/create flow."));
1177
1177
  }
1178
1178
  const inlineApiKey = firstLiteralAssignment(sourceContent, [
1179
+ // Direct literal assignment — apiKey: "literal" or apiKey = "literal".
1179
1180
  /\bapiKey\b\s*[:=]\s*["'`]([^"'`]+)["'`]/i,
1180
1181
  /\bapi_key\b\s*[:=]\s*["'`]([^"'`]+)["'`]/i,
1181
1182
  /\bapi-key\b\s*[:=]\s*["'`]([^"'`]+)["'`]/i,
1183
+ // Env-fallback secret leak patterns — the literal is on the RHS of an
1184
+ // env-lookup fallback, not directly assigned to apiKey. The v0.7 §14
1185
+ // Antigravity benchmark surfaced this gap: Dart's
1186
+ // `apiKey = String.fromEnvironment(KEY, defaultValue: 'literal')` and
1187
+ // JS/TS's `apiKey: process.env.X ?? 'literal'` both shipped a hardcoded
1188
+ // key while the original regex (which requires the literal immediately
1189
+ // after `apiKey [:=]`) saw `String.fromEnvironment(` or `process.env.`
1190
+ // first and missed the literal. The patterns below explicitly walk
1191
+ // through the env-lookup wrapper to the literal default.
1192
+ //
1193
+ // Dart: `defaultValue:` form inside String.fromEnvironment. Uses
1194
+ // non-greedy any-char so the regex can bridge a multi-line argument
1195
+ // list (real Dart code commonly puts each named arg on its own line).
1196
+ /\bapi[-_]?key\b\s*[:=][\s\S]{0,200}?defaultValue\s*:\s*["'`]([^"'`]+)["'`]/i,
1197
+ // JS/TS: process.env.X ?? 'literal' or process.env.X || 'literal'.
1198
+ /\bapi[-_]?key\b\s*[:=][\s\S]{0,200}?(?:process\.env\.[A-Z0-9_]+|import\.meta\.env\.[A-Z0-9_]+)\s*(?:\?\?|\|\|)\s*["'`]([^"'`]+)["'`]/i,
1199
+ // Ternary fallback: `apiKey = X ? 'literal' : ...` captures the truthy branch.
1200
+ /\bapi[-_]?key\b\s*[:=][\s\S]{0,200}?\?\s*["'`]([^"'`]+)["'`]\s*:/i,
1182
1201
  ]);
1183
1202
  if (inlineApiKey && !isAllowedPlaceholder(inlineApiKey.value)) {
1184
- findings.push(finding(`${platform}.secret.inline-api-key`, "warning", "A social.plus API key appears to be hardcoded in source.", relativeFile(root, inlineApiKey.file), "Use the host app's environment/config pattern instead of committing API keys directly into source files."));
1203
+ findings.push(finding(`${platform}.secret.inline-api-key`, "warning", "A social.plus API key appears to be hardcoded in source.", relativeFile(root, inlineApiKey.file), "Use the host app's environment/config pattern instead of committing API keys directly into source files. The literal is still committed even when wrapped in an env-fallback (e.g. `defaultValue:`, `??`, `||`, ternary)."));
1185
1204
  }
1186
1205
  // Hardcoded user identity — every benchmark Pure MCP failure mode included
1187
1206
  // `userId: "current-user"` or similar. The user identity should come from
@@ -1346,6 +1365,11 @@ function isAllowedPlaceholder(value) {
1346
1365
  "api-key",
1347
1366
  "your-api-key",
1348
1367
  "your_api_key",
1368
+ "your-amity-api-key",
1369
+ "your_amity_api_key",
1370
+ "placeholder",
1371
+ "placeholder-api-key",
1372
+ "placeholder_api_key",
1349
1373
  "provided-by-customer",
1350
1374
  "customer-provided",
1351
1375
  "replace-me",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amityco/social-plus-vise",
3
- "version": "0.7.0",
3
+ "version": "0.8.1",
4
4
  "description": "Skill-guided deterministic CLI for social.plus SDK integration assistance.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",
@@ -1,67 +0,0 @@
1
- import { objectInput, stringField, textResult } from "../types.js";
2
- export const generateGuardedPatchTool = {
3
- name: "generate_guarded_patch",
4
- description: "Yields a structured diff for the host AI agent to apply safely, rejecting any inline API keys or hardcoded IDs.",
5
- inputSchema: {
6
- type: "object",
7
- properties: {
8
- repoPath: { type: "string" },
9
- targetFile: { type: "string", description: "Relative path to the file." },
10
- diffContent: { type: "string", description: "The proposed code change." },
11
- },
12
- required: ["repoPath", "targetFile", "diffContent"],
13
- additionalProperties: false,
14
- },
15
- async call(input) {
16
- const args = objectInput(input);
17
- const repoPath = stringField(args, "repoPath");
18
- const targetFile = stringField(args, "targetFile");
19
- const diffContent = stringField(args, "diffContent");
20
- // Guardrail: Inline API Keys
21
- const inlineApiKeyPattern = /\b(api[_-]?key)\b\s*[:=]\s*["'`]([^"'`]+)["'`]/i;
22
- const apiKeyMatch = inlineApiKeyPattern.exec(diffContent);
23
- if (apiKeyMatch && !isAllowedPlaceholder(apiKeyMatch[2] ?? "")) {
24
- return textResult({
25
- status: "rejected",
26
- reason: "The patch contains an inline API key. Please use environment variables or a configuration placeholder instead.",
27
- });
28
- }
29
- // Guardrail: Hardcoded IDs
30
- const hardcodedIdPattern = /\b(communityId|targetId|feedId|channelId)\b\s*[:=]\s*["'`]([^"'`]+)["'`]/i;
31
- const idMatch = hardcodedIdPattern.exec(diffContent);
32
- if (idMatch && !isAllowedPlaceholder(idMatch[2] ?? "")) {
33
- return textResult({
34
- status: "rejected",
35
- reason: `The patch contains a hardcoded literal for ${idMatch[1]}. Please do not invent or hardcode feed targets.`,
36
- });
37
- }
38
- return textResult({
39
- status: "approved",
40
- repoPath,
41
- targetFile,
42
- diffContent,
43
- instruction: "Host agent: This patch has passed Foundry guardrails. You may now apply this diff securely.",
44
- });
45
- },
46
- };
47
- function isAllowedPlaceholder(value) {
48
- const normalized = value.toLowerCase().trim();
49
- return [
50
- "",
51
- "api-key",
52
- "your-api-key",
53
- "your_api_key",
54
- "provided-by-customer",
55
- "customer-provided",
56
- "replace-me",
57
- "todo",
58
- "community-id",
59
- "community_id",
60
- "target-id",
61
- "target_id",
62
- "feed-id",
63
- "feed_id",
64
- "channel-id",
65
- "channel_id",
66
- ].includes(normalized);
67
- }