@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 +23 -2
- package/docs/PUBLIC-BETA-READINESS.md +25 -8
- package/docs/WINDOWS-BETA-ACCEPTANCE.md +10 -2
- package/experience/linux/prepare.sh +1 -1
- package/package.json +1 -1
- package/skills/foggy-deepseek-onboarding/SKILL.md +10 -0
- package/skills/foggy-deepseek-onboarding/assets/versions.json +1 -1
- package/skills/foggy-deepseek-onboarding/references/onboarding-workflow.md +12 -1
- package/skills/foggy-deepseek-onboarding/scripts/invoke-onboarding.ps1 +2 -0
- package/skills/foggy-deepseek-onboarding/scripts/onboarding.py +99 -10
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.
|
|
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.
|
|
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.
|
|
1
|
+
# Public beta readiness: 0.4.0-beta.17
|
|
2
2
|
|
|
3
|
-
Assessment date: 2026-09-
|
|
3
|
+
Assessment date: 2026-09-05
|
|
4
4
|
|
|
5
5
|
## Verdict
|
|
6
6
|
|
|
7
|
-
`0.4.0-beta.
|
|
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
|
|
44
|
-
0.1.18, analysis Skill 0.1.17, and onboarding Skill
|
|
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
|
|
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,
|
|
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.
|
|
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.
|
|
65
|
+
- onboarding Skill 0.4.0-beta.17;
|
|
58
66
|
- Java 17+ available;
|
|
59
67
|
- native DSH Skill registration available.
|
|
60
68
|
|
package/package.json
CHANGED
|
@@ -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
|
|
|
@@ -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.
|
|
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
|
|
@@ -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
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
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(
|
|
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,
|
|
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)
|