Skip to content

Releases: fredgis/sql-migration-advisor

v3.14.8 - all three Low clauses

Choose a tag to compare

@fredgis fredgis released this 13 Sep 14:38
1eef61c

The Low line has three clauses, and v3.14.7 wrote the exception against the first one only: a prerequisite path this interview cannot reach is not a decision-driving unknown.

The third clause reads on the same thing. An unsettled path is unverified remediation, so the always-loaded file still mandated low for exactly the case the reference documents had just put at medium, and a model that stops at the first sentence answers low.

Each of the three clauses is now scoped to what the interview handles, and the remediation clause names what it means: work the conversation surfaced and can describe, such as refactoring off a linked server, moving to a supported authentication model, or opening a port. Not the prerequisite plan's.

76 gates, 118 scenarios, 3625 prerequisite checks.

v3.14.7 - a path-level hold on the recommended method

Choose a tag to compare

@fredgis fredgis released this 13 Sep 14:31
3dd0384

§C4 says medium requires the chosen method's gates to be satisfied, and the line below it says a candidate held by a prerequisite path this interview cannot reach does not lower the confidence. Those coexist until the held candidate is the one being recommended, which happens whenever DMS or transactional replication wins: invariant 15 then puts the winner's gate at unknown_requires_assessment, so one line forbids medium and the other permits it for the same fully answered estate.

medium is the answer. The alternative gives low to a user who answered every question, and a scale that always says the same thing says nothing. The medium line admits that case by name, the exception says what happens when it holds the winner, and the card states which path is unread and names the prerequisite plan as the next step.

Writing the scenario for it found the other half: the invariant-15 alignment was promoting such a winner to available, announcing as checked a route whose prerequisite rows nobody had read. Agreement is reached from the candidate's side now, and the gate follows.

76 gates, 118 scenarios, 3625 prerequisite checks.

v3.14.6 - one confidence rule

Choose a tag to compare

@fredgis fredgis released this 13 Sep 14:16
7926319

Invariant 5b split the reasons a candidate is held, and I wrote it in the output contract, where the rule is defined, and not in the decision rules, where the confidence is actually computed. So §C4 still read confidence = low when any candidate is unknown_requires_assessment on a decision-driving dependency, and DMS held by an unreachable P23/P24 is decision-driving by that wording. One document permitted medium, the other mandated low, for the same estate.

§C4 now states the two kinds where the confidence is derived, and the Low line in the always-loaded skill says the same. A gate reads every document that states when confidence drops and fails any that omits the kind that does not drop it, so the two cannot separate again.

76 gates, 117 scenarios, 3625 prerequisite checks.

v3.14.5 - one status, two reasons

Choose a tag to compare

@fredgis fredgis released this 13 Sep 12:11
7082805

A candidate held at unknown_requires_assessment is waiting on one of two things, and the previous release recorded only one of them properly.

It can be waiting on a field the profile does not carry. That is a hard-gate unknown: the interview could have collected it and did not, so it belongs in unknowns and evidenceRequired and it lowers confidence.

Or it can be waiting on a prerequisite path no question in this interview reaches. That is not the same thing, and v3.14.4 put it in evidenceRequired alone without saying why, which created a third category the contract never defined.

Recording it as an unknown was the alternative, and it was measured before choosing: 29 scenarios drop to low, including both evidence-complete scenarios, which state every field their name claims. A profile that answers everything would still read low, so the documented medium ceiling becomes unreachable and the confidence scale stops distinguishing anything.

Invariant 5b names the two reasons instead. The field kind lowers confidence because the interview could have settled it. The path kind does not, because no answer the user could give would change it, and it goes to evidenceRequired and nextActions as work for the prerequisite-plan skill.

Writing that found the hole underneath: several rules hold a candidate and record their reason under the winning method's name, or under none, so a held candidate could carry its reason in its own text and nowhere a reader looks. A gate now reads all 269 held candidates across the scenario set and fails on any whose reason appears in none of the three arrays.

75 gates, 117 scenarios, 3625 prerequisite checks.

v3.14.4 - a refused gate is not an unchecked one

Choose a tag to compare

@fredgis fredgis released this 13 Sep 06:57
cf7cdc5

Four findings, all on the third candidate state introduced one release earlier.

