@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 +305 -92
- package/dist/tools/project.js +25 -1
- package/package.json +1 -1
- package/dist/tools/patch.js +0 -67
package/README.md
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="
|
|
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
|
-
##
|
|
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 **
|
|
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 |
|
|
52
|
+
| Layer | Purpose |
|
|
22
53
|
|---|---|
|
|
23
|
-
| **Skill** (`SKILL.md`) | Tells AI
|
|
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
|
|
64
|
+
## Benchmark: First-Try Success
|
|
30
65
|
|
|
31
|
-
>
|
|
66
|
+
> **100% first-try CI pass with Vise vs 0% without.**
|
|
67
|
+
>
|
|
68
|
+
> **76% cheaper · 28% faster · 86% fewer issues**
|
|
32
69
|
|
|
33
|
-
|
|
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
|
-
|
|
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
|
-
|
|
80
|
+
<sub>Token/cost data from Antigravity/Gemini Flash 3.5. Copilot CLI does not expose token accounting.</sub>
|
|
50
81
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
|
58
|
-
|
|
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
|
-
##
|
|
114
|
+
## Supported Platforms
|
|
63
115
|
|
|
64
|
-
|
|
|
65
|
-
|
|
66
|
-
| **
|
|
67
|
-
| **
|
|
68
|
-
| **
|
|
69
|
-
| **
|
|
70
|
-
| **
|
|
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
|
|
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
|
-
|
|
126
|
+
---
|
|
80
127
|
|
|
81
|
-
##
|
|
128
|
+
## Installation
|
|
82
129
|
|
|
83
|
-
Install
|
|
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
|
-
|
|
137
|
+
Or install per-project:
|
|
91
138
|
|
|
92
139
|
```sh
|
|
93
|
-
npm install
|
|
94
|
-
|
|
95
|
-
npm start
|
|
140
|
+
npm install -D @amityco/social-plus-vise
|
|
141
|
+
npx vise --help
|
|
96
142
|
```
|
|
97
143
|
|
|
98
|
-
|
|
144
|
+
### Install the Skill Into Your Coding Tool
|
|
99
145
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
vise install-skill --target claude
|
|
105
|
-
vise install-skill --target
|
|
106
|
-
vise install-skill --target
|
|
107
|
-
vise install-skill --target
|
|
108
|
-
vise install-skill --target
|
|
109
|
-
vise
|
|
110
|
-
vise
|
|
111
|
-
vise
|
|
112
|
-
vise
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
vise
|
|
123
|
-
vise
|
|
124
|
-
|
|
125
|
-
|
|
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 "..."]
|
|
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
|
-
|
|
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
|
-
|
|
188
|
+
---
|
|
131
189
|
|
|
132
|
-
|
|
133
|
-
|
|
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
|
-
|
|
267
|
+
### Tool names (snake_case per MCP convention)
|
|
137
268
|
|
|
138
|
-
|
|
139
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
```
|
|
147
|
-
|
|
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
|
-
|
|
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>
|
package/dist/tools/project.js
CHANGED
|
@@ -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
package/dist/tools/patch.js
DELETED
|
@@ -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
|
-
}
|