@amityco/social-plus-vise 0.14.27 → 1.0.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 +81 -0
- package/README.md +9 -14
- package/dist/capabilities.js +44 -0
- package/dist/server.js +7 -1
- package/dist/tools/ast.js +302 -25
- package/dist/tools/blocks.js +95 -2
- package/dist/tools/compliance.js +15 -4
- package/dist/tools/docs.js +48 -0
- package/dist/tools/harness.js +114 -1
- package/dist/tools/project.js +106 -11
- package/dist/tools/sdkFacts.js +128 -7
- package/dist/tools/sensors.js +30 -0
- package/docs-cache/README.md +34 -0
- package/docs-cache/social-plus-sdk/core-concepts/foundation/logging.mdx +236 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/live-objects-collections/android.mdx +262 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/live-objects-collections/flutter.mdx +195 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/live-objects-collections/ios.mdx +452 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/live-objects-collections/overview.mdx +133 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/live-objects-collections/typescript.mdx +264 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/push-notifications/register-and-unregister-push-notifications-on-a-device.mdx +191 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/push-notifications/settings/overview.mdx +43 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/push-notifications/setup/android-setup.mdx +360 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/push-notifications/setup/flutter-setup.mdx +457 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/push-notifications/setup/ios-setup.mdx +423 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/push-notifications/setup/react-native-setup.mdx +384 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/realtime-events/overview.mdx +94 -0
- package/docs-cache/social-plus-sdk/getting-started/authentication.mdx +808 -0
- package/docs-cache/social-plus-sdk/getting-started/platform-setup/mobile/android-quick-start.mdx +304 -0
- package/docs-cache/social-plus-sdk/getting-started/platform-setup/mobile/flutter-quick-start.mdx +121 -0
- package/docs-cache/social-plus-sdk/getting-started/platform-setup/mobile/ios-quick-start.mdx +225 -0
- package/docs-cache/social-plus-sdk/getting-started/platform-setup/web/web-quick-start.mdx +99 -0
- package/docs-cache/social-plus-sdk/social/communities-spaces/organization/community-invitation.mdx +459 -0
- package/docs-cache/social-plus-sdk/social/communities-spaces/organization/join-leave-community.mdx +449 -0
- package/docs-cache/social-plus-sdk/social/communities-spaces/organization/query-community-members.mdx +376 -0
- package/docs-cache/social-plus-sdk/social/content-management/posts/creation/text-post.mdx +318 -0
- package/docs-cache/social-plus-sdk/social/discovery-engagement/notifications/notification-tray-status.mdx +399 -0
- package/docs-cache/social-plus-sdk/social/user-relationship/blocking/block-unblock-user.mdx +166 -0
- package/docs-cache/social-plus-sdk/social/user-relationship/following/get-follower-following-list.mdx +339 -0
- package/package.json +15 -3
- package/scripts/dart-model-extractor/bin/extract_models.dart +169 -0
- package/scripts/dart-model-extractor/pubspec.lock +149 -0
- package/scripts/dart-model-extractor/pubspec.yaml +16 -0
- package/scripts/extract-sdk-models.mjs +749 -0
- package/scripts/import-sdk-surface.mjs +52 -21
- package/sdk-surface/manifest.json +48 -2
- package/sdk-surface/models.android.json +990 -0
- package/sdk-surface/models.flutter.json +980 -0
- package/sdk-surface/models.ios.json +980 -0
- package/sdk-surface/models.typescript.json +1304 -0
- package/skills/social-plus-vise/SKILL.md +15 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,87 @@ 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
|
+
## 1.0.0 — 2026-06-11
|
|
8
|
+
|
|
9
|
+
**First stable release.** 1.0 is a stability promise about the contract surface, not a new feature: `vise check` exit codes (0–7) and their precedence, the `sp-vise/` sidecar formats (with backward-read + attestation grandfathering now gated by `test:sidecar-compat`), the CLI command and MCP tool surface, the skill's required loop, and the `packages/schemas` wire formats are now under semver — breaking changes require a major bump. See [`docs/V1_READINESS.md`](docs/V1_READINESS.md) for the decision package and evidence basis (5-platform deterministic E2E journeys with all exit codes asserted on every commit; real-agent semantic matrix; three brownfield pilots green with zero Vise findings). This release consolidates everything developed across the 0.14.x-dev line after the published 0.14.28 (block-aware completeness): the items below plus the platform-hardening and model-facts work noted under the 0.14.28 entry, which reached npm here.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
- **Skill: prefer installable blocks over hand-building.** When a Block Factory registry is available, agents are taught to check it first and use the governed `vise blocks` install path, hand-building only the remaining gaps — backed by the 2026-06-10 semantic-matrix measurement (installed path ~9× faster to green than hand-building the same outcome). No registry means hand-build as normal; block existence stays the registry's truth.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- **False-negative discovery lane — the third compass (`docs/FN_DISCOVERY.md`).** Vise already had a TP-detection compass (`bench/tp-dashboard.mjs`, seeded from the rules so circular) and an FP compass (happy-path-clean + clone cells + pilots) but NO systematic false-NEGATIVE discovery — violations the rule corpus misses only surfaced by accident. This lane closes that, mirroring the semantic lane's two-half split:
|
|
16
|
+
- **Measured lane (periodic, never CI)** — `benchmarks/fn-discovery/run-fn-discovery.mjs`: for a chosen rule, hand a real coding agent the rule's INTENT (title + rationale from `rules/*.yaml`, NOT its detector) and ask for SDK-using samples that violate that intent in novel ways; run `vise validate --json` over each; grade CAUGHT vs MISSED; write append-only dated evidence (samples + validate output + `FINDINGS.md`) under `benchmarks/fn-discovery/runs/<date>-<rule>-<generator>/`. Scoped first to TypeScript × secrets/ban-state/feed-target/session-lifecycle. Generator policy mirrors the semantic lane (default `agy`; `agent`; `claude` pinned to Sonnet). Built and proven with a **deterministic STUB generator** (default) so the grading core is testable without spawning agents or spending tokens; the real-agent path is wired but invoked only with `--generator`, and the live discovery round runs later with explicit human authorization.
|
|
17
|
+
- **Deterministic gate (CI)** — `test/run-fn-regression.mjs` (`test:fn-regression`): a frozen corpus under `test/fixtures/fn-regression/` of previously-discovered false negatives. `fires` entries assert a rule now fires on a committed sample of a class it once missed (so a fixed blind spot can't silently return); seed entries are realistic catches labeled scaffold so the gate is real and grows; quarantined entries are REAL discovered misses asserted to stay missed until a fix lands, then the gate flips loud and the entry is promoted. The gate never patches a rule — fixes are harness-engineering work with their own review.
|
|
18
|
+
- **Self-test** — `test/run-fn-discovery-selftest.mjs` (`test:fn-discovery-selftest`): runs the stub samples through the real validator + real grader and asserts every CAUGHT/MISSED/CLEAN-OK verdict against the stub's oracle, locking down the lane's plumbing. Both new gates run in `validate` right after `test:harness-e2e`.
|
|
19
|
+
- **Real false negatives discovered while building (TypeScript):** (1) `secret.inline-api-key` missed a hardcoded key re-wrapped through a template string before `createClient` (`resolveLiteralValue` resolved direct literals only); (2) `feed.target.literal` missed a feed-target literal re-bound through a second const before `createPost` (the AST resolver followed one identifier hop); (3) `feed.target.literal` missed a hardcoded feed target when the `createPost` payload carried an `as any` cast (`pickObjectProperty` required a bare object node). Controls proved the rules fire at the single-hop / un-cast forms. **All three were then fixed in this release** (see Fixed, below); their corpus entries are promoted from quarantine to `fires`, so each blind spot can never silently reopen.
|
|
20
|
+
- **iOS and Flutter model facts upgraded to `names-and-types`** (previously names-only): `scripts/extract-sdk-models.mjs` now grounds both platforms in typed sources instead of the type-less docs-ops surface exports, completing the per-platform grounding table (typescript/android/ios/flutter all names-and-types). Wire format unchanged (`2026-06-10.sdk-model-facts.v1` — names-and-types was already a legal grounding); the `extraction.sourceKind` enum gains `sdk-swiftmodule-abi` and `sdk-source-dart` in `packages/schemas`.
|
|
21
|
+
- **iOS** — parsed from the prebuilt AmitySDK xcframework's Swift module ABI JSON, canonically the **`ios-arm64` device slice** (the architecture customers ship and the only single-arch slice; the simulator slices were diffed member-for-member identical for the target models). Fields carry the compiler-printed Swift type (`Swift.String?`, `[AmitySDK.AmityCommentAttachment]`) and Optional-wrapper nullability; `declaredIn` stays `null` because a prebuilt binary has no source locations. Discovery follows the import script's pattern: `--ios-abi-json` / `SP_IOS_ABI_JSON`, then the docs-repo-relative `.docs-ops/integration-tests/ios/vendor/AmitySDK.xcframework/...` location beside the surface dir.
|
|
22
|
+
- **Flutter** — parsed from the local Flutter SDK sources by the new `scripts/dart-model-extractor` helper (package:analyzer `parseString`, **syntax-only**: verbatim declared types and literal `?` nullability, no resolution or inference; analyzer version pinned by the committed `pubspec.lock` and recorded in the extraction provenance). Public instance fields and getters only; untyped members are skipped rather than invented. Real file:line anchors into the SDK checkout. Discovery: `--flutter-sdk-root` / `SP_FLUTTER_SDK_ROOT`, then the `Amity-Social-Cloud-SDK-Flutter-Internal` checkout beside `social-plus-docs`.
|
|
23
|
+
- **Degradation, recorded:** when the `.abi.json`, the Flutter checkout, or the `dart` toolchain is unreachable at import time, the platform falls back to the previous names-only surface-export extraction and the manifest records a `degradedReason` — grounding never exceeds what the reachable source proves, and the snapshot gates refuse a degraded re-import of the committed names-and-types artifacts. npm tarball 495.2 kB → 503.9 kB (regenerated typed snapshots + the Dart helper).
|
|
24
|
+
|
|
25
|
+
### Verified (typed iOS/Flutter model facts)
|
|
26
|
+
- `test:sdk-surface` locks the new grounding with real extracted fields: iOS `AmityComment.commentId` as required `Swift.String` and `parentId` as optional `Swift.String?` from the arm64 abi.json (plus all-fields-typed and no-source-locations invariants), Flutter `AmityComment.commentId` as nullable `String?` property anchored to `lib/src/domain/model/amity_comment.dart` and `AmityUser.isFlaggedByMe` as a non-nullable `bool` getter.
|
|
27
|
+
- `test:sdk-facts` serves the typed schemas end to end (`AmityPost.postId` → `Swift.String` on iOS; source-anchored `AmityComment` on Flutter) with the new extractor ids recorded.
|
|
28
|
+
- The schemas self-test now expects names-and-types on every platform and proves the extended `sourceKind` enum bites (doctored unknown sourceKind fails validation).
|
|
29
|
+
- Block Factory seam unchanged by design: contracts are still TypeScript-provenance only, so `validate:sdk-facts` / `validate:adapters` pass untouched; the typed iOS/Flutter facts are ready for future native-platform `sdkProvenance`.
|
|
30
|
+
|
|
31
|
+
### Verified
|
|
32
|
+
- **Harness E2E platform matrix completed (`test:harness-e2e`):** the deterministic lane-1 journey now runs for **flutter** and **ios** alongside typescript and android — each with the complete journey, no partial credit (HARNESS_E2E.md). Per-platform discoveries baked into the gate: flutter/ios block on `feed_scope`/`feed_target`/`target_screen_or_route` only; `flutter-happy-path` *is* the add-feed gap state (zero-rule clean, no pagination affordance), so its known-good implementation is a structural Dart pagination helper (naming `AmityCollection` would trip the flutter `feed.ui-states-present` sensor); the ios pre-implementation state removes `AppTheme.swift` together with `FeedViewController.swift` because the feed view is the theme's only consumer (`ios.design.reuse-detected-tokens` would otherwise mask the exit-5 gap); the exit-2 injection reuses the rule-coverage-proven `flutter-rule-missing-guards` / `ios-rule-missing-guards` files, which pair the attestation-disallowed `<platform>.secret.inline-api-key` driver with attestation-level findings in one file.
|
|
33
|
+
- **Exit-4 (`contract-drift`) stage:** every platform journey now tampers the recorded `rule_digest` of its feed-target rule in `sp-vise/compliance.json` and asserts `vise check --ci` exits **4** with status `contract-drift`, naming the drifted rule (`stale`, "Rule digest changed since vise init"); restoring the contract bytes restores green. Lane 1 now asserts all documented exit codes 0–7.
|
|
34
|
+
- **Environment-aware iOS sensors stage:** the guarded xcodebuild sensor is asserted in *both* environments on every machine via a controlled `PATH` (stub toolchain → integrity probe + guarded build detected; empty `PATH` → the single skipped-with-reason precondition), so `test:harness-e2e` passes identically on darwin-with-Xcode and ubuntu CI without it.
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
- **Three confirmed TypeScript false negatives closed (resolver/extractor precision; behavior-parity — no rule id/severity/semantics change).** All three were surfaced by the FN-discovery lane above and verified with single-hop/un-cast controls: (1) `secret.inline-api-key` now resolves a pure-passthrough template (`` `${X}` `` ≡ `X`) — a committed production key re-wrapped through a template no longer ships undetected; (2) `feed.target.literal` now does bounded multi-hop identifier resolution (depth cap + cycle guard) so a const aliased through another const still resolves — and the shared resolver means **Kotlin/Swift re-bind chains benefit too**; (3) a new `unwrapExpression` peels `as`/`satisfies`/parenthesized/non-null wrappers before object-property extraction, so a hardcoded target inside `createPost({…} as any)` is caught (high-frequency, since agents emit `as any` constantly). Each broadening is guarded against false positives by a dedicated dynamic-clean canary (member-access / parameter / `process.env`-sourced values must stay clean), and `happy-path-clean` (the 5-platform FP canary) stays at zero findings.
|
|
38
|
+
|
|
39
|
+
### Added (sidecar compatibility + hermetic docs)
|
|
40
|
+
- **`test:sidecar-compat` — the backward-read gate (the semver promise 1.0 makes).** A frozen corpus of authentic `sp-vise/` sidecars generated by the real published `0.14.26` / `0.14.27` / `0.14.28` (`npx … vise init/sync/attest`, provenance recorded per version — not hand-authored) is replayed by the current build, asserting tolerant reads (no crash/parse-failure, coherent status, older `vise_version`/`foundry_version` tolerated, no unknown old-contract rule) and exercising attestation grandfathering live for the first time against a real v1-era host-agent attestation (`compatible_with` honored; `deprecated_versions` honored and flagged for re-attestation; empty `compatible_with` softens to `attestation-needed`, never a hard fail). Boundary: this covers backward reads (old sidecar, new build — the direction 1.0 promises), not forward compatibility.
|
|
41
|
+
- **Hermetic docs CI mode (`VISE_DOCS_OFFLINE=1`).** Doc lookups can serve a committed `docs-cache/` corpus instead of fetching `learn.social.plus`; CI runs hermetic by default, killing the network-flake class. `test:docs-offline` proves zero network dependency (sinkhole host + 1 ms timeout, with an empty-corpus negative control that fails loudly rather than silently hitting the network); the live-fetch path is preserved off the critical path as `test:docs-live`.
|
|
42
|
+
|
|
43
|
+
## 0.14.28 — 2026-06-10
|
|
44
|
+
|
|
45
|
+
> **Note (reconciled at 1.0.0):** the published npm `0.14.28` tarball shipped **block-aware completeness** (and the schemas-seam refactor). The platform-hardening (Swift tree-sitter AST, the guarded iOS build sensor) and field-level model facts described below were committed after that publish and first reached npm in **1.0.0** — they are documented here because that is where the work was authored; the version they shipped in is 1.0.0.
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
**Theme:** block-aware completeness — install a block, end green. Plus platform-leg hardening: Swift gets the tree-sitter treatment and iOS gets a guarded build sensor.
|
|
50
|
+
|
|
51
|
+
### Added
|
|
52
|
+
- **Field-level SDK model facts (sdk-facts Phase 4):** `vise sdk-facts` / `get_sdk_facts` no longer prove symbol existence only. The bundled snapshot now includes `sdk-surface/models.<platform>.json` (wire format `2026-06-10.sdk-model-facts.v1`, owned by `packages/schemas/model-facts.schema.json` with a type-only TS twin) carrying capability-anchored model schemas — per field: `name`, `type` (the platform's own string form), `optional`, `memberKind`, and `declaredIn` source anchor — plus full extraction provenance (extractor id/version, timestamp, upstream docs-ops extractor, upstream git commit). `--include-models` (MCP `includeModels`) serves the schemas; capability model entries gain a verbatim `schema`; every result carries a `modelFacts` status so absence is explicit.
|
|
53
|
+
- **Extraction-grounded by construction:** `scripts/extract-sdk-models.mjs` (run by `sdk-surface:import`) grounds each platform mechanically — TypeScript via the compiler API over the local SDK sources (`names-and-types`, including `?` optionality and file:line), Android via dokka signature data (`names-and-types`, Kotlin `?` nullability, doc-prose stripped), iOS/Flutter as `names-only` because their docc-abi/dart exports carry no type data (the schema then forces field `type`/`optional` to `null` — fabricated detail cannot validate). A platform whose field source is unreachable ships no model file and the manifest records why. Scope is limited to the first factory capabilities (comments, reactions, posts, users): npm tarball grew 479.2 kB → 484.2 kB.
|
|
54
|
+
- **Reaction model anchors:** the `reactions` capability now also anchors `Amity.Reactor` and `Amity.Reactable` (the reaction-summary shape blocks actually consume), alongside `Amity.Reaction`.
|
|
55
|
+
|
|
56
|
+
### Verified (model facts)
|
|
57
|
+
- `test:sdk-surface` locks the manifest `models` map (sha256, per-platform grounding) and one real extracted model per platform — including that `Amity.Comment` carries `userId` but **not** the imagined `creatorId`/`isHidden` fields that previously lived in hand-written factory fixtures.
|
|
58
|
+
- `test:sdk-facts` covers `modelFacts` status, capability schema attachment, `includeModels` capability filtering, names-only null enforcement, and the CLI `--include-models` path.
|
|
59
|
+
- The schemas package self-test validates every committed snapshot against `model-facts.schema.json` and proves the schema bites (11 doctored snapshots fail, including fabricated types under names-only grounding).
|
|
60
|
+
- **Swift AST validators (tree-sitter-swift 0.7.x):** the highest-false-positive-risk iOS rules move from regex to the same tree-sitter helper layer Kotlin uses (`tree-sitter-swift` is the maintained alex-pinkus grammar; its node shapes descend from the Kotlin grammar, so `findCallExpressions` shares the walk and adds Swift labeled-argument extraction via the new `pickLabeledArgument`). Migrated rules — ids, severities, and pass/fail semantics unchanged, only precision improved:
|
|
61
|
+
- `ios.auth.no-literal-user-id`, `ios.secret.inline-api-key`, `ios.feed.target.literal` now resolve **indirect literals** (`let FALLBACK_USER = "demo-user-42"` … `login(userId: FALLBACK_USER)`) that the call-site regex could never see — proven by the new `ios-userid-via-constant` / `ios-secret-via-constant` / `ios-feed-target-via-constant` fixtures.
|
|
62
|
+
- `ios.session-handler.retained` asks the real scope question (is the binding inside a function body?) instead of bridging 200 chars from any `func … {`. A bare class-scope `let sessionHandler = …` directly after a short function used to false-fire (the rescue pattern demanded an access modifier); the new `ios-session-handler-class-scope-bare` fixture locks the fix. Type-annotated locals (`let h: AmitySessionHandler = …`) the regex bridge missed are now caught.
|
|
63
|
+
- `ios.user.ban-state-respected` detects its interaction surface on the comment-stripped view — `// TODO: wire createPost here` no longer counts as an interaction (new `ios-ban-state-comment-only` fixture); the `// vise: ban state checked at` escape hatch deliberately stays on raw text.
|
|
64
|
+
- All Swift gate rules now use the precise tree-sitter comment stripper, chained onto the conservative scanner so bindings-unavailable/oversized files degrade to the previous behavior, never to raw text. `ios-happy-path` stays at zero findings (FP canary), and a missing `tree-sitter-swift` prebuild degrades only the Swift helpers — ts/tsx/kotlin AST stays up.
|
|
65
|
+
- **Dart AST honestly skipped:** every Dart grammar on npm fails against the pinned `tree-sitter@^0.21` (stale nan binding, ≥0.22-only API, forked core, WASM-only, or an unmaintained vendor-internal fork). Dart rules remain regex + conservative scanner; the verdict and re-evaluation trigger are recorded in ARCHITECTURE.md.
|
|
66
|
+
- **iOS build sensor — guarded best-effort (revises the old "xcodebuild is too fragile to wire" decision):** an `.xcodeproj`/`.xcworkspace` at the surface root now enables two sensors, **only when `xcodebuild` is on PATH** — absent, `vise run-sensors` reports the sensor `skipped` with the install-Xcode precondition (the pf-003 visible-precondition pattern) instead of returning no-sensors. When runnable: a cheap `xcodebuild -list` integrity probe, then a bounded-timeout build with signing disabled (`CODE_SIGNING_ALLOWED=NO`/`CODE_SIGNING_REQUIRED=NO`/`CODE_SIGN_IDENTITY=`). Non-zero exits are classified before being reported: environment-caused failures (Command-Line-Tools-only `xcode-select`, unaccepted Xcode license, signing/provisioning demands, missing simulator/SDK destination, undeterminable workspace scheme) become **skipped-with-reason and exit 0** — never project failure — while real compile/link errors stay `failed` with a non-zero CLI exit (pf-004-era semantics). The classification channel is a new serializable `environmentSkips` field on command sensors, available to any future toolchain with the same exit-code conflation. Locked by a stub-`xcodebuild` controlled-PATH matrix in `test:sensors` (detected+green, detected+real-failure, environmental skips, absent toolchain).
|
|
67
|
+
- **Installed blocks satisfy completeness baselines:** `vise check` previously scanned customer source only, so a capability delivered inside an installed Block Factory package (e.g. the Comments block's composer) still reported `completeness-gap` (exit 5). Now a checklist capability counts as present with evidence `source: "block:<blockId>"` (and a note naming the block) when an installed sidecar entry declares it and the install is still locally valid.
|
|
68
|
+
- **Factory declares, Vise validates:** Block Factory contracts declare `providesCapabilities` using Vise's completeness-checklist id vocabulary (Vise owns the id space, the factory owns the per-block claim; an empty list is legitimate — the Reactions block provides no baseline ids). `vise blocks plan`/`add` carry the registry entry's ids into the install plan and `--apply` records them — plus the manifest `dependencyName` — in `sp-vise/blocks.json` (sidecar `schemaVersion` bumped to `2026-06-10.vise-blocks-sidecar.v1`).
|
|
69
|
+
- **Seam guard:** `vise blocks plan`/`add`/`validate` emit a `blocks.providesCapabilities.known` **warning** finding (never a failure) for declared ids outside Vise's completeness vocabulary; unknown ids never satisfy a gap.
|
|
70
|
+
|
|
71
|
+
### Changed
|
|
72
|
+
- **Skill: bounded-turn stop guidance.** Agents running in one-shot/print mode are told to reach a `vise check` verdict before the turn ends rather than ending mid-environment-setup (finding from the first semantic harness-E2E measurement).
|
|
73
|
+
- **Gap returns on drift:** the block evidence is registry-free and re-validated on every `vise check` — the block's dependency must still be declared in the project manifest and every recorded `filesTouched` path must exist. Remove the touched source file or the package and the capability reverts to the normal `completeness-gap`. Pre-`0.14.28` sidecar entries carry no package evidence and fail closed.
|
|
74
|
+
|
|
75
|
+
### Verified
|
|
76
|
+
- `test:ast` extended with the Swift section: grammar availability, labeled-argument call extraction, identifier→literal resolution (with the env-fallback `?? ""` and interpolated-string non-resolution cases), comment stripping that preserves `//` inside strings, function-local vs type-scope handler declarations, the three indirect-literal fixtures, and the two false-positive-kill fixtures (each verified to fire under the pre-change regexes). `ios-happy-path` asserted at zero findings; existing `ios-session-handler-local-var`/`-retained` pass/fail semantics asserted unchanged.
|
|
77
|
+
- `test:sensors` gains the stub-`xcodebuild` controlled-PATH matrix: detection with/without the toolchain, detected+green (exit 0), detected+real-build-failure (exit 1, not environment-skipped), no-simulator and CLT-only environmental skips (exit 0), and the absent-toolchain skip end to end.
|
|
78
|
+
- New `test:blocks-completeness` gate: real `blocks add --apply` against the monorepo Block Factory registry, init with answers, `check --ci` green via `block:comments` evidence, gap restored after deleting a touched file and after removing the manifest dependency, empty `providesCapabilities` tolerated end to end, and the unknown-id warning on a doctored registry.
|
|
79
|
+
- The Block Factory react target-project journey (`validate:target-projects:react`) now asserts the full install journey ends **green** with `comment-composer` satisfied by `block:comments`.
|
|
80
|
+
|
|
81
|
+
### Internal
|
|
82
|
+
- **Registry seam contract extracted to `packages/schemas`:** the block-registry wire format and the `sp-vise/blocks.json` sidecar shape now live in the root workspace package `@amityco/social-plus-schemas` (private, unpublished) — a JSON Schema (`registry.schema.json`) enforced on the factory's `validate:registry`, plus the TypeScript types formerly hand-written in `src/tools/blocks.ts`. Vise imports them **type-only** via a `workspace:*` devDependency, so nothing from the package survives into the published `dist/` (proven by the packed-tarball E2E). Type-only refactor; no behavior change.
|
|
83
|
+
|
|
84
|
+
### Fixed
|
|
85
|
+
- **Attestation evidence fingerprints no longer truncate prose-embedded paths:** the source-path extractor's extension alternation was shortest-first, so `.tsx`→`.ts`, `.json`→`.js`, and `.kts`→`.kt` inside evidence prose silently recorded no fingerprint (weakening drift detection for that attestation). Found by the harness E2E attestation stage, which now cites paths in prose as the standing regression test.
|
|
86
|
+
|
|
87
|
+
|
|
7
88
|
## 0.14.27 — 2026-06-10
|
|
8
89
|
|
|
9
90
|
**Theme:** social-plus-forge monorepo move. No runtime behavior changes.
|
package/README.md
CHANGED
|
@@ -77,9 +77,9 @@ Vise validates on three layers, and the layer is set by the *kind of claim* —
|
|
|
77
77
|
|---|---|---|---|
|
|
78
78
|
| **SDK compliance** | "this is **wrong**" | 300+ deterministic rules (session renewal, live-collection vs one-shot, no secret in logs, parent-child rendering, ban-state gating…) | **Hard gate** — `vise check` blocks until green or attested. A small advisory subset surfaces as informational only and never blocks. |
|
|
79
79
|
| **Design conformance** | "this **looks off**" | extract the customer's design system into a contract, render a preview for confirmation, then check token usage | **Advisory** — `vise design check`/`preview`; never fails a build |
|
|
80
|
-
| **Feature completeness** | "this is **missing**" | Vise proposes a narrow baseline per outcome; for add-feed, pagination is mandatory, for add-comments, the composer/write affordance is mandatory, for add-chat, send plus read/unread state are mandatory, and for add-follow/profile, SDK-backed follower/following data is mandatory, while richer feed capabilities are opt-in choices from `vise plan` | **Decision gate** — `vise check` exits `completeness-gap` until each baseline capability is built or validly opted out; selected optional capabilities run separate sensors |
|
|
80
|
+
| **Feature completeness** | "this is **missing**" | Vise proposes a narrow baseline per outcome; for add-feed, pagination is mandatory, for add-comments, the composer/write affordance is mandatory, for add-chat, send plus read/unread state are mandatory, and for add-follow/profile, SDK-backed follower/following data is mandatory, while richer feed capabilities are opt-in choices from `vise plan` | **Decision gate** — `vise check` exits `completeness-gap` until each baseline capability is built, satisfied by an installed Block Factory block (evidence `source: "block:<id>"`, re-validated locally on every check), or validly opted out; selected optional capabilities run separate sensors |
|
|
81
81
|
|
|
82
|
-
Correctness is gated by deterministic rules or attestations. Baseline completeness is gated by explicit scope decisions: if a baseline capability is legitimately out of scope, record `// vise: scope-omit <id> — <reason>` and it no longer blocks. Optional feed capabilities such as image upload, poll creation, and edit post are offered during planning and become checked only after the user opts in. Conformance remains advisory because "matches the brand" is legitimately subjective. See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md).
|
|
82
|
+
Correctness is gated by deterministic rules or attestations. Baseline completeness is gated by explicit scope decisions: if a baseline capability is legitimately out of scope, record `// vise: scope-omit <id> — <reason>` and it no longer blocks. Installed Block Factory blocks count too: the factory declares the completeness ids a block provides (`providesCapabilities`), `vise blocks add --apply` records them in `sp-vise/blocks.json`, and `vise check` honours them only while the block's manifest dependency and touched files are intact — on drift the gap returns. Optional feed capabilities such as image upload, poll creation, and edit post are offered during planning and become checked only after the user opts in. Conformance remains advisory because "matches the brand" is legitimately subjective. See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md).
|
|
83
83
|
|
|
84
84
|
### Engagement Intelligence roadmap
|
|
85
85
|
|
|
@@ -89,13 +89,7 @@ The current milestone is the **Learning Engine sensor bridge with score calibrat
|
|
|
89
89
|
|
|
90
90
|
### Relationship to social.plus Block Factory
|
|
91
91
|
|
|
92
|
-
Vise
|
|
93
|
-
|
|
94
|
-
- **Customer integration helper:** runs inside customer projects to inspect, plan, validate, and sensor-check social.plus SDK integrations.
|
|
95
|
-
- **Block Factory SDK facts provider:** internal mode for social.plus Block Factory to verify SDK capabilities, symbols, and model schemas before reusable blocks are generated or released.
|
|
96
|
-
- **Block installer governance:** customer-project workflow that consumes a Block Factory registry, plans safe package/source changes, writes `sp-vise/blocks.json`, and validates installed block state.
|
|
97
|
-
|
|
98
|
-
Vise owns SDK truth and customer-project governance. social.plus Block Factory owns block contracts, package adapters, registry metadata, previews, conformance tests, and release readiness. See [docs/SDK_FACTS_FOR_BLOCK_FACTORY.md](docs/SDK_FACTS_FOR_BLOCK_FACTORY.md) for the internal provider-side plan.
|
|
92
|
+
Vise keeps two deliberately separate personas — the **customer-integration helper** (runs inside customer projects, may write `sp-vise/*`, including the `vise blocks` installer workflow) and the **Block Factory SDK-facts provider** (projectless, read-only, exports SDK symbol/capability/model facts). Vise owns SDK truth and customer-project governance; Block Factory owns the blocks. The canonical ownership table and the seam contracts live in [`../docs/BOUNDARY.md`](../docs/BOUNDARY.md); the provider-side design is [docs/SDK_FACTS_FOR_BLOCK_FACTORY.md](docs/SDK_FACTS_FOR_BLOCK_FACTORY.md).
|
|
99
93
|
|
|
100
94
|
### Block Factory user experience
|
|
101
95
|
|
|
@@ -167,7 +161,7 @@ Aggregate: **98/99 expected feed capabilities** and **27/27 selected optional ca
|
|
|
167
161
|
|
|
168
162
|
### Current Release Validation
|
|
169
163
|
|
|
170
|
-
Version 0.
|
|
164
|
+
Version 1.0.0 carries current release proof around the full feed-forward, product-expectation, creative pre-planning, block-aware completeness, and validation flow:
|
|
171
165
|
|
|
172
166
|
| Surface | What was validated |
|
|
173
167
|
|---|---|
|
|
@@ -180,7 +174,8 @@ Version 0.14.26 carries current release proof around the full feed-forward, prod
|
|
|
180
174
|
| **Experience Score calibration guard** | Experience Report, Experience Sensors, and Learning Engine snapshots keep `score: null`, while `learning-summary.json` keeps `recommendationOptimization.status: "not-active"`. The shadow benchmark has 70 measured cells; `shadow-policy-v2-draft` independently ranked expected variants first in 21/21 registered ranking/cross-platform cells, its human gate package has named product FP/FN and privacy sign-off recorded, and runtime exposure is limited to the opt-in local `vise creative --ranking-preview` artifact. |
|
|
181
175
|
| **Android workplan dogfood** | A brownfield Android music-player app refreshed under `0.14.24` reached `vise check` green with **43/43 deterministic passes** on the focused feed surface and recorded a green-check workplan snapshot. This is dogfood evidence, not a controlled multi-agent benchmark. |
|
|
182
176
|
| **Shared product expectations** | Public IDs such as `feed.target-resolved`, `feed.post-type-scope-explicit`, `comments.creation-affordance`, `chat.channel-list-order-explicit`, `community.avatar-from-sdk`, `moderation.role-gated-action`, `follow.relationship-live`, `profile.identity-from-sdk`, `profile.social-counts`, and `notifications.tray-live` stay platform-agnostic while check results retain concrete `contractRuleId` and `validator.sensorId` evidence when deterministic sensors exist. |
|
|
183
|
-
| **Rule detection** | TP-track dashboard detects **
|
|
177
|
+
| **Rule detection** | TP-track dashboard detects **100% of seeded rule gaps** in the static corpus (run `npm run bench:tp` for the current seeded count; `npm run validate`'s rule-coverage gate prints the full corpus size). |
|
|
178
|
+
| **Block-aware completeness** | An installed Block Factory block satisfies its declared baseline capabilities: `vise check` counts a checklist item as present with evidence `source: "block:<id>"` when the `sp-vise/blocks.json` entry declares it in `providesCapabilities` and the install is still locally valid (dependency declared, touched files present), and the gap returns on drift. Field-level SDK model facts (`sdk-surface/models.<platform>.json`, wire format `2026-06-10.sdk-model-facts.v1`) ship for all five platform surfaces, names-and-types on every grounded platform. |
|
|
184
179
|
| **Packed-package smoke** | Packed-package and host-agent smokes exercise the release tarball path, surfaced plan questions, selected optional capability sensors, rejected design confirmation handling, and exact contract-rule evidence for shared product expectations. |
|
|
185
180
|
|
|
186
181
|
### Supporting Proof
|
|
@@ -232,7 +227,7 @@ The benchmark suite is intentionally reported with boundaries:
|
|
|
232
227
|
| **React Native** | ✅ Full | `tsc`, `npm lint`, SDK import smoke |
|
|
233
228
|
| **Flutter / Dart** | ✅ Full | `flutter analyze`, `flutter test` |
|
|
234
229
|
| **Android (Kotlin)** | ✅ Full | Gradle assemble, unit tests |
|
|
235
|
-
| **iOS (Swift)** | ✅ Full | Static rule checks fully operational. Build sensor
|
|
230
|
+
| **iOS (Swift)** | ✅ Full | Static rule checks fully operational (highest-risk rules use the Swift tree-sitter AST). Build sensor is **guarded best-effort**: an `.xcodeproj`/`.xcworkspace` enables an `xcodebuild -list` integrity probe plus a signing-disabled build — only when `xcodebuild` is on PATH (absent → skipped with the visible precondition). Environment-caused failures (no simulator runtime, Command-Line-Tools-only `xcode-select`, signing demands, unaccepted license) report **skipped-with-reason**, never project failure; a real build failure still exits non-zero. |
|
|
236
231
|
|
|
237
232
|
Each platform has dozens of rules across 10 compliance domains (feed, comments, moderation, chat, secrets, session & auth, notifications, live objects, logging hygiene, design tokens).
|
|
238
233
|
|
|
@@ -420,9 +415,9 @@ MCP-capable hosts can call Vise as structured tool calls instead of shell comman
|
|
|
420
415
|
|
|
421
416
|
### Tool names (snake_case per MCP convention)
|
|
422
417
|
|
|
423
|
-
`inspect_project`, `creative_brief`, `creative_accept`, `ux_harness`, `compile_experience`, `experience_sensors`, `plan_harness`, `plan_integration`, `init_compliance`, `check_compliance`, `experience_report`, `record_learning`, `show_learning`, `sync_compliance`, `attest_rule`, `explain_rule`, `init_engagement`, `show_engagement`, `
|
|
418
|
+
`inspect_project`, `creative_brief`, `creative_accept`, `ux_harness`, `compile_experience`, `experience_sensors`, `plan_harness`, `plan_integration`, `init_compliance`, `check_compliance`, `experience_report`, `record_learning`, `show_learning`, `sync_compliance`, `attest_rule`, `explain_rule`, `init_engagement`, `show_engagement`, `search_docs`, `get_doc_page`, `debug_issue`, `validate_setup`, `run_sensors`, `design_extract`, `design_check`, `design_preview`, `design_reference`, `design_init_tokens`.
|
|
424
419
|
|
|
425
|
-
These are the same operations as the CLI commands above, exposed as MCP tools.
|
|
420
|
+
These are the same operations as the CLI commands above, exposed as MCP tools. `get_sdk_facts` is also registered as the internal, read-only Block Factory SDK-facts provider tool (it inspects no customer project — see [docs/SDK_FACTS_FOR_BLOCK_FACTORY.md](docs/SDK_FACTS_FOR_BLOCK_FACTORY.md)). The adapter still answers the legacy `resolve_request` and `suggest_patch` names for backward compatibility, but they are deprecated in favour of `plan_integration` plus host-tool edits.
|
|
426
421
|
|
|
427
422
|
---
|
|
428
423
|
|
package/dist/capabilities.js
CHANGED
|
@@ -1187,6 +1187,50 @@ function baselineCapabilities(outcome) {
|
|
|
1187
1187
|
export function capabilityChecklist(outcome) {
|
|
1188
1188
|
return baselineCapabilities(outcome).map((c) => ({ id: c.id, label: c.label, hint: c.hint }));
|
|
1189
1189
|
}
|
|
1190
|
+
/**
|
|
1191
|
+
* The Vise-owned completeness id vocabulary — every id a Block Factory contract
|
|
1192
|
+
* may reference in `providesCapabilities`. Vise owns this id space; the factory
|
|
1193
|
+
* owns the per-block declaration (see block-factory/docs/vise-boundary.md).
|
|
1194
|
+
*/
|
|
1195
|
+
export function completenessCapabilityIds() {
|
|
1196
|
+
return new Set(CAPABILITIES.map((capability) => capability.id));
|
|
1197
|
+
}
|
|
1198
|
+
/**
|
|
1199
|
+
* Overlay installed-block evidence onto a source-scan completeness assessment.
|
|
1200
|
+
* A still-missing checklist capability becomes present with evidence
|
|
1201
|
+
* `source: "block:<blockId>"` when a locally validated installed block declares
|
|
1202
|
+
* it in `providesCapabilities`. Callers are responsible for the local validation
|
|
1203
|
+
* (package declared + filesTouched intact); on drift they must simply not pass
|
|
1204
|
+
* the capability here, so the normal gap returns.
|
|
1205
|
+
*/
|
|
1206
|
+
export function applyBlockProvidedCompleteness(assessment, provided) {
|
|
1207
|
+
if (provided.length === 0 || assessment.missing.length === 0) {
|
|
1208
|
+
return assessment;
|
|
1209
|
+
}
|
|
1210
|
+
const blockByCapability = new Map();
|
|
1211
|
+
for (const item of provided) {
|
|
1212
|
+
if (!blockByCapability.has(item.capabilityId)) {
|
|
1213
|
+
blockByCapability.set(item.capabilityId, item.blockId);
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
const present = [...assessment.present];
|
|
1217
|
+
const missing = [];
|
|
1218
|
+
for (const item of assessment.missing) {
|
|
1219
|
+
const blockId = blockByCapability.get(item.id);
|
|
1220
|
+
if (blockId) {
|
|
1221
|
+
present.push({
|
|
1222
|
+
id: item.id,
|
|
1223
|
+
label: item.label,
|
|
1224
|
+
source: `block:${blockId}`,
|
|
1225
|
+
note: `Satisfied by installed block "${blockId}" (sp-vise/blocks.json): the block package delivers this capability and its local install validation passed.`,
|
|
1226
|
+
});
|
|
1227
|
+
}
|
|
1228
|
+
else {
|
|
1229
|
+
missing.push(item);
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
return { ...assessment, present, missing };
|
|
1233
|
+
}
|
|
1190
1234
|
/** Optional feed-forward choices. These are not baseline completeness requirements. */
|
|
1191
1235
|
export function optionalCapabilityChecklist(outcome, availableIds) {
|
|
1192
1236
|
const available = availableIds ? new Set(availableIds) : undefined;
|
package/dist/server.js
CHANGED
|
@@ -342,7 +342,7 @@ async function handleCli(args) {
|
|
|
342
342
|
return "exit";
|
|
343
343
|
}
|
|
344
344
|
if (command === "sdk-facts" || command === "sdk_facts") {
|
|
345
|
-
assertOnlyKnownFlags(args, ["platform", "capability", "surface-dir", "format", "include-symbols"], "sdk-facts");
|
|
345
|
+
assertOnlyKnownFlags(args, ["platform", "capability", "surface-dir", "format", "include-symbols", "include-models"], "sdk-facts");
|
|
346
346
|
const format = flagValue(args, "format") ?? "json";
|
|
347
347
|
if (format !== "json") {
|
|
348
348
|
throw new Error("sdk-facts currently supports --format json only.");
|
|
@@ -352,6 +352,7 @@ async function handleCli(args) {
|
|
|
352
352
|
capability: flagValue(args, "capability"),
|
|
353
353
|
surfaceDir: flagValue(args, "surface-dir"),
|
|
354
354
|
includeSymbols: hasFlag(args, "include-symbols"),
|
|
355
|
+
includeModels: hasFlag(args, "include-models"),
|
|
355
356
|
});
|
|
356
357
|
return "exit";
|
|
357
358
|
}
|
|
@@ -776,10 +777,15 @@ Usage:
|
|
|
776
777
|
return `${packageName} sdk-facts
|
|
777
778
|
|
|
778
779
|
Read bundled SDK surface facts for social.plus Block Factory planning. Internal, projectless, and read-only.
|
|
780
|
+
Symbol facts prove existence; --include-models adds extraction-grounded field-level model schemas
|
|
781
|
+
(modelSchemas, plus capability model entries gain a schema). Platforms without grounded field data
|
|
782
|
+
report modelFacts.status=absent instead of fabricated fields.
|
|
779
783
|
|
|
780
784
|
Usage:
|
|
781
785
|
vise sdk-facts --platform typescript --capability comments --format json
|
|
786
|
+
vise sdk-facts --platform typescript --capability comments --include-models
|
|
782
787
|
vise sdk-facts --platform react-native --capability reactions --include-symbols
|
|
788
|
+
vise sdk-facts --platform android --include-models --format json
|
|
783
789
|
vise sdk-facts --platform android --surface-dir ./sdk-surface --format json`;
|
|
784
790
|
}
|
|
785
791
|
if (command === "blocks") {
|