From 6b83ab75f32fc167062ae087c13d0e4a076cecb8 Mon Sep 17 00:00:00 2001 From: GiggleLiu Date: Thu, 12 Mar 2026 22:56:52 +0800 Subject: [PATCH 1/5] fix: address issue review comments for #126 and #117 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #599 (KSat→SubsetSum): Fix imprecise Karp 1972 attribution — the direct 3-SAT→SubsetSum digit encoding follows Sipser (2012, Thm 7.56) and CLRS (2022, §34.5.5), not Karp's original reduction tree. Add bib entries for both textbooks. PR #570 (GraphPartitioning): Add proper @citations for Garey, Johnson & Stockmeyer (1976) and Arora, Rao & Vazirani (2009) instead of plain-text references. Add bib entries for both papers. Regenerate problem_schemas.json and reduction_graph.json. Co-Authored-By: Claude Opus 4.6 --- docs/paper/reductions.typ | 4 +- docs/paper/references.bib | 38 +++++ docs/src/reductions/problem_schemas.json | 11 ++ docs/src/reductions/reduction_graph.json | 209 ++++++++++++----------- 4 files changed, 160 insertions(+), 102 deletions(-) diff --git a/docs/paper/reductions.typ b/docs/paper/reductions.typ index b08ca70f0..747996668 100644 --- a/docs/paper/reductions.typ +++ b/docs/paper/reductions.typ @@ -385,7 +385,7 @@ caption: [The house graph with max cut $S = {v_0, v_3}$ (blue) vs $overline(S) = Given an undirected graph $G = (V, E)$ with $|V| = n$ (even), find a partition of $V$ into two disjoint sets $A$ and $B$ with $|A| = |B| = n slash 2$ that minimizes the number of edges crossing the partition: $ "cut"(A, B) = |{(u, v) in E : u in A, v in B}|. $ ][ -Graph Partitioning is a core NP-hard problem arising in VLSI design, parallel computing, and scientific simulation, where balanced workload distribution with minimal communication is essential. Closely related to Max-Cut (which _maximizes_ rather than _minimizes_ the cut) and to the Ising Spin Glass model. NP-completeness was proved by Garey, Johnson and Stockmeyer (1976). Arora, Rao and Vazirani (2009) gave an $O(sqrt(log n))$-approximation algorithm. Standard partitioning tools include METIS, KaHIP, and Scotch. +Graph Partitioning is a core NP-hard problem arising in VLSI design, parallel computing, and scientific simulation, where balanced workload distribution with minimal communication is essential. Closely related to Max-Cut (which _maximizes_ rather than _minimizes_ the cut) and to the Ising Spin Glass model. NP-completeness was proved by Garey, Johnson and Stockmeyer @garey1976. Arora, Rao and Vazirani @arora2009 gave an $O(sqrt(log n))$-approximation algorithm. Standard partitioning tools include METIS, KaHIP, and Scotch. *Example.* Consider the graph $G$ with $n = 6$ vertices and 9 edges: $(v_0, v_1)$, $(v_0, v_2)$, $(v_1, v_2)$, $(v_1, v_3)$, $(v_2, v_3)$, $(v_2, v_4)$, $(v_3, v_4)$, $(v_3, v_5)$, $(v_4, v_5)$. The optimal balanced partition is $A = {v_0, v_1, v_2}$, $B = {v_3, v_4, v_5}$, with cut value 3: the crossing edges are $(v_1, v_3)$, $(v_2, v_3)$, $(v_2, v_4)$. All other balanced partitions yield a cut of at least 3. @@ -1198,7 +1198,7 @@ where $P$ is a penalty weight large enough that any constraint violation costs m Source config: #ksat_ss_sol.source_config #h(1em) Target config: #ksat_ss_sol.target_config ], )[ - Classical Karp reduction @karp1972 using base-10 digit encoding. Each integer has $(n + m)$ digits, where the first $n$ positions correspond to variables and the last $m$ to clauses. For variable $x_i$, two integers $y_i, z_i$ encode positive and negative literal occurrences. For clause $C_j$, slack integers $g_j, h_j$ pad the clause digit to exactly 4. Since each clause has at most 3 literals and slacks add at most 2, no digit exceeds 5, so no carries occur. + Base-10 digit encoding reduction following Sipser @sipser2012[Thm 7.56] and CLRS @cormen2022[§34.5.5]. (Karp @karp1972 established SubsetSum NP-completeness via Exact Cover; this direct 3-SAT construction is a later textbook formulation.) Each integer has $(n + m)$ digits, where the first $n$ positions correspond to variables and the last $m$ to clauses. For variable $x_i$, two integers $y_i, z_i$ encode positive and negative literal occurrences. For clause $C_j$, slack integers $g_j, h_j$ pad the clause digit to exactly 4. Since each clause has at most 3 literals and slacks add at most 2, no digit exceeds 5, so no carries occur. ][ _Construction._ Given a 3-CNF formula $phi$ with $n$ variables and $m$ clauses, create $2n + 2m$ integers in $(n+m)$-digit base-10 representation: diff --git a/docs/paper/references.bib b/docs/paper/references.bib index c3129a691..b69248331 100644 --- a/docs/paper/references.bib +++ b/docs/paper/references.bib @@ -387,3 +387,41 @@ @article{ibarra1975 year = {1975}, doi = {10.1145/321906.321909} } + +@book{sipser2012, + author = {Michael Sipser}, + title = {Introduction to the Theory of Computation}, + edition = {3rd}, + publisher = {Cengage Learning}, + year = {2012} +} + +@book{cormen2022, + author = {Thomas H. Cormen and Charles E. Leiserson and Ronald L. Rivest and Clifford Stein}, + title = {Introduction to Algorithms}, + edition = {4th}, + publisher = {MIT Press}, + year = {2022} +} + +@article{garey1976, + author = {Michael R. Garey and David S. Johnson and Larry Stockmeyer}, + title = {Some Simplified NP-Complete Graph Problems}, + journal = {Theoretical Computer Science}, + volume = {1}, + number = {3}, + pages = {237--267}, + year = {1976}, + doi = {10.1016/0304-3975(76)90059-1} +} + +@article{arora2009, + author = {Sanjeev Arora and Satish Rao and Umesh Vazirani}, + title = {Expander Flows, Geometric Embeddings and Graph Partitioning}, + journal = {Journal of the ACM}, + volume = {56}, + number = {2}, + pages = {1--37}, + year = {2009}, + doi = {10.1145/1502793.1502794} +} diff --git a/docs/src/reductions/problem_schemas.json b/docs/src/reductions/problem_schemas.json index ea93e5f67..4e60ebdcd 100644 --- a/docs/src/reductions/problem_schemas.json +++ b/docs/src/reductions/problem_schemas.json @@ -110,6 +110,17 @@ } ] }, + { + "name": "GraphPartitioning", + "description": "Find minimum cut balanced bisection of a graph", + "fields": [ + { + "name": "graph", + "type_name": "G", + "description": "The undirected graph G=(V,E)" + } + ] + }, { "name": "ILP", "description": "Optimize linear objective subject to linear constraints", diff --git a/docs/src/reductions/reduction_graph.json b/docs/src/reductions/reduction_graph.json index dcef7eae0..ce418d783 100644 --- a/docs/src/reductions/reduction_graph.json +++ b/docs/src/reductions/reduction_graph.json @@ -64,6 +64,15 @@ "doc_path": "models/misc/struct.Factoring.html", "complexity": "exp((m + n)^(1/3) * log(m + n)^(2/3))" }, + { + "name": "GraphPartitioning", + "variant": { + "graph": "SimpleGraph" + }, + "category": "graph", + "doc_path": "models/graph/struct.GraphPartitioning.html", + "complexity": "2^num_vertices" + }, { "name": "ILP", "variant": { @@ -396,7 +405,7 @@ "edges": [ { "source": 4, - "target": 8, + "target": 9, "overhead": [ { "field": "num_vars", @@ -411,7 +420,7 @@ }, { "source": 4, - "target": 40, + "target": 41, "overhead": [ { "field": "num_spins", @@ -441,7 +450,7 @@ }, { "source": 7, - "target": 9, + "target": 10, "overhead": [ { "field": "num_vars", @@ -455,8 +464,8 @@ "doc_path": "rules/factoring_ilp/index.html" }, { - "source": 8, - "target": 9, + "source": 9, + "target": 10, "overhead": [ { "field": "num_vars", @@ -470,8 +479,8 @@ "doc_path": "rules/ilp_bool_ilp_i32/index.html" }, { - "source": 8, - "target": 37, + "source": 9, + "target": 38, "overhead": [ { "field": "num_vars", @@ -481,8 +490,8 @@ "doc_path": "rules/ilp_qubo/index.html" }, { - "source": 11, - "target": 14, + "source": 12, + "target": 15, "overhead": [ { "field": "num_vertices", @@ -496,8 +505,8 @@ "doc_path": "rules/kcoloring_casts/index.html" }, { - "source": 14, - "target": 8, + "source": 15, + "target": 9, "overhead": [ { "field": "num_vars", @@ -511,8 +520,8 @@ "doc_path": "rules/coloring_ilp/index.html" }, { - "source": 14, - "target": 37, + "source": 15, + "target": 38, "overhead": [ { "field": "num_vars", @@ -522,8 +531,8 @@ "doc_path": "rules/coloring_qubo/index.html" }, { - "source": 15, - "target": 17, + "source": 16, + "target": 18, "overhead": [ { "field": "num_vars", @@ -537,8 +546,8 @@ "doc_path": "rules/ksatisfiability_casts/index.html" }, { - "source": 15, - "target": 37, + "source": 16, + "target": 38, "overhead": [ { "field": "num_vars", @@ -548,8 +557,8 @@ "doc_path": "rules/ksatisfiability_qubo/index.html" }, { - "source": 16, - "target": 17, + "source": 17, + "target": 18, "overhead": [ { "field": "num_vars", @@ -563,8 +572,8 @@ "doc_path": "rules/ksatisfiability_casts/index.html" }, { - "source": 16, - "target": 37, + "source": 17, + "target": 38, "overhead": [ { "field": "num_vars", @@ -574,8 +583,8 @@ "doc_path": "rules/ksatisfiability_qubo/index.html" }, { - "source": 16, - "target": 41, + "source": 17, + "target": 42, "overhead": [ { "field": "num_elements", @@ -585,8 +594,8 @@ "doc_path": "rules/ksatisfiability_subsetsum/index.html" }, { - "source": 17, - "target": 38, + "source": 18, + "target": 39, "overhead": [ { "field": "num_clauses", @@ -604,8 +613,8 @@ "doc_path": "rules/sat_ksat/index.html" }, { - "source": 19, - "target": 40, + "source": 20, + "target": 41, "overhead": [ { "field": "num_spins", @@ -619,8 +628,8 @@ "doc_path": "rules/spinglass_maxcut/index.html" }, { - "source": 21, - "target": 8, + "source": 22, + "target": 9, "overhead": [ { "field": "num_vars", @@ -634,8 +643,8 @@ "doc_path": "rules/maximumclique_ilp/index.html" }, { - "source": 22, - "target": 23, + "source": 23, + "target": 24, "overhead": [ { "field": "num_vertices", @@ -649,8 +658,8 @@ "doc_path": "rules/maximumindependentset_casts/index.html" }, { - "source": 22, - "target": 27, + "source": 23, + "target": 28, "overhead": [ { "field": "num_vertices", @@ -664,8 +673,8 @@ "doc_path": "rules/maximumindependentset_casts/index.html" }, { - "source": 23, - "target": 28, + "source": 24, + "target": 29, "overhead": [ { "field": "num_vertices", @@ -679,8 +688,8 @@ "doc_path": "rules/maximumindependentset_casts/index.html" }, { - "source": 24, - "target": 22, + "source": 25, + "target": 23, "overhead": [ { "field": "num_vertices", @@ -694,8 +703,8 @@ "doc_path": "rules/maximumindependentset_gridgraph/index.html" }, { - "source": 24, - "target": 25, + "source": 25, + "target": 26, "overhead": [ { "field": "num_vertices", @@ -709,8 +718,8 @@ "doc_path": "rules/maximumindependentset_casts/index.html" }, { - "source": 24, - "target": 26, + "source": 25, + "target": 27, "overhead": [ { "field": "num_vertices", @@ -724,8 +733,8 @@ "doc_path": "rules/maximumindependentset_triangular/index.html" }, { - "source": 24, - "target": 30, + "source": 25, + "target": 31, "overhead": [ { "field": "num_sets", @@ -739,8 +748,8 @@ "doc_path": "rules/maximumindependentset_maximumsetpacking/index.html" }, { - "source": 25, - "target": 32, + "source": 26, + "target": 33, "overhead": [ { "field": "num_sets", @@ -754,8 +763,8 @@ "doc_path": "rules/maximumindependentset_maximumsetpacking/index.html" }, { - "source": 25, - "target": 35, + "source": 26, + "target": 36, "overhead": [ { "field": "num_vertices", @@ -769,8 +778,8 @@ "doc_path": "rules/minimumvertexcover_maximumindependentset/index.html" }, { - "source": 26, - "target": 28, + "source": 27, + "target": 29, "overhead": [ { "field": "num_vertices", @@ -784,8 +793,8 @@ "doc_path": "rules/maximumindependentset_casts/index.html" }, { - "source": 27, - "target": 24, + "source": 28, + "target": 25, "overhead": [ { "field": "num_vertices", @@ -799,8 +808,8 @@ "doc_path": "rules/maximumindependentset_casts/index.html" }, { - "source": 27, - "target": 28, + "source": 28, + "target": 29, "overhead": [ { "field": "num_vertices", @@ -814,8 +823,8 @@ "doc_path": "rules/maximumindependentset_casts/index.html" }, { - "source": 28, - "target": 25, + "source": 29, + "target": 26, "overhead": [ { "field": "num_vertices", @@ -829,8 +838,8 @@ "doc_path": "rules/maximumindependentset_casts/index.html" }, { - "source": 29, - "target": 8, + "source": 30, + "target": 9, "overhead": [ { "field": "num_vars", @@ -844,8 +853,8 @@ "doc_path": "rules/maximummatching_ilp/index.html" }, { - "source": 29, - "target": 32, + "source": 30, + "target": 33, "overhead": [ { "field": "num_sets", @@ -859,8 +868,8 @@ "doc_path": "rules/maximummatching_maximumsetpacking/index.html" }, { - "source": 30, - "target": 24, + "source": 31, + "target": 25, "overhead": [ { "field": "num_vertices", @@ -874,8 +883,8 @@ "doc_path": "rules/maximumindependentset_maximumsetpacking/index.html" }, { - "source": 30, - "target": 32, + "source": 31, + "target": 33, "overhead": [ { "field": "num_sets", @@ -889,8 +898,8 @@ "doc_path": "rules/maximumsetpacking_casts/index.html" }, { - "source": 31, - "target": 37, + "source": 32, + "target": 38, "overhead": [ { "field": "num_vars", @@ -900,8 +909,8 @@ "doc_path": "rules/maximumsetpacking_qubo/index.html" }, { - "source": 32, - "target": 8, + "source": 33, + "target": 9, "overhead": [ { "field": "num_vars", @@ -915,8 +924,8 @@ "doc_path": "rules/maximumsetpacking_ilp/index.html" }, { - "source": 32, - "target": 25, + "source": 33, + "target": 26, "overhead": [ { "field": "num_vertices", @@ -930,8 +939,8 @@ "doc_path": "rules/maximumindependentset_maximumsetpacking/index.html" }, { - "source": 32, - "target": 31, + "source": 33, + "target": 32, "overhead": [ { "field": "num_sets", @@ -945,8 +954,8 @@ "doc_path": "rules/maximumsetpacking_casts/index.html" }, { - "source": 33, - "target": 8, + "source": 34, + "target": 9, "overhead": [ { "field": "num_vars", @@ -960,8 +969,8 @@ "doc_path": "rules/minimumdominatingset_ilp/index.html" }, { - "source": 34, - "target": 8, + "source": 35, + "target": 9, "overhead": [ { "field": "num_vars", @@ -975,8 +984,8 @@ "doc_path": "rules/minimumsetcovering_ilp/index.html" }, { - "source": 35, - "target": 25, + "source": 36, + "target": 26, "overhead": [ { "field": "num_vertices", @@ -990,8 +999,8 @@ "doc_path": "rules/minimumvertexcover_maximumindependentset/index.html" }, { - "source": 35, - "target": 34, + "source": 36, + "target": 35, "overhead": [ { "field": "num_sets", @@ -1005,8 +1014,8 @@ "doc_path": "rules/minimumvertexcover_minimumsetcovering/index.html" }, { - "source": 37, - "target": 8, + "source": 38, + "target": 9, "overhead": [ { "field": "num_vars", @@ -1020,8 +1029,8 @@ "doc_path": "rules/qubo_ilp/index.html" }, { - "source": 37, - "target": 39, + "source": 38, + "target": 40, "overhead": [ { "field": "num_spins", @@ -1031,7 +1040,7 @@ "doc_path": "rules/spinglass_qubo/index.html" }, { - "source": 38, + "source": 39, "target": 4, "overhead": [ { @@ -1046,8 +1055,8 @@ "doc_path": "rules/sat_circuitsat/index.html" }, { - "source": 38, - "target": 11, + "source": 39, + "target": 12, "overhead": [ { "field": "num_vertices", @@ -1061,8 +1070,8 @@ "doc_path": "rules/sat_coloring/index.html" }, { - "source": 38, - "target": 16, + "source": 39, + "target": 17, "overhead": [ { "field": "num_clauses", @@ -1076,8 +1085,8 @@ "doc_path": "rules/sat_ksat/index.html" }, { - "source": 38, - "target": 24, + "source": 39, + "target": 25, "overhead": [ { "field": "num_vertices", @@ -1091,8 +1100,8 @@ "doc_path": "rules/sat_maximumindependentset/index.html" }, { - "source": 38, - "target": 33, + "source": 39, + "target": 34, "overhead": [ { "field": "num_vertices", @@ -1106,8 +1115,8 @@ "doc_path": "rules/sat_minimumdominatingset/index.html" }, { - "source": 39, - "target": 37, + "source": 40, + "target": 38, "overhead": [ { "field": "num_vars", @@ -1117,8 +1126,8 @@ "doc_path": "rules/spinglass_qubo/index.html" }, { - "source": 40, - "target": 19, + "source": 41, + "target": 20, "overhead": [ { "field": "num_vertices", @@ -1132,8 +1141,8 @@ "doc_path": "rules/spinglass_maxcut/index.html" }, { - "source": 40, - "target": 39, + "source": 41, + "target": 40, "overhead": [ { "field": "num_spins", @@ -1147,8 +1156,8 @@ "doc_path": "rules/spinglass_casts/index.html" }, { - "source": 42, - "target": 8, + "source": 43, + "target": 9, "overhead": [ { "field": "num_vars", From 98b9cfdb20e2726919dffdf7d6da16acaf751246 Mon Sep 17 00:00:00 2001 From: GiggleLiu Date: Thu, 12 Mar 2026 23:01:18 +0800 Subject: [PATCH 2/5] fix: add FPT complexity citation for GraphPartitioning (#117) Address review comment: explicitly state that brute-force O*(2^n) is the best known unconditional exact algorithm, and cite Cygan et al. (STOC 2014 / SICOMP 2019) for the FPT result parameterized by bisection width. Co-Authored-By: Claude Opus 4.6 --- docs/paper/reductions.typ | 2 +- docs/paper/references.bib | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/paper/reductions.typ b/docs/paper/reductions.typ index 747996668..a30d1b73b 100644 --- a/docs/paper/reductions.typ +++ b/docs/paper/reductions.typ @@ -385,7 +385,7 @@ caption: [The house graph with max cut $S = {v_0, v_3}$ (blue) vs $overline(S) = Given an undirected graph $G = (V, E)$ with $|V| = n$ (even), find a partition of $V$ into two disjoint sets $A$ and $B$ with $|A| = |B| = n slash 2$ that minimizes the number of edges crossing the partition: $ "cut"(A, B) = |{(u, v) in E : u in A, v in B}|. $ ][ -Graph Partitioning is a core NP-hard problem arising in VLSI design, parallel computing, and scientific simulation, where balanced workload distribution with minimal communication is essential. Closely related to Max-Cut (which _maximizes_ rather than _minimizes_ the cut) and to the Ising Spin Glass model. NP-completeness was proved by Garey, Johnson and Stockmeyer @garey1976. Arora, Rao and Vazirani @arora2009 gave an $O(sqrt(log n))$-approximation algorithm. Standard partitioning tools include METIS, KaHIP, and Scotch. +Graph Partitioning is a core NP-hard problem arising in VLSI design, parallel computing, and scientific simulation, where balanced workload distribution with minimal communication is essential. Closely related to Max-Cut (which _maximizes_ rather than _minimizes_ the cut) and to the Ising Spin Glass model. NP-completeness was proved by Garey, Johnson and Stockmeyer @garey1976. Arora, Rao and Vazirani @arora2009 gave an $O(sqrt(log n))$-approximation algorithm. The best known unconditional exact algorithm is brute-force enumeration of all $binom(n, n slash 2) = O^*(2^n)$ balanced partitions; no faster worst-case algorithm is known. Cygan et al. @cygan2014 showed that Minimum Bisection is fixed-parameter tractable in $O(2^(O(k^3)) dot n^3 log^3 n)$ time parameterized by bisection width $k$. Standard partitioning tools include METIS, KaHIP, and Scotch. *Example.* Consider the graph $G$ with $n = 6$ vertices and 9 edges: $(v_0, v_1)$, $(v_0, v_2)$, $(v_1, v_2)$, $(v_1, v_3)$, $(v_2, v_3)$, $(v_2, v_4)$, $(v_3, v_4)$, $(v_3, v_5)$, $(v_4, v_5)$. The optimal balanced partition is $A = {v_0, v_1, v_2}$, $B = {v_3, v_4, v_5}$, with cut value 3: the crossing edges are $(v_1, v_3)$, $(v_2, v_3)$, $(v_2, v_4)$. All other balanced partitions yield a cut of at least 3. diff --git a/docs/paper/references.bib b/docs/paper/references.bib index b69248331..a68de5c4b 100644 --- a/docs/paper/references.bib +++ b/docs/paper/references.bib @@ -425,3 +425,15 @@ @article{arora2009 year = {2009}, doi = {10.1145/1502793.1502794} } + +@article{cygan2014, + author = {Marek Cygan and Daniel Lokshtanov and Marcin Pilipczuk and Micha{\l} Pilipczuk and Saket Saurabh}, + title = {Minimum Bisection Is Fixed Parameter Tractable}, + journal = {SIAM Journal on Computing}, + volume = {48}, + number = {2}, + pages = {417--450}, + year = {2019}, + note = {Conference version: STOC 2014}, + doi = {10.1137/140990255} +} From 6676a1b7f18baa56abf729f90164cf75843ae42c Mon Sep 17 00:00:00 2001 From: GiggleLiu Date: Thu, 12 Mar 2026 23:08:32 +0800 Subject: [PATCH 3/5] fix: use sort_by_key per clippy unnecessary_sort_by lint Co-Authored-By: Claude Opus 4.6 --- examples/detect_isolated_problems.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/detect_isolated_problems.rs b/examples/detect_isolated_problems.rs index e2a359c79..209b61b17 100644 --- a/examples/detect_isolated_problems.rs +++ b/examples/detect_isolated_problems.rs @@ -53,7 +53,7 @@ fn main() { } // Sort components by size (largest first) - components.sort_by(|a, b| b.len().cmp(&a.len())); + components.sort_by_key(|b| std::cmp::Reverse(b.len())); // Identify isolated types (no edges at all) let isolated: Vec<&str> = types From c660d53b1ec3641f52ee87cf38dcf8298703bc92 Mon Sep 17 00:00:00 2001 From: GiggleLiu Date: Thu, 12 Mar 2026 23:10:40 +0800 Subject: [PATCH 4/5] feat: add merge-with-main conflict resolution step to review-pipeline Add Step 1a between checkout and Copilot fixes to merge origin/main into the PR branch. Resolves simple conflicts automatically; aborts and reports for complex conflicts needing manual resolution. Co-Authored-By: Claude Opus 4.6 --- .claude/skills/review-pipeline/SKILL.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.claude/skills/review-pipeline/SKILL.md b/.claude/skills/review-pipeline/SKILL.md index f9c5bf81f..c61d183dc 100644 --- a/.claude/skills/review-pipeline/SKILL.md +++ b/.claude/skills/review-pipeline/SKILL.md @@ -82,6 +82,22 @@ cd "$WORKTREE_DIR" All subsequent steps run inside the worktree. +### 1a. Resolve Conflicts with Main + +Check if the branch has merge conflicts with main: + +```bash +git fetch origin main +git merge origin/main --no-edit +``` + +- If the merge succeeds cleanly: push the merge commit and continue. +- If there are conflicts: + 1. Inspect the conflicting files with `git diff --name-only --diff-filter=U`. + 2. Resolve conflicts (prefer the PR branch for new code, main for regenerated artifacts like JSON). + 3. Stage resolved files, commit, and push. +- If conflicts are too complex to resolve automatically (e.g., overlapping logic changes in the same function): abort the merge (`git merge --abort`), leave the PR in review-agentic, and report: `PR #N has complex merge conflicts with main — needs manual resolution.` Then STOP processing this PR. + ### 2. Fix Copilot Review Comments Copilot review is guaranteed to exist (verified in Step 0). Fetch the comments: @@ -210,3 +226,4 @@ Completed: 2/2 | All moved to In Review | Not checking out the right branch | Use `gh pr view` to get the exact branch name | | Worktree left behind on failure | Always clean up with `git worktree remove` in Step 5 | | Working in main checkout | All work happens in `.worktrees/` — never modify the main checkout | +| Skipping merge with main | Always merge origin/main in Step 1a to catch conflicts before fixing comments | From 16c5b18d7ae9d37c3d26b89dd15f601e1aedf0b1 Mon Sep 17 00:00:00 2001 From: GiggleLiu Date: Thu, 12 Mar 2026 23:13:06 +0800 Subject: [PATCH 5/5] update pipeline skills: eligibility-first sorting, merge-with-main project-pipeline: Reorder Steps 0c/0d so eligibility check (source and target models exist) runs before scoring. Only eligible issues get scored. review-pipeline: Add Step 1a to merge origin/main into the PR branch before fixing Copilot comments, catching conflicts early. Co-Authored-By: Claude Opus 4.6 --- .claude/skills/project-pipeline/SKILL.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/.claude/skills/project-pipeline/SKILL.md b/.claude/skills/project-pipeline/SKILL.md index 73ff0b02d..eee7baa4b 100644 --- a/.claude/skills/project-pipeline/SKILL.md +++ b/.claude/skills/project-pipeline/SKILL.md @@ -48,9 +48,19 @@ Filter items where `status == "Ready"`. Partition into `[Model]` and `[Rule]` bu 1. **Existing problems:** Call `list_problems` (MCP tool) to get all problems currently in the reduction graph. 2. **Pending rules:** From the full project board JSON, collect all `[Rule]` issues that are in "Ready" or "In Progress" status. Parse their source/target problem names (e.g., `[Rule] BinPacking to ILP` → source=BinPacking, target=ILP). -#### 0c. Score Each Issue +#### 0c. Check Eligibility -Score each Ready issue on three criteria. For `[Model]` issues, extract the problem name. For `[Rule]` issues, extract both source and target problem names. +**Rule issues require both source and target models to exist.** For each `[Rule]` issue, parse the source and target problem names (e.g., `[Rule] BinPacking to ILP` → source=BinPacking, target=ILP). Check that both appear in the `list_problems` output (existing models) OR in a `[Model]` issue in the current Ready/In Progress columns. + +- If both models exist → **eligible** +- If a missing model has a `[Model]` issue in Ready → eligible only in `--all` mode (the Model will be processed first); in single-issue mode, **skip this Rule** and mark it `[blocked]` +- If a missing model has no `[Model]` issue at all → **ineligible**, mark it `[blocked]` with reason + +All `[Model]` issues are always eligible (no dependency check needed). + +#### 0d. Score Eligible Issues + +Score only **eligible** issues on three criteria. For `[Model]` issues, extract the problem name. For `[Rule]` issues, extract both source and target problem names. | Criterion | Weight | How to Assess | |-----------|--------|---------------| @@ -64,14 +74,6 @@ Score each Ready issue on three criteria. For `[Model]` issues, extract the prob **Important for C2:** A problem that is merely a weighted/unweighted variant or a graph-subtype specialization of an existing problem scores **0** on C2, not 2. The goal is to add genuinely new problem types that expand the graph's reach. -#### 0d. Apply Hard Constraints - -**Rule issues require both source and target models to exist.** For each `[Rule]` issue, check that both its source and target problem names appear in the `list_problems` output (existing models) OR in a `[Model]` issue in the current Ready/In Progress columns. - -- If both models exist → eligible -- If a missing model has a `[Model]` issue in Ready → eligible only in `--all` mode (the Model will be processed first); in single-issue mode, **skip this Rule** and mark it `[blocked]` -- If a missing model has no `[Model]` issue at all → **ineligible**, mark it `[blocked]` with reason - #### 0e. Print Ranked List Print all Ready issues with their scores for visibility (no confirmation needed). Blocked rules appear at the bottom with their reason: