@foggy-projects/deepseek-harness-plugin 0.4.0-beta.15 → 0.4.0-beta.17

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
@@ -14,7 +14,7 @@ modify `PATH`, or register Python globally. Advanced users may explicitly set
14
14
  ## Local beta installation
15
15
 
16
16
  ```powershell
17
- dsh plugin --profile web add --workspace-root ./foggy-projects-deepseek-harness-plugin-0.4.0-beta.15.tgz
17
+ dsh plugin --profile web add --workspace-root ./foggy-projects-deepseek-harness-plugin-0.4.0-beta.17.tgz
18
18
  ```
19
19
 
20
20
  Restart `dsh web`, use the browser it opens (or the complete printed URL,
@@ -27,6 +27,24 @@ After npm beta publication, the corresponding one-line install is:
27
27
  dsh plugin --profile web add --workspace-root @foggy-projects/deepseek-harness-plugin@beta
28
28
  ```
29
29
 
30
+ DeepSeek Harness 0.1.2-rc.1 applies pnpm's minimum-release-age policy to its
31
+ profile lockfile. An upgrade performed shortly after publication can therefore
32
+ fail while naming either the new plugin or the previously installed Beta. This
33
+ is a DSH profile-policy failure, not a damaged Foggy package. Use the exact
34
+ profile directory printed in the error and rebuild its lockfile, then rerun the
35
+ same `dsh plugin add` command:
36
+
37
+ ```powershell
38
+ Set-Location "<the DSH profile directory printed in the error>"
39
+ npx --yes pnpm@11.7.0 clean --lockfile
40
+ ```
41
+
42
+ The failed add normally records the requested exact version under
43
+ `minimumReleaseAgeExclude` before returning. If the error repeats, confirm that
44
+ both the installed and requested exact Foggy versions named by the error appear
45
+ under that key in the profile's `pnpm-workspace.yaml`; do not disable the policy
46
+ globally.
47
+
30
48
  For development, `FOGGY_ASSET_CACHE_DIRS` can contain platform-delimited verified
31
49
  asset-cache directories. It is not required for a normal install.
32
50
 
@@ -50,7 +68,10 @@ Opaque CLI profiles remain available for users who prefer them and default to
50
68
  the private persistent `<dataRoot>/cli-profiles` directory, but they are not a
51
69
  prerequisite for ordinary development. Composite onboarding commands are
52
70
  idempotent: unchanged completed phases are resumed rather than re-adding a
53
- datasource or re-registering a local Bundle. Settings detects legacy temporary
71
+ datasource or re-registering a local Bundle. A resumed datasource checkpoint is
72
+ also reconciled against the live Runtime; if the datasource was removed outside
73
+ the wrapper, only datasource configuration, verification, and schema discovery
74
+ are resumed. Settings detects legacy temporary
54
75
  profiles and offers an explicit, validated migration into the persistent store.
55
76
 
56
77
  Private Python, CLI, Launcher, the analysis Skill, install state, and Runtime
@@ -1,10 +1,10 @@
1
- # Public beta readiness: 0.4.0-beta.15
1
+ # Public beta readiness: 0.4.0-beta.17
2
2
 
3
- Assessment date: 2026-09-04
3
+ Assessment date: 2026-09-05
4
4
 
5
5
  ## Verdict
6
6
 
7
- `0.4.0-beta.15` is suitable for a scoped public beta on Windows 10/11 x64 and
7
+ `0.4.0-beta.17` is suitable for a scoped public beta on Windows 10/11 x64 and
8
8
  Linux/WSL2 x64. It is not a general-availability release.
9
9
 
10
10
  The plugin package stays small and downloads large components only during
@@ -40,8 +40,10 @@ system PATH, registry, or a user's existing Python installation.
40
40
  inspected a SQLite datasource containing one table. Runtime retained the same
41
41
  PID, while the persisted onboarding state and command evidence contained no
42
42
  copy of the synthetic password.
43
- - The UI reported Python 3.12.13 as `Foggy private`, and CLI 0.1.23, Launcher
44
- 0.1.18, analysis Skill 0.1.17, and onboarding Skill 0.4.0-beta.15 as installed.
43
+ - The package and settings contract report Python 3.12.13 as `Foggy private`,
44
+ CLI 0.1.23, Launcher 0.1.18, analysis Skill 0.1.17, and onboarding Skill
45
+ 0.4.0-beta.17; the same component display was accepted in the preceding
46
+ native Windows beta run.
45
47
  - Runtime startup now reports the current phase, elapsed/timeout seconds, and a
46
48
  bounded progress value. A real Windows launch with Temurin 17 reached readiness
47
49
  and passed capabilities in 18.9 seconds. A controlled post-launch Java exit was
@@ -61,10 +63,25 @@ system PATH, registry, or a user's existing Python installation.
61
63
  downloaded artifacts are not trusted until the complete SHA256 matches.
62
64
  - Windows progress writes tolerate transient sharing violations without losing
63
65
  the previous valid progress document or leaving temporary files behind.
64
- - Current automated regression passes 20 Node tests and 20 Python tests. The
66
+ - Current automated regression passes 20 Node tests and 25 Python tests. The
65
67
  new datasource tests cover secret-free persisted state, direct Runtime API
66
- submission, CLI bypass for inline development credentials, and output
67
- redaction.
68
+ submission, CLI bypass for inline development credentials, stable inline
69
+ credential resumption, bounded transient connection retry, and output redaction.
70
+ - A real Java 17 / Launcher 0.1.18 regression resumed the same completed inline
71
+ datasource composite twice, retained the Runtime PID, and emitted a complete
72
+ `01` through `06` workspace evidence sequence without falling back to granular
73
+ commands.
74
+ - A separate recovery regression completed a SQLite onboarding composite,
75
+ removed the managed datasource outside the wrapper, and reran the same
76
+ composite. The wrapper detected the missing live datasource, reset only the
77
+ three dependent checkpoints, recreated and tested the datasource, rebound the
78
+ namespace, and rediscovered the selected table successfully.
79
+ - The full release rehearsal converted an inspected 126-column TMS order table
80
+ into versioned TM/QM source, passed eight development question-bank cases,
81
+ deployed the exact Git-tagged source to a separate Ubuntu host, published the
82
+ bundle, and passed the same question bank before and after a Runtime restart.
83
+ The remote Runtime retained its datasource binding, active bundle, query
84
+ model, and 11-tool MCP surface after restart.
68
85
 
69
86
  ## Beta boundaries
70
87
 
@@ -1,7 +1,7 @@
1
1
  # Native Windows Beta acceptance
2
2
 
3
3
  This runbook validates DeepSeek Harness `0.1.2-rc.1` with Foggy plugin
4
- `0.4.0-beta.15` on a clean 64-bit Windows 10 or Windows 11 machine. Use a local
4
+ `0.4.0-beta.17` on a clean 64-bit Windows 10 or Windows 11 machine. Use a local
5
5
  directory that is not synchronized by OneDrive.
6
6
 
7
7
  ## Prerequisites
@@ -34,6 +34,14 @@ npx --yes --package=@deepseek-ai/dsh@0.1.2-rc.1 --package=pnpm@11.7.0 `
34
34
  npx --yes --package=@deepseek-ai/dsh@0.1.2-rc.1 --package=pnpm@11.7.0 dsh web
35
35
  ```
36
36
 
37
+ If an immediate upgrade reports
38
+ `ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION`, use the exact DSH profile directory
39
+ printed by the error, run `npx --yes pnpm@11.7.0 clean --lockfile` there, and
40
+ repeat the same plugin-add command. The failed add normally records the new
41
+ exact package version in that profile's `minimumReleaseAgeExclude`; if the
42
+ error names an older installed Beta, confirm that exact version is listed too.
43
+ Do not disable the policy globally.
44
+
37
45
  Let DSH open the browser automatically. If it does not, copy the complete URL
38
46
  printed by `dsh web`, including its `?token=...` query, into the browser. A new
39
47
  browser session cannot use the bare `http://127.0.0.1:3080/` URL until that
@@ -54,7 +62,7 @@ Expected component state:
54
62
  - CLI 0.1.23;
55
63
  - Launcher 0.1.18;
56
64
  - analysis Skill 0.1.17;
57
- - onboarding Skill 0.4.0-beta.15;
65
+ - onboarding Skill 0.4.0-beta.17;
58
66
  - Java 17+ available;
59
67
  - native DSH Skill registration available.
60
68
 
@@ -3,7 +3,7 @@ set -euo pipefail
3
3
 
4
4
  DSH_VERSION="0.1.2-rc.1"
5
5
  PNPM_VERSION="11.7.0"
6
- PLUGIN_VERSION="0.4.0-beta.15"
6
+ PLUGIN_VERSION="0.4.0-beta.17"
7
7
  PLUGIN_REF="v${PLUGIN_VERSION}"
8
8
  PLUGIN_REPOSITORY="https://github.com/foggy-projects/foggy-deepseek-harness-plugin.git"
9
9
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@foggy-projects/deepseek-harness-plugin",
3
- "version": "0.4.0-beta.15",
3
+ "version": "0.4.0-beta.17",
4
4
  "description": "Foggy Java data analysis engine integration for DeepSeek Harness",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -62,6 +62,16 @@ are authoritative; do not copy the Skill into the current workspace.
62
62
  7. When the model works, recommend committing the model directory to the user's own Git repository.
63
63
  Do not initialize a repository, commit, push, or create a remote unless the user requests it.
64
64
 
65
+ For a normal end-to-end request, take the documented composite-command path first. Do not inspect
66
+ `onboarding.py`, enumerate CLI help, search installation directories, load the sales-drop example, or
67
+ fetch online syntax documentation before trying that path. Use those troubleshooting or reference
68
+ sources only when a concrete error or unsupported modeling requirement makes them relevant.
69
+
70
+ Use the user's business terms to narrow schema discovery with `--pattern` or repeated `--table` when
71
+ there are clear candidates. Otherwise keep the bounded default, then inspect only the few tables and
72
+ columns needed for the requested model. Full results belong in the evidence files; retain concise
73
+ summaries and paths in the conversation instead of repeatedly reading complete JSON artifacts.
74
+
65
75
  Read [references/onboarding-workflow.md](references/onboarding-workflow.md) for the wrapper commands and
66
76
  credential shapes. Use `foggy-ai-analysis` references for detailed TM/QM modeling and query tuning.
67
77
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": "foggy-deepseek-onboarding-versions/v1",
3
- "packageVersion": "0.4.0-beta.15",
3
+ "packageVersion": "0.4.0-beta.17",
4
4
  "validatedAt": "2026-09-04",
5
5
  "components": {
6
6
  "deepseekHarness": {
@@ -72,7 +72,18 @@ tables list -> bounded schema inspection
72
72
  ```
73
73
 
74
74
  It does not stop or restart Runtime. Repeated calls reuse completed checkpoints when the public
75
- connection contract is unchanged. Inline password values are excluded from the comparison.
75
+ connection contract is unchanged. Before reusing a datasource checkpoint, the wrapper verifies that
76
+ the named datasource still exists with the expected public type in the live Runtime. If it was
77
+ removed outside the wrapper, datasource configuration, verification, and schema discovery resume
78
+ automatically from the first affected step. Inline password values are excluded from the comparison.
79
+ Transient connection-pool readiness timeouts are retried a small, bounded number of times; invalid
80
+ credentials, invalid URLs, and other configuration errors fail immediately.
81
+
82
+ When the user's request clearly identifies a business subject or likely tables, add `--pattern` or
83
+ one or more `--table` arguments so discovery remains focused. Do not enumerate CLI help, inspect the
84
+ wrapper source, load unrelated examples, or fetch online documentation on the successful normal path.
85
+ Keep full command payloads in the numbered evidence files and use only their concise result fields in
86
+ the conversation.
76
87
 
77
88
  After discovery, use `foggy-ai-analysis` to create TM/QM drafts from actual tables, columns, keys,
78
89
  small read-only samples when useful, and the user's business questions. Keep the files in the current
@@ -26,5 +26,7 @@ if (-not $pythonCommand -or -not (Test-Path -LiteralPath $pythonCommand)) {
26
26
  exit 1
27
27
  }
28
28
 
29
+ $env:PYTHONUTF8 = '1'
30
+ $env:PYTHONIOENCODING = 'utf-8'
29
31
  & $pythonCommand (Join-Path $PSScriptRoot 'onboarding.py') @OnboardingArgs
30
32
  exit $LASTEXITCODE
@@ -993,12 +993,15 @@ def validate_connection(payload: dict) -> dict:
993
993
  def persisted_connection(connection: dict) -> dict:
994
994
  """Return the resumable connection contract without an inline development password."""
995
995
  persisted = {key: value for key, value in connection.items() if key != "password"}
996
- persisted["credentialMode"] = (
997
- "inline-development" if connection.get("password") is not None
998
- else "agent-environment" if connection.get("passwordEnv")
999
- else "opaque-profile" if connection.get("connectionMode") == "opaque-profile"
1000
- else "none"
1001
- )
996
+ credential_mode = connection.get("credentialMode")
997
+ if credential_mode not in {"inline-development", "agent-environment", "opaque-profile", "none"}:
998
+ credential_mode = (
999
+ "inline-development" if connection.get("password") is not None
1000
+ else "agent-environment" if connection.get("passwordEnv")
1001
+ else "opaque-profile" if connection.get("connectionMode") == "opaque-profile"
1002
+ else "none"
1003
+ )
1004
+ persisted["credentialMode"] = credential_mode
1002
1005
  return persisted
1003
1006
 
1004
1007
 
@@ -1797,6 +1800,50 @@ def cli_json(install_state: dict, runtime_state: dict, namespace: str, command:
1797
1800
  return payload
1798
1801
 
1799
1802
 
1803
+ TRANSIENT_DATASOURCE_TEST_MARKERS = (
1804
+ "connection is not available",
1805
+ "connection pool",
1806
+ "request timed out",
1807
+ "timeout waiting for connection",
1808
+ )
1809
+
1810
+
1811
+ def datasource_test_with_retry(
1812
+ install_state: dict,
1813
+ runtime_state: dict,
1814
+ namespace: str,
1815
+ datasource_name: str,
1816
+ *,
1817
+ attempts: int = 3,
1818
+ initial_delay_seconds: float = 1.0,
1819
+ ) -> dict:
1820
+ """Retry only transient pool/readiness failures; authentication and configuration failures fail fast."""
1821
+ for attempt in range(1, attempts + 1):
1822
+ try:
1823
+ result = cli_json(
1824
+ install_state,
1825
+ runtime_state,
1826
+ namespace,
1827
+ ["datasources", "test", datasource_name],
1828
+ "datasources test",
1829
+ )
1830
+ if attempt > 1:
1831
+ result = {
1832
+ **result,
1833
+ "onboardingRetry": {
1834
+ "attempts": attempt,
1835
+ "reason": "transient-datasource-readiness",
1836
+ },
1837
+ }
1838
+ return result
1839
+ except OnboardingError as exc:
1840
+ transient = any(marker in str(exc).lower() for marker in TRANSIENT_DATASOURCE_TEST_MARKERS)
1841
+ if not transient or attempt == attempts:
1842
+ raise
1843
+ time.sleep(initial_delay_seconds * attempt)
1844
+ raise AssertionError("unreachable")
1845
+
1846
+
1800
1847
  def runtime_api_json(
1801
1848
  runtime_state: dict,
1802
1849
  namespace: str,
@@ -2092,9 +2139,8 @@ def datasource_verify_command(args: argparse.Namespace) -> dict:
2092
2139
  raise OnboardingError("Datasource is not configured; run datasource-configure --apply first")
2093
2140
  connection = state["connection"]
2094
2141
  namespace = connection["namespace"]
2095
- tested = redact_connection_material(cli_json(
2096
- install_state, runtime_state, namespace,
2097
- ["datasources", "test", connection["name"]], "datasources test",
2142
+ tested = redact_connection_material(datasource_test_with_retry(
2143
+ install_state, runtime_state, namespace, connection["name"],
2098
2144
  ))
2099
2145
  if not args.bind:
2100
2146
  mark_step(state, "datasourceVerified", "waiting-for-binding", connectionTested=True)
@@ -2714,6 +2760,38 @@ def step_completed(state: dict, name: str) -> bool:
2714
2760
  return state.get("steps", {}).get(name, {}).get("status") == "completed"
2715
2761
 
2716
2762
 
2763
+ def reconcile_datasource_checkpoint(
2764
+ state: dict,
2765
+ install_state: dict,
2766
+ data_root: Path,
2767
+ runtime_state: dict,
2768
+ ) -> dict | None:
2769
+ """Reset dependent checkpoints when the live Runtime lost the datasource."""
2770
+ if not step_completed(state, "datasourceConfigured"):
2771
+ return None
2772
+ connection = state["connection"]
2773
+ listed = cli_json(
2774
+ install_state,
2775
+ runtime_state,
2776
+ connection["namespace"],
2777
+ ["datasources", "list"],
2778
+ "datasources list for checkpoint reconciliation",
2779
+ )
2780
+ if matching_datasource(listed, connection) is not None:
2781
+ return None
2782
+ reset_steps = ("datasourceConfigured", "datasourceVerified", "schemaDiscovered")
2783
+ for name in reset_steps:
2784
+ mark_step(state, name, "pending", reason="runtime-datasource-missing")
2785
+ state.get("artifacts", {}).pop("schemaDiscovery", None)
2786
+ write_onboarding_state(data_root, state)
2787
+ return {
2788
+ "recovered": True,
2789
+ "reason": "runtime-datasource-missing",
2790
+ "resetSteps": list(reset_steps),
2791
+ "dataSource": connection["name"],
2792
+ }
2793
+
2794
+
2717
2795
  def bound_project_roots(state: dict) -> list[Path]:
2718
2796
  values = [state.get("projectRoot"), *state.get("workspaceBindings", [])]
2719
2797
  result: list[Path] = []
@@ -2746,7 +2824,7 @@ def bind_completed_workspace(state: dict, data_root: Path, project_root: Path) -
2746
2824
 
2747
2825
 
2748
2826
  def datasource_run_command(args: argparse.Namespace) -> dict:
2749
- _install_root, install_state, data_root, _runtime_state = onboarding_context(args, require_runtime=True)
2827
+ _install_root, install_state, data_root, runtime_state = onboarding_context(args, require_runtime=True)
2750
2828
  project_root = normalized(args.project_root or Path.cwd())
2751
2829
  requested_connection = validate_connection(read_json_object(normalized(args.connection_file), "Connection plan"))
2752
2830
  resumable_connection = persisted_connection(requested_connection)
@@ -2788,6 +2866,9 @@ def datasource_run_command(args: argparse.Namespace) -> dict:
2788
2866
  ))
2789
2867
  save_composite_result(evidence_dir, "01-plan.json", plan_result, files)
2790
2868
  state = read_onboarding_state(data_root, profile)
2869
+ checkpoint_recovery = reconcile_datasource_checkpoint(
2870
+ state, install_state, data_root, runtime_state,
2871
+ )
2791
2872
 
2792
2873
  if step_completed(state, "datasourceConfigured"):
2793
2874
  configured = resumed_phase(profile, "datasourceConfigured")
@@ -2798,6 +2879,8 @@ def datasource_run_command(args: argparse.Namespace) -> dict:
2798
2879
  install_root=args.install_root, data_root=args.data_root, profile=profile, apply=False, replace=False,
2799
2880
  runtime_password=requested_connection.get("password"),
2800
2881
  ))
2882
+ if checkpoint_recovery:
2883
+ configure_dry["checkpointRecovery"] = checkpoint_recovery
2801
2884
  save_composite_result(evidence_dir, "02-datasource-dry.json", configure_dry, files)
2802
2885
  if not args.approve_configure:
2803
2886
  return {
@@ -2814,6 +2897,8 @@ def datasource_run_command(args: argparse.Namespace) -> dict:
2814
2897
  install_root=args.install_root, data_root=args.data_root, profile=profile, apply=True, replace=False,
2815
2898
  runtime_password=requested_connection.get("password"),
2816
2899
  ))
2900
+ if checkpoint_recovery:
2901
+ configured["checkpointRecovery"] = checkpoint_recovery
2817
2902
  save_composite_result(evidence_dir, "03-datasource-apply.json", configured, files)
2818
2903
  state = read_onboarding_state(data_root, profile)
2819
2904
 
@@ -3425,6 +3510,10 @@ def build_parser() -> argparse.ArgumentParser:
3425
3510
 
3426
3511
 
3427
3512
  def main() -> None:
3513
+ for stream in (sys.stdout, sys.stderr):
3514
+ reconfigure = getattr(stream, "reconfigure", None)
3515
+ if callable(reconfigure):
3516
+ reconfigure(encoding="utf-8", errors="replace")
3428
3517
  args = build_parser().parse_args()
3429
3518
  try:
3430
3519
  result = args.handler(args)