@amityco/social-plus-vise 1.4.6 → 1.6.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 CHANGED
@@ -4,14 +4,39 @@ All notable changes to `@amityco/social-plus-vise` are documented in this file.
4
4
 
5
5
  The format is loosely based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
- ## Unreleased
7
+ ## 1.6.0 — 2026-07-06
8
8
 
9
- No changes yet.
9
+ ### Added
10
+ - **Reactivity rules for the latest SDK features.** Three new live-collection rules guard features added in the recent SDK release: in-chat **message search** (`message-search.live-collection`, all platforms), **archived channels** (`channel-archive.live-collection`, all platforms), and the personalized **For-You feed** (`for-you-feed.live-collection`, TypeScript/React Native/Android/iOS). Each flags a results list rendered from a one-shot query instead of the reactive, paginated Live Collection, and stays silent on a correct reactive integration. For-You is not part of the Flutter public API, so a For-You request on Flutter now surfaces a platform-availability notice pointing to a community- or user-scoped feed instead.
11
+
12
+ ### Changed
13
+ - **Refreshed the bundled SDK surface facts** for TypeScript, Android, iOS, and Flutter. `vise sdk-facts` and the symbol-anchored rules now reflect the current SDK symbols and models — including channel archiving, message search, For-You feed, and per-scope notification modes. The refresh is additive: no previously grounded symbol was removed, so existing rules keep resolving.
14
+ - **Portable provenance in `vise sdk-surface:import`.** The importer normalizes the source paths recorded in the shipped surface facts, so they stay machine-independent regardless of local checkout layout.
15
+
16
+ ## 1.5.0 — 2026-07-05
17
+
18
+ ### Added
19
+ - **`no-platform` check status (exit 8).** A repo with no detected mobile/web platform no longer resolves to a vacuous green — `vise check` reports `no-platform` so a platform-less/static project can't pass by having zero applicable rules.
20
+ - **Runtime `proof-waived` terminal.** `vise smoke waive --reason <why> --mode declined|deviceless` records an auditable, under-claiming waiver; `vise check` then reports `runtime-proof-waived` (exit 9; `--allow-proof-waiver` → exit 0), and `vise workplan complete` accepts it. Genuine passing runtime-smoke evidence always overrides a waiver; a waiver never reads as "proven".
21
+ - **Evidence-inferred workplan completion.** `vise workplan status`/`next` now auto-records a surface whose live check is green (completable) for the in-scope surface, reusing the same snapshot/integrity-manifest machinery as `vise workplan complete` — so a working, check-green surface isn't left uncredited when the separate `complete` step is skipped. Reports an `autoCompleted` field; fires only for the in-scope surface.
22
+ - **Native data-seeding guidance (SKILL).** New "Seeding Data When Empty (read-after-write lag)" guidance: a freshly created community/channel/post may not reappear in an immediate list re-query — merge the create-response into the rendered list, persist created IDs, and bound-retry on a transient 401/stall.
23
+
24
+ ### Changed
25
+ - **State-based resume.** A reworded "continue" request re-attaches to an in-progress signed flow via companion outcomes (comments↔feed, community→feed/comments); unrelated requests stay separate but get a resume hint.
26
+ - **Sharper day-2 debug scope.** Session-state symptoms (`notLoggedIn`, "session not established") correlate to the requery rules; a bare backend 401/500 now needs SDK context so it doesn't mis-correlate.
27
+
28
+ ### Fixed
29
+ - **iOS sensor precision (false-positives).** Recognize valid SDK idioms — `post.postData` / `post.data?["text"]` for post body, Combine `AmityObject.$snapshot.sink` for follow subscription — bound the unread manual-count regex to a single line (it spanned to EOF in semicolon-free Swift), and skip non-rendering `ViewModel`/`Gateway` layers for the ban-state/role-gated guards (the View/Activity that renders the action is still checked). Also fixed a latent bug: the non-UI-file skip didn't account for `.java`/`.kts` extensions, so it never applied to Android Java files.
30
+ - **Forgeable cross-file `// vise:` assertions.** A `// vise: … at <File>` guard assertion is now trusted only when the named file actually carries a real (non-comment) guard; a bare comment naming no file stays the documented opt-out.
31
+ - **Malformed `design-profile.json`.** Now surfaces `brandGrounding: invalid` with a "fix, don't re-author" diagnostic instead of silently reading as absent.
32
+
33
+ ### Compatibility
34
+ - **Additive exit codes.** `vise check` gains `no-platform` (exit 8) and `runtime-proof-waived` (exit 9; `--allow-proof-waiver` → 0). The existing 0–6 exit surface and its precedence are unchanged, so a pipeline that gates on `exitCode === 0` (or `--ci`) is unaffected. One intentional behavior change: a platform-less repo that previously exited green now reports `no-platform` (exit 8) — a repo with zero applicable rules was never a real pass. The rule corpus and contract digest are unchanged, so existing attestations are not invalidated.
10
35
 
11
36
  ## 1.4.6 — 2026-07-02
12
37
 
13
38
  ### Added
14
- - **Marketing capability explainer.** Added a shipped `docs/vise-how-it-helps.html` page for marketing and sales enablement that explains Vise's agentic workflow, three validation layers, current real-E2E scorecard methodology, and realistic brownfield-style Social+ integration outputs in a light themed gallery.
39
+ - **Capability explainer page.** Added a shipped `docs/vise-how-it-helps.html` page that explains Vise's agentic workflow, three validation layers, real-E2E scorecard methodology, and realistic brownfield-style social.plus integration outputs in a light-themed gallery.
15
40
 
16
41
  ### Changed
17
42
  - **Preview status is explicit in the public README.** The npm README now marks Vise as a preview release and sets the expected boundary for API stability, benchmark methodology, advisory intelligence, code review, QA, and runtime verification.
@@ -32,7 +57,7 @@ No changes yet.
32
57
  ## 1.4.3 — 2026-07-02
33
58
 
34
59
  ### Changed
35
- - **Current scorecard now has React Native and Flutter controls.** The retained real-E2E summary and npm README now include fresh no-Vise controls for React Native and Flutter beside the current Vise rows, bringing the cross-platform head-to-head average to **91.8 vs 48.0** (+43.8 points).
60
+ - **Current scorecard now has React Native and Flutter controls.** The retained real-E2E summary and npm README now include fresh no-Vise controls for React Native and Flutter beside the current Vise rows.
36
61
  - **Scoring methodology is now documented.** Added the real-E2E scoring methodology, including dimensions, weights, caps, aggregation rules, and the claim boundary for current-loop vs formal public benchmark results.
37
62
 
38
63
  ### Fixed
@@ -41,13 +66,13 @@ No changes yet.
41
66
  ## 1.4.2 — 2026-07-02
42
67
 
43
68
  ### Changed
44
- - **README scorecard now includes the current Flutter and React Native rows.** The npm README and retained real-E2E results now show Flutter `fieldhouse-club` (**92.8**) and React Native `arena-fit` (**90.3**) as current Vise-arm-only native readiness evidence, with runtime-launch/screenshot proof and no console errors.
45
- - **Head-to-head benchmark boundary tightened.** The Android/iOS/Web Vise-vs-no-Vise average remains **91.9 vs 46.6** (+45.3 points), while Flutter and React Native are explicitly excluded from that lift until their no-Vise controls are rerun on the hardened harness.
69
+ - **README scorecard now includes the current Flutter and React Native rows.** The npm README and retained real-E2E results now show Flutter and React Native as current Vise-arm-only native readiness evidence, with runtime-launch/screenshot proof and no console errors.
70
+ - **Head-to-head benchmark boundary tightened.** Flutter and React Native are explicitly excluded from the Android/iOS/Web Vise-vs-no-Vise average until their no-Vise controls are rerun on the hardened harness.
46
71
 
47
72
  ## 1.4.1 — 2026-07-02
48
73
 
49
74
  ### Changed
50
- - **README evidence refreshed to the current real-E2E scorecard.** The npm README now leads with the retained July 2026 cross-platform scorecard: Vise average **91.9** vs no-Vise average **46.6** (+45.3 points), with Android/iOS/Web runtime-proof rows and the same methodology boundary as `benchmarks/real-e2e/RESULTS.md`.
75
+ - **README evidence refreshed to the current real-E2E scorecard.** The npm README now leads with the retained July 2026 cross-platform scorecard, with Android/iOS/Web runtime-proof rows and the same methodology boundary as `benchmarks/real-e2e/RESULTS.md`.
51
76
  - **Outdated benchmark figures removed from the shipped README.** Earlier SDK-compliance, design-conformance, feed-completeness, and Engagement Intelligence dogfood numbers were removed from the public README because they were measured on older builds/protocols and should not be mixed with the current scorecard.
52
77
 
53
78
  ## 1.4.0 — 2026-07-02
@@ -600,9 +625,9 @@ Docs-only patch; no CLI, MCP, rule, or sidecar behavior changes.
600
625
  - **`reactions.configured-name-used`** (all 5 platforms) downgraded to advisory. Rule fires on ~100% of correct apps (every tenant defaults to `"like"`) and was only clearable by a ritual comment. Version bumped to 2; existing compliance.json files will show contract-drift — run `vise sync` to update.
601
626
 
602
627
  ### Benchmark
