diff --git a/builtin/runtime/lsp.lua b/builtin/runtime/lsp.lua index a8bca7c..e924a3a 100644 --- a/builtin/runtime/lsp.lua +++ b/builtin/runtime/lsp.lua @@ -240,8 +240,10 @@ pmacs.lsp.config.json = pmacs.lsp.config.json or { -- live-observed with Red Hat `yaml-language-server@1.24.0`: its initial -- pull requests exactly those five sections, and opening a YAML document -- requests a second scoped `[yaml]` section. The standalone smoke reached --- a real syntax diagnostic and clean shutdown; the PATH-gated --- pmacs-through-server acceptance remains a transfer task. +-- a real syntax diagnostic and clean shutdown. The PATH-gated pmacs +-- acceptance also proves auto-attach, initialization, config pulls, a +-- syntax diagnostic, and continued server liveness with both catalogs +-- disabled for network-free determinism. pmacs.lsp.config.yaml = pmacs.lsp.config.yaml or { command = "yaml-language-server", args = { "--stdio" }, diff --git a/docs/json-yaml-framing.md b/docs/json-yaml-framing.md index bb3e4b6..4c52e58 100644 --- a/docs/json-yaml-framing.md +++ b/docs/json-yaml-framing.md @@ -1,12 +1,12 @@ # JSON + YAML grammars — framing (side quest, highlight family) -**Revision 2 — 2026-07-20. Status: PR #123 open; review-fix +**Revision 3 — 2026-07-20. Status: PR #123 open; review-fix checkpoint preserved on branch `json-yaml-handoff-2026-07-20`.** The public PR branch still pointed to the original implementation `4be2a65` when this checkpoint was created. JSON provider resolution and its real pmacs smoke are complete; the YAML 1.24.0 standalone -protocol smoke is complete; the real YAML-through-pmacs acceptance, -rebase onto current main, and full gates remain. +protocol smoke and real YAML-through-pmacs acceptance are complete; +rebase onto current main and full gates remain. **Intent.** Add `tree-sitter-json` and `tree-sitter-yaml` grammars (plus their language servers) to the bundle. Two config formats that pmacs @@ -157,8 +157,8 @@ fences resolve through the #122 engine. Acceptance proves both end to end 3. The two configuration models are now observed: JSON consumes the pushed full settings object; YAML 1.24.0 pulls the five documented sections plus a document-scoped `[yaml]` request. The remaining bet - is that pmacs answers the real YAML server correctly end to end, - which the pending PATH-gated acceptance must prove. + was that pmacs answers the real YAML server correctly end to end; + the PATH-gated acceptance now proves that against version 1.24.0. ## Deferred (named) @@ -203,18 +203,17 @@ fences resolve through the #122 engine. Acceptance proves both end to end pmacs, receive the pushed default config, open invalid JSON, and publish a syntax diagnostic. Skips when the binary is absent. 12. `m4_real_yaml_provider_pulls_config_and_reports_diagnostics` — - **pending on the destination machine**. PATH-gated live smoke for - Red Hat `yaml-language-server@1.24.0`: auto-attach through pmacs, - disable SchemaStore and Kubernetes CRD catalog network access for - determinism, reach initialized, open invalid YAML, publish a - diagnostic, and remain alive. + PATH-gated live smoke for Red Hat `yaml-language-server@1.24.0`: + auto-attach through pmacs, disable SchemaStore and Kubernetes CRD + catalog network access for determinism, reach initialized, open + invalid YAML, publish a diagnostic, and remain alive. ## Risks / interactions -- **LSP configuration** (Q#JY2) — JSON push and YAML standalone pulls - are observed. The real YAML-through-pmacs path is still pending and - is an explicit transfer blocker, not implied complete by source - inspection. +- **LSP configuration** (Q#JY2) — JSON push, YAML standalone pulls, and + the real YAML-through-pmacs path are observed. Both live provider + tests remain PATH-gated, so release verification must put the pinned + binaries on PATH rather than accepting their skip paths. - **Themes / injections** — untouched. This is pure grammar+detection addition; it consumes the #122 engine, doesn't change it. No protocol bump. diff --git a/tests/m4_acceptance.rs b/tests/m4_acceptance.rs index f417f16..8d462e3 100644 --- a/tests/m4_acceptance.rs +++ b/tests/m4_acceptance.rs @@ -6496,6 +6496,94 @@ fn m4_real_json_provider_receives_config_and_reports_diagnostics() { assert_no_lsp_crash(&mut state, "real JSON server"); } +/// PATH-gated provider smoke: drive Red Hat +/// `yaml-language-server@1.24.0` through pmacs's default YAML config and +/// require a syntax diagnostic for an invalid document. `SchemaStore` and +/// the Kubernetes CRD catalog are disabled in this test so the result is +/// deterministic and does not depend on network access. CI skips cleanly +/// when no compatible binary is installed. +#[test] +fn m4_real_yaml_provider_pulls_config_and_reports_diagnostics() { + use pmacs::editor::EditorState; + + let Ok(command) = which_binary("yaml-language-server") else { + eprintln!("yaml-language-server not on PATH; skipping"); + return; + }; + let command = command.display().to_string(); + let dir = tempfile::tempdir().expect("tempdir"); + let file = std::fs::canonicalize(dir.path()) + .expect("canonicalize") + .join("invalid.yaml"); + std::fs::write(&file, b"root:\n broken: [one,\n").expect("write invalid yaml"); + let file_disp = file.display().to_string(); + let uri = format!("file://{file_disp}"); + + let mut state = EditorState::new(); + state + .lua_host + .lua() + .load(format!( + "local c = pmacs.lsp.config.yaml + c.command = '{command}' + c.settings.yaml.schemaStore = {{ enable = false }} + c.settings.yaml.kubernetesCRDStore = {{ enable = false }} + pmacs.buffer.find_or_open('{file_disp}')" + )) + .exec() + .expect("configure real YAML server + open file"); + + assert!( + pump_lua_flag( + &mut state, + "(function() for _,r in ipairs(pmacs.lsp.list()) do \ + if r.language_id=='yaml' and r.state \ + and r.state.kind=='initialized' then return true end \ + end return false end)()", + 30, + ), + "auto-attached real YAML server never reached initialized" + ); + + let deadline = Instant::now() + Duration::from_secs(10); + let mut got_diagnostic = false; + while Instant::now() < deadline { + state.tick_processes(); + state.tick_lsp(); + state.tick_async(); + got_diagnostic = state + .lua_host + .lua() + .load(format!("return pmacs.diag.count('{uri}') > 0")) + .eval() + .unwrap_or(false); + if got_diagnostic { + break; + } + std::thread::sleep(Duration::from_millis(10)); + } + assert!( + got_diagnostic, + "real YAML server produced no diagnostic; config pulls or validation are broken" + ); + assert_no_lsp_crash(&mut state, "real YAML server"); + let still_initialized: bool = state + .lua_host + .lua() + .load( + "for _,r in ipairs(pmacs.lsp.list()) do \ + if r.language_id=='yaml' and r.state \ + and r.state.kind=='initialized' then return true end \ + end return false", + ) + .eval() + .expect("inspect YAML server state"); + assert!( + still_initialized, + "real YAML server did not remain alive after publishing diagnostics" + ); +} + /// Typing-perf: the default bundle coalesces full-document /// `didChange` notifications instead of sending one per keystroke /// (each send copies the whole buffer several times and writes