A refused gate and an unchecked one returned the same string. Every caller read both as a refusal, so DMS came back unavailable on a profile where nobody had collected the recovery model. That word asserts the source was examined and failed. It also took the offline P23 variant down with it, which consumes neither online-only fact, and could force a switch to SQL VM. The two are distinguished now, and an unchecked gate leaves both the candidate and the fallback standing.

The unproven-prerequisite check keyed on bridged fields only. A path whose questions are all unbridged had nothing to test, which is how transactional replication was offered as available with none of P13 established. A path the interview cannot reach at all is named as such. It goes to evidenceRequired rather than unknowns, because it is a property of where the two skills divide and not a fact the interview failed to collect.

The evidence line was pushed without the matching unknowns entry, so the always-loaded exemplar failed invariant 5, its own pre-render self-check. Both arrays carry it now, and the two evidence-complete scenarios state the method prerequisites their name claims, so the medium ceiling still has something to prove.

Two schema descriptions still required the selected candidate to be available, while the output contract permits a winner at unknown_requires_assessment with a matching gate, which is what both canonical examples now are.

74 gates, 117 scenarios, 3625 prerequisite checks.

v3.14.3 - four review findings

Choose a tag to compare

@fredgis fredgis released this 12 Sep 17:39
ff04689

Four findings, all founded. The first was a bridge built four hours earlier, in the commit meant to close this exact class.

CHAIN_INTACT cleared eight blockers on one sentence. log_chain_status: CHAIN_INTACT mapped to backup_chain_status: CONFIRMED, and that field feeds eight blocking prerequisites whose evidence columns ask for RESTORE VERIFYONLY, a gap check and a restore rehearsal. The consumer is told never to re-ask an inherited fact, so a user saying the chain was unbroken settled all eight and moved a never-tested restore route off blocked. The mapping is asymmetric now, because the two directions are not equally conclusive: a reported break is proof of a problem and stays MISSING, an intact chain is an input to proof and converts to nothing.

Fabric could not be the more permissive of two surfaces. fabric_sql_db stayed eligible for a profile with linked servers while the same trace refused Azure SQL Database for them, on a reason that argues ranking rather than eligibility. SQL database in Fabric is database-scoped and narrower, so it inherits any verdict SQL Database receives. Ten scenarios moved with it.

The error table licensed working from memory. It said the bundled copy is always in context, which contradicts step 1 and lets a model skip the mandatory reads and rebuild the rules from recall, defeating the stop-on-read-failure rule. The row points back at step 1, and step 1 names all seven files rather than three, including both schemas and advisor-coverage.json, without which the candidate list cannot be built.

A candidate nobody could vouch for was written up as available. The exemplar marked five methods available while its profile stated none of the facts their paths turn on, and readers are explicitly invited to hand any available candidate to the planner. A candidate whose blocking prerequisites are unstated now reads unknown_requires_assessment, derived from the catalog, questions.json and the crosswalk rather than written per method, with the missing fields named in evidenceRequired.

74 gates, 117 scenarios, 3625 prerequisite checks.

v3.14.2 - the duplicated card paragraph

Choose a tag to compare

@fredgis fredgis released this 12 Sep 17:00
dbf75b5

Rewriting the method-candidate template in v3.14.1 left the previous draft in place instead of replacing it, so the always-loaded SKILL.md carried the same two paragraphs twice. The stale copy told the agent to write unverified, which neither the output schema nor the output contract defines.

The duplicate is gone. A gate now reads both status enums out of the schema, refuses any other word in the method rendering block, and refuses a paragraph that appears twice in it. Nothing compared the card's vocabulary to the contract's before, which is why a word invented and abandoned in the same edit could ship.

74 gates, 117 scenarios, 3625 prerequisite checks.

v3.14.1 - the documents the model reads

Choose a tag to compare

@fredgis fredgis released this 12 Sep 16:52
3b76cc1

Five findings from reading the documents a session actually opens, rather than the files a test can run.

The contract said the opposite of the schema. v3.14.0 moved evidence records to evidenceRegister in the schema, the validator and the exemplar plan, and left output-contract.md, which is the one of the four a session opens. Invariant 22 still sent acceptedEvidence ids to sourceRegister, a list of citations that cannot hold an evidence record. A plan following the contract produced output the schema then rejected.

The method list offered two states. Four lines below a gate that argues at length for three, the rendering template gave available and unavailable only, so a method whose prerequisites nobody had confirmed was written up as checked and failed, or as checked and passed. It uses the three the output contract already named.