603
- - Brand benchmark (an external brand design system × social.plus community feed, Sonnet n=3): pure-mcp 0/3 behavioral compliance (avg 2.3 behavioral findings), vise-design 3/3 (0). Ban-state is the standout discriminator — missed by all pure-mcp agents, fixed by all vise-design agents through the iteration loop.
604
- - Ambiguous-brief design test: vise-design 0 hex literals (all 3 seeds), pure-mcp 0/2/15 (high variance). Design loop is a variance-reduction tool.
605
- - Grader now partitions findings into behavioral / file-presence / attestation-dialect; headline score is behavioral-only.
628
+ - Brand benchmark (an external brand design system × social.plus community feed): the design loop improved behavioral compliance over a pure-MCP baseline; ban-state was the standout discriminator — missed by the baseline and fixed through the iteration loop.
629
+ - Ambiguous-brief design test: the design loop reduced hex-literal variance versus the baseline a variance-reduction tool.
630
+ - Grader now partitions findings into behavioral / file-presence / attestation-dialect; the headline signal is behavioral-only.
606
631
 
607
632
  ---
608
633
 
package/README.md CHANGED
@@ -106,7 +106,7 @@ Prefer a per-project install? `npm install -D @amityco/social-plus-vise`, then c
106
106
  4. **Build** — the agent edits your code, grounded by `vise search-docs` and `vise get-doc-page`.
107
107
  5. **Check & repair** — `vise check` reports deterministic findings, completeness gaps, and attestation needs. The agent fixes findings or records attestations with evidence, looping until green.
108
108
  6. **Sense** — `vise run-sensors` runs your project's own typecheck/build/lint/SDK smokes. Done means the contract and evidence are committed, not just that the agent stopped.
109
- 7. **Launch and verify** — for any user-visible handoff, ask before spending browser/simulator/emulator/device resources. If approved, open the actual target, check the selected journey, and record what data was discovered or created. Discover targets naturally from host app state, SDK queries, user selection, or SDK create-flow return values; if the tenant has no data, prepare Console data or seed safe sample data before calling the surface populated. When a `sp-vise/smoke.json` contract exists, run `vise smoke` against captured logs; `expect: "populated"` requires `loaded count=N` with `N > 0`. If launch verification is skipped, say what remains unverified.
109
+ 7. **Launch and verify** — for any user-visible handoff, ask before spending browser/simulator/emulator/device resources. If approved, open the actual target, check the selected journey, and record what data was discovered or created. Discover targets naturally from host app state, SDK queries, user selection, or SDK create-flow return values; if the tenant has no data, prepare Console data or seed safe sample data before calling the surface populated. When a `sp-vise/smoke.json` contract exists, run `vise smoke` against captured logs; `expect: "populated"` requires `loaded count=N` with `N > 0`. If runtime proof genuinely can't be produced — the user declines to spend device/emulator resources, or the environment is deviceless — record an honest waiver with `vise smoke waive` (rather than leaving a live surface red-forever or faking evidence); `vise check` then reports `runtime-proof-waived` as an explicit under-claim. If launch verification is skipped, say what remains unverified.
110
110
 
111
111
  ### Solution path & UIKit routing (advisory)
112
112
 
