@wenathlan/saddle 1.8.10 → 1.8.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -203,7 +203,7 @@ Earlier README snapshots remain in `docs/plans/README.md`, `docs/talks9/README.m
203
203
 
204
204
  ## Current scope
205
205
 
206
- Version 1.8.10 extends the TypeScript-first engine with explicit Android, iOS and browser surface boundaries, optimized Android release configuration, dotted release asset naming and helper-binary rejection. Browser binaries, provider credentials, n8n host registration, persistent databases, captcha solvers and production deployment remain caller-selected adapters. Future work should extend contracts without coupling the core to one forge, registry, browser or storage vendor.
206
+ Version 1.8.11 extends the TypeScript-first engine with flat project-owned desktop, Android and iOS build surfaces, explicit Capacitor staging boundaries, dotted release asset naming and helper-binary rejection. Browser binaries, provider credentials, n8n host registration, persistent databases, captcha solvers and production deployment remain caller-selected adapters. Future work should extend contracts without coupling the core to one forge, registry, browser or storage vendor.
207
207
 
208
208
  ## License
209
209
 
@@ -13,10 +13,10 @@ export declare function permissionpolicy(options?: {}): {
13
13
  };
14
14
  /** Requests an optional capability through an injected browser permission function. */
15
15
  export declare function requestpermission(policy: any, permission: any, request: any): Promise<{
16
- code?: undefined;
17
- message?: undefined;
18
16
  permission: string;
19
17
  granted: boolean;
18
+ code?: undefined;
19
+ message?: undefined;
20
20
  } | {
21
21
  permission: string;
22
22
  granted: boolean;
@@ -4,15 +4,14 @@ export declare function mcpserver(options?: {}): {
4
4
  description: string;
5
5
  }[];
6
6
  handle(request: any): Promise<{
7
- error?: undefined;
8
7
  jsonrpc: string;
9
8
  id: any;
10
9
  result: {
11
10
  tools: any;
12
11
  content?: undefined;
13
12
  };
14
- } | {
15
13
  error?: undefined;
14
+ } | {
16
15
  jsonrpc: string;
17
16
  id: any;
18
17
  result: {
@@ -22,6 +21,7 @@ export declare function mcpserver(options?: {}): {
22
21
  text: string;
23
22
  }[];
24
23
  };
24
+ error?: undefined;
25
25
  } | {
26
26
  result?: undefined;
27
27
  jsonrpc: string;
@@ -43,7 +43,7 @@ export function robotsrules(text = "") { const directives = []; const groups = [
43
43
  /** Fetches and caches a site's robots policy without failing the caller's scrape. */
44
44
  export async function fetchRobotsTxt(siteUrl, options = {}) { const base = siteUrl.replace(/\/$/, ""); const robotsUrl = `${base}/robots.txt`; const cached = cache.get(robotsUrl); if (cached && Date.now() - cached.fetchedAt < cachettl)
45
45
  return cached.robots; try {
46
- const response = await fetch(robotsUrl, { headers: { "User-Agent": options.userAgent ?? "Saddle/1.8.10" }, signal: AbortSignal.timeout(options.timeout ?? 5000) });
46
+ const response = await fetch(robotsUrl, { headers: { "User-Agent": options.userAgent ?? "Saddle/1.8.11" }, signal: AbortSignal.timeout(options.timeout ?? 5000) });
47
47
  const robots = response.ok ? robotsrules(await response.text()) : robotsrules();
48
48
  cache.set(robotsUrl, { robots, fetchedAt: Date.now() });
49
49
  return robots;
@@ -11,10 +11,10 @@ export declare function triggermatch(manifest: any, event?: {}): {
11
11
  reason: string;
12
12
  requestid?: undefined;
13
13
  } | {
14
- reason?: undefined;
15
14
  matched: boolean;
16
15
  type: string;
17
16
  requestid: any;
17
+ reason?: undefined;
18
18
  };
19
19
  /** Keeps trigger declarations and produces deterministic matching results. */
20
20
  export declare function triggerregistry(): {
@@ -26,10 +26,10 @@ export declare function triggerregistry(): {
26
26
  reason: string;
27
27
  requestid?: undefined;
28
28
  } | {
29
- reason?: undefined;
30
29
  matched: boolean;
31
30
  type: string;
32
31
  requestid: any;
32
+ reason?: undefined;
33
33
  };
34
34
  list: () => any[];
35
35
  };
@@ -38,3 +38,28 @@ Tauri configuration is resolved from `tauri.conf.json` and can be extended with
38
38
  Version 1.8.10 keeps the Tauri desktop browser and adds explicit Capacitor Android and iOS conversion targets. The shared source is the TypeScript library plus the compiled `web/dist/public` output; the native folders do not fork engine logic. The Android release build enables R8 and resource shrinking, and the workflow creates an ephemeral CI test key when caller production signing secrets are absent.
39
39
 
40
40
  The 1.8.10 workflow names the public outputs `saddle.browser.1.8.10.<format>`, `saddle.apk.1.8.10.apk`, `saddle.aab.1.8.10.aab`, `saddle.ipa.1.8.10.ipa`, `saddle.container.1.8.10.tar.gz` and `saddle.extension.1.8.10.zip`. Surface manifests and checksums use the corresponding `manifest.<surface>.1.8.10.json` and `sha256.<surface>.1.8.10` forms. The release is not considered complete until the live GitHub asset list matches these generated names.
41
+
42
+ ## Verified 1.8.10 primary assets
43
+
44
+ The v1.8.10 release contains the following primary assets. Sizes are bytes and exclude the separate manifest and checksum files.
45
+
46
+ | Surface | Asset | Size |
47
+ | --------------- | ----------------------------------------------------------------------------------------------------------- | ---------: |
48
+ | Desktop browser | [AppImage](https://github.com/wenathlan/saddle/releases/download/v1.8.10/saddle.browser.1.8.10.appimage) | 79,870,456 |
49
+ | Desktop browser | [Debian](https://github.com/wenathlan/saddle/releases/download/v1.8.10/saddle.browser.1.8.10.deb) | 5,294,388 |
50
+ | Desktop browser | [RPM](https://github.com/wenathlan/saddle/releases/download/v1.8.10/saddle.browser.1.8.10.rpm) | 5,297,815 |
51
+ | Desktop browser | [Windows EXE](https://github.com/wenathlan/saddle/releases/download/v1.8.10/saddle.browser.1.8.10.exe) | 4,341,818 |
52
+ | Desktop browser | [Windows MSI](https://github.com/wenathlan/saddle/releases/download/v1.8.10/saddle.browser.1.8.10.msi) | 5,246,976 |
53
+ | Desktop browser | [macOS DMG](https://github.com/wenathlan/saddle/releases/download/v1.8.10/saddle.browser.1.8.10.dmg) | 5,222,365 |
54
+ | Android | [APK](https://github.com/wenathlan/saddle/releases/download/v1.8.10/saddle.apk.1.8.10.apk) | 3,498,594 |
55
+ | Android | [AAB](https://github.com/wenathlan/saddle/releases/download/v1.8.10/saddle.aab.1.8.10.aab) | 3,893,352 |
56
+ | Container | [OCI tarball](https://github.com/wenathlan/saddle/releases/download/v1.8.10/saddle.container.1.8.10.tar.gz) | 81,718,314 |
57
+ | Extension | [ZIP](https://github.com/wenathlan/saddle/releases/download/v1.8.10/saddle.extension.1.8.10.zip) | 10,759 |
58
+
59
+ ## 1.8.11 flat source contract
60
+
61
+ Version 1.8.11 keeps the Tauri browser build flat at `desktop/`, with `Cargo.toml`, `tauri.conf.json`, `build.rs`, `lib.rs` and `main.rs` directly in that surface root. The frontend remains the generated `web/dist/public` output and `dist/` is not committed.
62
+
63
+ The Android project maps Saddle-owned `AndroidManifest.xml`, `main/`, `res/`, `test/` and `androidtest/` directly from the `android/` root through Gradle `sourceSets`. Capacitor staging under `android/app`, `android/assets` and plugin internals is generated during synchronization, removed or ignored before build, and is not project-owned source. The iOS surface keeps its generated Xcode and Swift Package internals because Capacitor owns those paths; Saddle-owned configuration remains at the `ios/` root and no project-owned `ios/src` directory is added.
64
+
65
+ The v1.8.11 workflows derive the version from the release tag, run flat-surface validation, reject helper binaries and attach only outputs matching the dotted lowercase contract. The live release asset list must be verified before this section is changed from a source contract to a generated asset inventory.
@@ -0,0 +1,29 @@
1
+ # Flat native build research for Saddle 1.8.11
2
+
3
+ The 1.8.11 migration follows the repository rule that project-owned code stays at the surface root and that generated `dist/` output is excluded from version control. The migration does not delete toolchain-owned files blindly: it separates Saddle-owned entrypoints from generated platform staging and verifies each build after the path change.
4
+
5
+ ## Tauri desktop
6
+
7
+ The official Tauri project structure normally places the Rust project under `src-tauri/`, and the configuration file acts as a marker for the CLI to locate the Rust project [1]. Tauri also supports configuration extension through `--config`, but that feature merges configuration and does not itself guarantee a different Rust project directory [2]. The 1.8.11 implementation therefore tests the more direct layout: `desktop/tauri.conf.json`, `desktop/Cargo.toml`, `desktop/build.rs`, `desktop/lib.rs` and `desktop/main.rs`. The workflow invokes the CLI from `desktop/` so the configuration and Cargo manifest share one flat surface root.
8
+
9
+ The frontend remains outside the native surface at `web/dist/public`. The path is relative to `desktop/tauri.conf.json`, and the generated `dist/` directory stays ignored. Desktop `target/`, icon outputs and bundle staging also remain generated and are never release inputs unless they match the explicit artifact collector patterns.
10
+
11
+ ## Android Capacitor
12
+
13
+ Android Gradle supports custom source directories through the module-level `sourceSets` block. The official Android guidance allows `java.srcDirs`, `res.srcDirs` and `manifest.srcFile` to point to project-defined paths outside the conventional `src/main` tree [3]. The 1.8.11 layout uses this capability for Saddle-owned files: `android/main/` for the activity host, `android/res/` for resources, `android/AndroidManifest.xml` for the manifest and root-level test directories where practical.
14
+
15
+ Capacitor 8 still generates its web staging, plugin metadata and Cordova bridge under its conventional Android project paths during `cap sync`. Those generated paths are toolchain-owned, ignored by Git and not treated as Saddle source. A validation step rejects tracked `android/app/src` project files while allowing the transient CI staging created by Capacitor. This keeps the repository flat without breaking the generator contract.
16
+
17
+ ## iOS Capacitor
18
+
19
+ Capacitor generates an Xcode project, Swift Package Manager bridge and copied web resources. The generated `CapApp-SPM` package explicitly identifies itself as CLI-managed. The 1.8.11 migration therefore keeps the Xcode project and Capacitor-managed package paths as generated platform internals while ensuring Saddle-owned metadata, workflow configuration and documentation live at the `ios/` root. Flattening the internal Xcode group hierarchy would require abandoning the generated Capacitor project and would reduce reproducibility rather than improve it.
20
+
21
+ ## Decision
22
+
23
+ The flat rule applies strictly to project-owned files. Desktop becomes fully flat at `desktop/`. Android moves the Saddle-owned activity, manifest, resources and tests to root-level paths and maps them through Gradle `sourceSets`; transient Capacitor files remain ignored. iOS keeps generator-owned Xcode internals but exposes a flat root contract and does not add a project-owned `src` directory. All workflows use release-tag version derivation and contain no credentials or fixed infrastructure endpoints.
24
+
25
+ ## References
26
+
27
+ [1]: https://v2.tauri.app/start/project-structure/ "Tauri project structure"
28
+ [2]: https://v2.tauri.app/develop/configuration-files/ "Tauri configuration files"
29
+ [3]: https://developer.android.com/build/gradle-tips "Android Gradle tips and source set configuration"
@@ -1,10 +1,10 @@
1
1
  # Release assets
2
2
 
3
- The Node-only release adapter creates deterministic metadata for caller-selected artifacts. For version `1.8.10`, it writes dotted surface-specific names such as `sha256.desktop.1.8.10`, `manifest.desktop.1.8.10.json`, `sbom.desktop.1.8.10.cdx.json` and `provenance.desktop.1.8.10.intoto.jsonl`. The adapter rejects underscore-based public names and Rust build-helper executables. It never publishes, authenticates or selects a registry.
3
+ The Node-only release adapter creates deterministic metadata for caller-selected artifacts. For version `1.8.11`, it writes dotted surface-specific names such as `sha256.desktop.1.8.11`, `manifest.desktop.1.8.11.json`, `sbom.desktop.1.8.11.cdx.json` and `provenance.desktop.1.8.11.intoto.jsonl`. The adapter rejects underscore-based public names and Rust build-helper executables. It never publishes, authenticates or selects a registry.
4
4
 
5
5
  ```bash
6
6
  npm run release:assets -- \
7
- --version 1.8.10 \
7
+ --version 1.8.11 \
8
8
  --surface desktop \
9
9
  --output build/release \
10
10
  --artifact build/saddle.tgz \
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "Saddle browser bridge",
4
- "version": "1.8.10",
4
+ "version": "1.8.11",
5
5
  "description": "User initiated page snapshots through the Saddle browser contract.",
6
6
  "minimum_chrome_version": "110",
7
7
  "permissions": ["activeTab", "scripting", "storage"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wenathlan/saddle",
3
- "version": "1.8.10",
3
+ "version": "1.8.11",
4
4
  "description": "binary computing engine that turns distributed storage into a publishable working set",
5
5
  "type": "module",
6
6
  "private": false,
@@ -97,7 +97,9 @@
97
97
  "prepublishOnly": "npm run pack:check",
98
98
  "tauri": "npx --yes @tauri-apps/cli@2.11.4",
99
99
  "capacitor:sync:android": "npm run web:build:pages && cap sync android",
100
+ "capacitor:flatten:android": "node tests/scripts/flattenandroid.mjs",
100
101
  "capacitor:sync:ios": "npm run web:build:pages && cap sync ios",
102
+ "native:check:flat": "node tests/scripts/validateflatnative.mjs",
101
103
  "web:dev": "vite --config web/vite.config.ts --host",
102
104
  "web:check": "tsc --project web/tsconfig.json --noEmit",
103
105
  "web:build": "vite build --config web/vite.config.ts",