The gate dimensions were short by two. decision-rules.md listed version, ports, source type and capacity, and not the recovery model or log chain that DMS-MODE refuses on. The rule told a reader to gate the fallback without saying what against, and it now names the case: refusing online DMS on a source in SIMPLE and then offering log shipping, which P03-001 refuses for the same reason.

The crosswalk bridged neither field. recovery_model and log_chain_status have been typed on the advisor side since v3.11.0 and fed P03-001 and P09-001 on the consumer side since the catalog shipped. The table between them named neither, so a handoff dropped both and the consumer asked again for what it had been told.

The validator never read what an answer returned. It checked whether a question fed a row, so UNKNOWN could sit under confirmed. An obligation could also be dismissed as not_applicable with no condition named, and the owed rows could be switched off by carrying the path in selectedMethodPath and omitting the alias the code happened to read. questionsAsked is typed, questions.json supplies the effects per consumer, and six mutations hold it.

73 gates, 117 scenarios, 3625 prerequisite checks.

v3.14.0 — three P1 defects from a behaviour audit

Choose a tag to compare

@fredgis fredgis released this 12 Sep 16:16
0633b83

Three defects found by replaying profiles instead of reading files. Every surface was green.

DMS-MODE read neither of the two fields it names. recovery_model and log_chain_status became typed fields in v3.11.0, and the engine mentioned neither, so online DMS came back available on a source in SIMPLE recovery with a broken log chain — the one state the rule exists to refuse. Four combinations of the two produced the same answer. AVS-LICENSING and COPILOT-AGENT were in the same position with target_region and preview_acceptable.

The check written for exactly this compared the rule index against the schema, not against the engine. Declaring a field and reading it are different things. It compares both now, and a scenario carries the refusal.

The plan validator checked the rows a plan carried, never the rows it owed. A P10 plan cut from nineteen prerequisites to one, counts recalculated to agree, came back valid and ready. The catalog knows what a path owes and is asked now.

The exemplar plan failed its own output schema in 181 places. acceptedEvidence ids were resolved against sourceRegister, which types citations and cannot hold an evidence record. The one plan object shipped here was built to satisfy the validator and never run past the schema it claims to be. One evidence model now, and the exemplar is checked against the schema and the invariants in the same run.

Six DMS online scenarios state the recovery model and chain the rule requires. Three AVS scenarios drop to low confidence while a regional licence question is open.

73 gates, 3613 prerequisite checks, 117 scenarios.

v3.13.1 — the fork SKILL.md is derived

Choose a tag to compare

@fredgis fredgis released this 12 Sep 15:48
0b4088d

Five findings, and four of them were one file nobody was comparing.

The fork's SKILL.md was maintained by hand

It told the agent that its policy was already in context and that the skill read no file at run time, months after this repository said the opposite and granted read tools. A model following it reconstructs 70 KB of gates, rule IDs and schemas from memory.

That arrangement had already cost a review round once, and the fix then was partial: the port carried the capability line and the JSON blocks, on the reasoning that a human had deliberately rewritten the prose. The prose is where the instructions are.

The whole document is derived from upstream now, with two sections declared fork-owned by heading and a reason each. Anything else that differs is a failure, not a choice.

And the parity checker, which has existed for a while, was only ever run by the port itself, so forgetting to port left no trace anywhere. It runs on every suite now: fixing something here without porting it fails the build naming the section that drifted.

The other three

The copyable advisor_handoff example stopped validating against either accepted shape when the mirror gained three required provenance fields. A user following the canonical page was refused before their path was resolved. Fenced handoff examples are validated against the schema now.

A shortlist handoff was required to echo a controlPlane that a shortlist cannot carry, leaving the planner to emit invalid JSON or fabricate standalone — the defaulting defect v3.11.3 removed. It is required of a provisional handoff only.

The always-loaded exemplar labelled revisitable preferences as technical refusals, used a method gate to decide target eligibility, and claimed medium confidence and a General Purpose tier over unconfirmed prerequisites. Derived from the rules now: low, with the method gate rendered and a tier that stays unknown_requires_assessment.

Writing that found a rule ordering defect: SQL Agent set Azure SQL Database to remediation unconditionally, two lines after linked servers had refused it.

72 gates to 73, 3611 prerequisite checks.