@@ -142,39 +142,41 @@ Vise can ingest your aesthetic from an HTML/CSS prototype (`vise design extract`
142
142
 
143
143
  ## Evidence
144
144
 
145
- Vise is measured against complete brownfield integrations, not isolated snippets. In the real end-to-end benchmark suite, agents were asked to add social.plus to existing product-shaped apps across five platforms. The current scorecard was produced with the Codex GPT-5.4 Medium harness; the protocol is designed for equivalent-tier coding models such as Claude Sonnet 4.6 or Gemini Flash 3.5, with each Vise/no-Vise pair kept on the same model and reasoning setting. The score combines workflow guidance, product surface completion, design fit, correctness, and efficiency. These July 2026 social.plus benchmark runs are directional product evidence from representative app fixtures, not a third-party audit.
145
+ We put Vise through the same brownfield social.plus integration twice per platform once through the **governed Vise workflow**, once from a structured checklist with **Vise switched off** (the control) across five platform families, on a live tenant with no mocking. The precise, uniform benchmark is **Claude Sonnet 5**; we cross-checked the direction with a second agent, **OpenAI Codex GPT-5.4**. Read the direction, not the decimals.
146
146
 
147
- **Current end-to-end scorecard**
147
+ ### Anchor: Claude Sonnet 5, per platform
148
148
 
149
- | Platform | Brownfield product / social goal | With Vise | Without Vise | Improvement |
150
- |---|---|---:|---:|---:|
151
- | **Android** | Investor watchlist app with social circles | **94.3** | 31.2 | **+63.1** |
152
- | **iOS** | Editorial audio app with curator clubs | **90.1** | 43.0 | **+47.1** |
153
- | **Web** | Fitness media app with program communities | **91.4** | 65.6 | **+25.8** |
154
- | **Flutter** | Training clubhouse with squad discussions | **92.8** | 33.0 | **+59.8** |
155
- | **React Native** | Athlete training app with clubhouse feed | **90.3** | 67.3 | **+23.0** |
149
+ Composite score, 0–100 shared scale; every control built and launched.
156
150
 
157
- Average with Vise: **91.8**. Average without Vise: **48.0**. Average improvement: **+43.8 points**.
151
+ | Platform | Fixture | Vise | no-Vise | Δ |
152
+ |---|---|--:|--:|--:|
153
+ | Web | PULSE / pulse-studio | 88.3 | 56.8 | **+31.5** |
154
+ | React Native | Arena Fit | 89.7 | 62.1 | **+27.6** |
155
+ | iOS | Luminary Club | 77.5 | 48.0 | **+29.5** |
156
+ | Android | MarketPulse | 77.5 | 50.1 | **+27.4** |
157
+ | Flutter | Fieldhouse | 78.0 | 48.5 | **+29.5** |
158
+ | **Average** | 5 fixtures | **82.2** | **53.1** | **+29.1** |
158
159
 
159
- **How the score is calculated:** each run is scored from 0-100 across five dimensions, then weighted into one overall score: capability activation (**25%**), product outcome (**25%**), design integration (**20%**), correctness (**20%**), and efficiency (**10%**). In shorthand:
160
+ That **+29.1** full composite still carries the **+90 definitional capability axis** (the control scores 0 there **by construction**). Drop it and re-weight the four fair dimensions to 100%:
160
161
 
161
- ```text
162
- overall =
163
- capability activation * 0.25 +
164
- product outcome * 0.25 +
165
- design integration * 0.20 +
166
- correctness * 0.20 +
167
- efficiency * 0.10
168
- ```
162
+ | | Vise | no-Vise | Δ |
163
+ |---|--:|--:|--:|
164
+ | Full weighted composite (incl. capability axis) | 82.2 | 53.1 | +29.1 |
165
+ | **Credible-only (capability axis removed)** | **83.0** | **70.8** | **+12.1** |
166
+
167
+ **+12.1 is the number to stand behind.** It comes from **Product outcome +17.6** and **Design integration +15.8** (the credible wins); **Runtime hygiene is a near-tie (+1.9** — build/launch cleanliness, which a capable agent clears either way; on Android the checklist control actually built cleaner — this is *not* SDK-rule compliance, see below); **Efficiency +11.7 is a scorer *budget* metric** (the governed arm is **slower** in real time, ~2.7× on web); **Capability activation +90 is definitional**, kept out of the headline. (Deltas use unrounded composites, so hand-subtracting rounded cells can differ by 0.1.)
168
+
169
+ > **Why the hygiene dimension is near-parity — and why that isn't the whole story.** The scorer's `correctness` dimension measures *runtime hygiene* (build, launch, no crashes/secrets/hardcoded IDs), which strong agents clear with or without Vise. It is **not** SDK-rule compliance — the thing the 400+ deterministic rules govern. That is measured directly by a separate **compliance-findings** metric (`vise validate` on both arms' produced source): an ungoverned control carries real rule violations a smoke test never surfaces, and its runtime symptoms already show up as the product-outcome gap above.
170
+
171
+ ### Cross-check: OpenAI Codex GPT-5.4 (directional)
169
172
 
170
- Capability activation measures whether the Vise arm actually used the governed workflow (inspection, Engagement Intelligence selection, blueprint/sign-off artifacts, docs lookup, checks, sensors, and local `sp-vise/` evidence); no-Vise controls intentionally score 0 on that dimension because they must not use Vise. Product outcome and design integration are judged from runtime-visible social surfaces and screenshots. Correctness covers build/runtime hygiene, SDK-backed source, no leaked secrets, no hardcoded social object IDs, and completed handoff. Efficiency rewards validated, SDK-backed outcome delivered within the time/command budget. Caps lower the score when a run is quota-limited, explicitly unfinished, missing a required multi-surface workplan, or proves too little runtime surface coverage. Platform rows enter the head-to-head average only when the Vise and no-Vise arms target the same platform/scenario and are scored with the same launch-verification standard.
173
+ The same A/B run with Codex points the same way **Vise ahead on every platform**. Codex's exact figures are **directional, not precise**: its no-Vise controls are high-variance on Android a single control has read anywhere from **+63** (an unlucky, instrument-affected run on the earlier harness) down to **+27** (clean). Run cleanly on the hardened harness (Android and iOS N=3; Flutter one clean launch, the rest watchdog-blocked), Codex's controls land ~65 and its lift settles around **+25–30**, converging with Sonnet's. Honest cross-model read: **both agents show Vise winning by ~+25–30 once controls are run cleanly.** We anchor on Sonnet because it is the uniform, current-harness run; Codex is cross-model confirmation of direction.
171
174
 
172
- What changed with Vise in the loop:
175
+ ### Methodology & caveats
173
176
 
174
- - The agent starts from a grounded plan instead of guessing the integration shape.
175
- - Product targets are discovered naturally from app state, SDK queries, user choices, or SDK create-flow results, not hardcoded IDs.
176
- - The stopping condition changes from "code was written" to "the requested social surface is planned, checked, and sensor-validated."
177
- - The same workflow applies across web, React Native, Flutter, Android, and iOS.
177
+ - **Vise is the deterministic CLI under test, not an AI model.** Each arm runs the same coding agent on the same brownfield fixture, live tenant, no mocking.
178
+ - **Scoring weights:** capability activation 25% (definitional), product outcome 25%, design integration 20%, runtime hygiene 20% (the scorer's `correctness` key — build/launch cleanliness, not SDK-rule compliance), efficiency 10%. A separate **compliance-findings** metric (`vise validate` on both arms) measures SDK-rule adherence directly. The credible-only composite drops the capability axis and re-weights the other four to 100%.
179
+ - **Small-N, directional.** Controls are n = 1–3 per arm, so neither model is a precise second measurement, and the two are not directly comparable (Codex ran on an earlier harness). The runtime-signal scorer that could over-credit a rendered-but-broken shell is now gated. July 2026 product-evidence runs on representative fixtures — **not a third-party audit**. For a formal comparison, keep each Vise / no-Vise pair on the same model and reasoning setting.
178
180
 
179
181
  <sub>Cursor, Claude, Codex, GitHub Copilot, VS Code, and other product names are trademarks of their respective owners; social.plus is not affiliated with or endorsed by them.</sub>
180
182
 
@@ -206,8 +208,8 @@ Run `vise <command> --help` for full flags. JSON output is the default for agent
206
208
  | `vise plan-harness [path] --request "..."` | Pre-planning step: build the harness around the request |
207
209
  | `vise init [path] --request "..." [--answer key=value]` | Write the `sp-vise/` compliance contract once blocking intake is answered; exits 7 (`needs-clarification`) otherwise |
208
210
  | `vise workplan next [path] --request "..."` | For broad social requests: print the next uncompleted surface and its focused commands |
209
- | `vise workplan status [path] --request "..."` | Show the workplan sequence and completed surfaces |
210
- | `vise workplan complete [path] --request "..." --surface <id>` | Record a green-checked surface; snapshots evidence under `sp-vise/workplan-snapshots/<surface>/` |
211
+ | `vise workplan status [path] --request "..."` | Show the workplan sequence and completed surfaces; ignores unverifiable or drifted snapshot evidence. If the in-scope surface's live `vise check` is already green, auto-records that one surface (same evidence bar as `workplan complete`) so a working, check-green surface isn't left uncounted |
212
+ | `vise workplan complete [path] --request "..." --surface <id>` | Record a green-checked surface; snapshots evidence plus an integrity manifest under `sp-vise/workplan-snapshots/<surface>/` |
211
213
  | `vise workplan trim [path] --request "..." --surface <id> --reason "..."` | Deliberately omit a companion surface (surface-level scope-omit). `--reason` required; re-arms the blueprint sign-off gate (re-sign the trimmed blueprint before proceeding) |
212
214
 
213
215
  ### Creative pre-planning (advisory)
@@ -250,8 +252,9 @@ Everything in this group is local and advisory: no uploads, no `vise check` exit
250
252
 
251
253
  | Command | Purpose |
252
254
  |---|---|
253
- | `vise check [path]` | Re-validate against the recorded contract: `green`, `needs-attestation`, `deterministic-failures`, `blocked`, or `contract-drift` |
255
+ | `vise check [path]` | Re-validate against the recorded contract: `green`, `needs-attestation`, `deterministic-failures`, `blocked`, `contract-drift`, `completeness-gap`, `selected-capability-failures`, `no-platform` (no SDK platform detected — reported as a failure, not a vacuous green), or `runtime-proof-waived` |
254
256
  | `vise check [path] --ci` | Read-only variant that exits non-zero unless green (for CI) |
257
+ | `vise check [path] --allow-proof-waiver` | Accept an honest `runtime-proof-waived` result (from `vise smoke waive`) as passing (exit 0) instead of blocking; without it a waiver blocks CI by default |
255
258
  | `vise check [path] --new-only` | **Brownfield gate.** With a recorded baseline, gate only on findings introduced *since* the baseline (pre-existing ones are reported but excluded). Default `check` always gates on everything |
256
259
  | `vise baseline [path]` | Snapshot the current pre-existing findings to `sp-vise/baseline.json` so `check --new-only` can separate legacy debt from new gaps. `vise init --baseline` records it at init time |
257
260
  | `vise validate [path]` | Run the deterministic validators only (no attestation comparison) |
@@ -266,6 +269,7 @@ Everything in this group is local and advisory: no uploads, no `vise check` exit
266
269
  |---|---|
267
270
  | `vise run-sensors [path] [--dry-run]` | Run detected project scripts (npm, Gradle, Flutter, lint, typecheck, SDK smokes); `--dry-run` lists without executing |
268
271
  | `vise smoke [path] --log <file>` | Assess a captured mount-smoke log into a pass/fail verdict + record evidence. `expect: "populated"` requires `loaded count=N` with `N > 0`; this catches session-establish and empty-data gaps that static checks cannot see |
272
+ | `vise smoke waive [path] --reason "..." [--mode declined\|deviceless]` | Record an auditable runtime-proof waiver when proof is declined or no device/emulator is available, instead of faking evidence. `vise check` then reports `runtime-proof-waived` (exit 9; accept with `--allow-proof-waiver`) rather than a red-forever live surface |
269
273
  | `vise install-skill --target <host>` | Install the bundled skill into a coding host (see [Quick Start](#quick-start)) |
270
274
  | `vise print-skill` | Print the skill markdown to stdout |
271
275
  | `vise engagement init [path] [--tier ...] [--customer-id ...] [--scope ...]` | Record optional contractual scope metadata |
@@ -349,8 +353,8 @@ Vise writes local planning, compliance, design, and evidence artifacts under `sp
349
353
  | `sp-vise/learning-summary.json` | `vise learning record` | Derived summary; `recommendationOptimization.status: "not-active"` |
350
354
  | `sp-vise/flow.json` | `vise workplan next` / `trim` | Entry-state, selected solution path, active blueprint digest, sign-off state, and omitted companion surfaces |
351
355
  | `sp-vise/flow-blueprint.html` | `vise workplan next` | Human-readable blueprint preview for the alignment gate; review before passing `blueprint_confirmation=<digest>` |
352
- | `sp-vise/workplan.json` | `vise workplan complete` | Broad-request progress: completed surfaces, green-check evidence |
353
- | `sp-vise/workplan-snapshots/<surface>/` | `vise workplan complete` | Per-surface snapshots so later focused surfaces don't erase earlier proof |
356
+ | `sp-vise/workplan.json` | `vise workplan complete` | Broad-request progress: completed surfaces, green-check evidence, snapshot integrity digest |
357
+ | `sp-vise/workplan-snapshots/<surface>/` | `vise workplan complete` | Per-surface snapshots plus `snapshot-manifest.json` so later focused surfaces don't erase earlier proof |
354
358
  | `sp-vise/smoke.json` | project/runtime harness | Declared runtime-smoke surfaces and expected resolution states |
355
359
  | `sp-vise/evidence/runtime-smoke.json` | `vise smoke` | Captured runtime-smoke verdicts used by evidence-citing runtime rules |
356
360
  | `sp-vise/design-contract.json` | `vise design extract` | Extracted tokens, breakpoints, source digests, stable design digest |
@@ -133,7 +133,7 @@ export const CAPABILITIES = [
133
133
  label: "Post composer (create)",
134
134
  outcomes: ["add-feed"],
135
135
  symbols: [/\bcreatePost\b/, /PostRepository[\s\S]{0,20}create/i],
136
- hint: "createPost with a dynamic targetType (not a hardcoded literal)",
136
+ hint: "createPost with a valid user/community targetType and targetId bound to app/auth/route state; global feeds are read aggregates, not write targets",
137
137
  },
138
138
  {
139
139
  id: "pinned-posts",
package/dist/flow.js CHANGED
@@ -77,11 +77,11 @@ function surfaceReadiness(stage) {
77
77
  smokeExpectation: "populated",
78
78
  smokeReason: "A feed integration is only product-proven when visible posts render, not just an empty shell.",
79
79
  targetSources: [
80
- "Current-user or global feed when the selected product story supports it.",
80
+ "Global read feed when the selected product story supports aggregate browsing; user or community target for any post composer.",
81
81
  "Selected community returned by the community discovery/create flow.",
82
82
  "Selected profile/user object from host auth, profile, member, follower, or search state.",
83
83
  ],
84
- tenantData: ["A target global, community, or user feed is known, and it contains at least one visible post for the current user."],
84
+ tenantData: ["A global read feed, community feed, or user feed is known, and it contains at least one visible post for the current user. If a composer is included, its write target is user or community, never global."],
85
85
  consolePrep: ["Confirm post permissions, community privacy, review mode, and any selected post-type availability."],
86
86
  noDataFallback: [
87
87
  "Ask whether to create a visible dogfood post in the selected runtime feed target through Console or SDK post creation.",
@@ -6,6 +6,8 @@ const STATUS_GLOSS = {
6
6
  "contract-drift": "The recorded ruleset no longer matches the installed Vise — re-run init.",
7
7
  "completeness-gap": "Required capabilities are neither built nor opted out (scope-omit) yet.",
8
8
  "selected-capability-failures": "A selected optional capability's sensor failed.",
9
+ "no-platform": "No social.plus SDK platform was detected — there is nothing to validate; scaffold or point at a real app surface.",
10
+ "runtime-proof-waived": "Runtime proof was waived (declined / deviceless) — static checks pass but the live-data surface is NOT runtime-proven. Exits non-zero unless --allow-proof-waiver.",
9
11
  "needs-clarification": "Blocking intake questions are unresolved.",
10
12
  };
11
13
  function asString(value) {
package/dist/outcomes.js CHANGED
@@ -1,4 +1,17 @@
1
1
  import { experienceBundleFor } from "./experience.js";
2
+ export const OUTCOME_COMPANIONS = {
3
+ "add-feed": ["add-comments"],
4
+ "add-comments": ["add-feed"],
5
+ "add-community": ["add-feed", "add-comments"],
6
+ };
7
+ export function relatedOutcomes(outcomes) {
8
+ const set = new Set(outcomes);
9
+ for (const outcome of outcomes) {
10
+ for (const companion of OUTCOME_COMPANIONS[outcome] ?? [])
11
+ set.add(companion);
12
+ }
13
+ return set;
14
+ }
2
15
  export function hasAnswer(answers, id) {
3
16
  const value = answers[id];
4
17
  return typeof value === "string" && value.trim() !== "";
@@ -50,6 +63,16 @@ export const PLATFORM_FEATURE_GAPS = [
50
63
  sdkSource: "use-cases/social/livestream/go-live-and-room-management",
51
64
  guidance: "Room-based livestreaming — broadcasting, going live, and room management (RoomRepository.createRoom / getRoom / getRooms / stopRoom) — is NOT in the social.plus Flutter SDK; it is available on the iOS, Android, and TypeScript/web SDKs. The Flutter SDK exposes only the DEPRECATED legacy Stream API (StreamRepository.getStream) for VIEWING existing stream posts — there is no Room API in Dart, so do not invent RoomRepository / createRoom. Options: (a) build the broadcast/host livestream experience on a supported platform (iOS, Android, or TypeScript/web), (b) on Flutter, render an existing legacy stream post read-only via StreamRepository.getStream(streamId) (deprecated — exposes title/status/isLive only), or (c) embed a web livestream view.",
52
65
  },
66
+ {
67
+ feature: "For-You (personalized) feed",
68
+ match: /\bfor[\s-]?you\b|personali[sz]ed\s+feed|curated\s+feed|recommend\w*\s+feed/i,
69
+ exclude: /\brecommend\w*\s+(?:communit|user|friend|people|member)\w*/i,
70
+ unavailableOn: ["flutter"],
71
+ availableOn: ["typescript", "ios", "android"],
72
+ objectIds: ["for-you"],
73
+ sdkSource: "social-plus-sdk/social/content-management/posts/retrieve/for-you-feed",
74
+ guidance: "The social.plus Flutter SDK does not expose the For-You (personalized) feed — getForYouFeed / getForYouFeedSetting are available on the iOS, Android, and TypeScript/web SDKs only. Do not invent a getForYouFeed in Dart. Options: (a) build the For-You surface on a supported platform (iOS, Android, or TypeScript/web), (b) on Flutter, render a community-scoped or user-scoped feed (getCommunityFeed / getUserFeed) or the global feed instead, or (c) call a server-side recommendation API from your backend and surface results through your own endpoint.",
75
+ },
53
76
  ];
54
77
  export function platformFeatureGapsFor(request, platform) {
55
78
  return PLATFORM_FEATURE_GAPS.filter((gap) => gap.unavailableOn.includes(platform) &&
@@ -79,6 +102,7 @@ const REACTION_PATTERNS = [
79
102
  ];
80
103
  const MODERATION_OUTCOME_PATTERNS = [
81
104
  /\b(moderation|report|flag|block user|mute user|hide content|abuse|review queue|admin queue)\b/,
105
+ /\b(?:users?\s+(?:block(?:ing)?|mut(?:e|ing))|(?:block(?:ing)?|mut(?:e|ing))\s+(?:a\s+|the\s+)?users?)\b/,
82
106
  ];
83
107
  const CHAT_PATTERNS = [
84
108
  /\b(chat|messaging|dm|direct message|conversation|group chat|channel|inbox)\b/,
@@ -579,11 +603,11 @@ const addFeed = {
579
603
  });
580
604
  questions.push({
581
605
  id: "feed_target",
582
- question: "What concrete feed target should reads and post creation use?",
583
- why: "Prefer the global (app-wide) feed or the current user's feed for a general social feed both are ID-free, need no membership to post, and are the safe default. The no-invent rule applies to IDs: never invent a communityId, targetId, or feedId. Choose a community target only when the request names a community-scoped surface, and then source it from route/app state, SDK discovery, user selection, or a create flow.",
606
+ question: "What feed source and post creation target should the first feed use?",
607
+ why: "Global feed is a read aggregate from users the viewer follows and communities the viewer joined; it is not a post creation target. If the surface includes a composer, create posts only to a user target (usually the current user) or a community target sourced from route/app state, SDK discovery, user selection, or a create flow. Never invent a communityId, targetId, or feedId.",
584
608
  required: true,
585
609
  blocksImplementationWhenMissing: true,
586
- options: ["app-defined/global feed", "current user's feed", "selected user's feed", "community selected from route/discovery/create flow", "ask user at runtime"],
610
+ options: ["global read feed + current-user post target", "current user's feed + current-user post target", "community feed selected from route/discovery/create flow", "selected user's feed (read-only unless the app owns a valid user post target)", "ask user at runtime"],
587
611
  });
588
612
  questions.push({
589
613
  id: "target_screen_or_route",
@@ -631,7 +655,7 @@ const addFeed = {
631
655
  "lifecycle owner for subscribe/unsubscribe cleanup",
632
656
  "feature choice: feed, comments, profile, community, chat, notifications, or another social surface",
633
657
  "feed scope: global, user, or community",
634
- "concrete feed target for reads and post creation: app-defined/global feed, current user feed, selected user target, or community selected from route/discovery/create flow",
658
+ "feed source and post creation target: global is read-only aggregate; createPost targets must be user or community",
635
659
  "target screen or route for the feed UI",
636
660
  ],
637
661
  implementationRules: () => [
@@ -644,17 +668,17 @@ const addFeed = {
644
668
  : ["requiredInputs.design token or theme source file"];
645
669
  return [
646
670
  {
647
- step: "Confirm the target route/screen, feed scope, and concrete feed target before writing code.",
671
+ step: "Confirm the target route/screen, feed read source, and post creation target before writing code.",
648
672
  evidence: [
649
673
  "requiredInputs.feed scope",
650
- "requiredInputs.concrete feed target",
674
+ "requiredInputs.feed source and post creation target",
651
675
  "requiredInputs.target screen or route",
652
676
  ],
653
677
  },
654
678
  {
655
- step: "Bind targetType and targetId in createPost (and query) calls to the intake-resolved feed target e.g. communityId from route params, userId from auth context, or a prop passed from the screen's caller. A variable or prop that is declared but never wired to the actual target is the same intent gap as a hardcoded literal: the validator fires on literals; the correctness gap fires on unbound variables.",
679
+ step: "Bind feed queries to the intake-resolved read source, and bind createPost to a real write target. A global feed is read-only aggregate; do not call createPost with targetType/global. For a composer, use targetType=user with the current/app-selected user target or targetType=community with a communityId from route params, SDK discovery, user selection, or a create flow. A variable or prop that is declared but never wired to the actual target is the same intent gap as a hardcoded literal: the validator fires on literals; the correctness gap fires on unbound variables.",
656
680
  evidence: [
657
- "requiredInputs.concrete feed target",
681
+ "requiredInputs.feed source and post creation target",
658
682
  "requiredInputs.feed scope",
659
683
  ],
660
684
  },
@@ -791,8 +815,8 @@ const addFeed = {
791
815
  "profile.social-counts",
792
816
  ],
793
817
  stopConditions: (ctx) => filterStops(ctx.answers, [
794
- { id: "feed_target", text: "The concrete feed target is unknown; never invent a communityId, targetId, or feedId. For a general social feed, default to the ID-free app-wide global feed or the current user's feed; reserve a specific community/target for an explicitly community-scoped request." },
795
- { id: "feed_target", text: "If post creation is in scope, the write target must be a concrete feed the global or current-user feed (no id, no membership needed), or a community/selected target the user or app state provides (never a hardcoded or invented id)." },
818
+ { id: "feed_target", text: "The feed source and post creation target are unknown; never invent a communityId, targetId, or feedId. For a general social feed, a global feed may be the read source, but composer writes must target a user or community." },
819
+ { id: "feed_target", text: "If post creation is in scope, the write target must be user or community. Global feed is an aggregate read surface from followed users and joined communities, not a createPost target." },
796
820
  ]),
797
821
  resolvePlan: () => [
798
822
  {