Skip to content

Commit bbf1e9f

Browse files
authored
Merge branch 'github:main' into main
2 parents ba11284 + b5db159 commit bbf1e9f

6 files changed

Lines changed: 415 additions & 72 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ The following community-contributed extensions are available in [`catalog.commun
268268
| Spec Reference Loader | Reads the ## References section from the feature spec and loads only the listed docs into context | `docs` | Read-only | [spec-kit-spec-reference-loader](https://github.com/KevinBrown5280/spec-kit-spec-reference-loader) |
269269
| Spec Critique Extension | Dual-lens critical review of spec and plan from product strategy and engineering risk perspectives | `docs` | Read-only | [spec-kit-critique](https://github.com/arunt14/spec-kit-critique) |
270270
| Spec Diagram | Auto-generate Mermaid diagrams of SDD workflow state, feature progress, and task dependencies | `visibility` | Read-only | [spec-kit-diagram-](https://github.com/Quratulain-bilal/spec-kit-diagram-) |
271+
| Spec Kit Schedule | Optimal multi-agent task scheduling via CP-SAT — DAG precedence, hallucination-aware caps, file-conflict avoidance, stochastic durations, replanning, and interactive HTML output | `process` | Read+Write | [spec-kit-schedule](https://github.com/jfranc38/spec-kit-schedule) |
271272
| Spec Orchestrator | Cross-feature orchestration — track state, select tasks, and detect conflicts across parallel specs | `process` | Read-only | [spec-kit-orchestrator](https://github.com/Quratulain-bilal/spec-kit-orchestrator) |
272273
| Spec Refine | Update specs in-place, propagate changes to plan and tasks, and diff impact across artifacts | `process` | Read+Write | [spec-kit-refine](https://github.com/Quratulain-bilal/spec-kit-refine) |
273274
| Spec Scope | Effort estimation and scope tracking — estimate work, detect creep, and budget time per phase | `process` | Read-only | [spec-kit-scope-](https://github.com/Quratulain-bilal/spec-kit-scope-) |

extensions/catalog.community.json

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"schema_version": "1.0",
3-
"updated_at": "2026-05-07T15:37:14Z",
3+
"updated_at": "2026-05-07T20:05:00Z",
44
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/extensions/catalog.community.json",
55
"extensions": {
66
"aide": {
@@ -2145,6 +2145,38 @@
21452145
"created_at": "2026-04-20T00:00:00Z",
21462146
"updated_at": "2026-04-20T00:00:00Z"
21472147
},
2148+
"schedule": {
2149+
"name": "Spec Kit Schedule — CP-SAT Agent Orchestrator",
2150+
"id": "schedule",
2151+
"description": "Optimal multi-agent task scheduling via CP-SAT solver with DAG precedence, hallucination-aware caps, file-conflict avoidance, stochastic durations, replanning, and interactive HTML output",
2152+
"author": "Julio César Franco Ardila",
2153+
"version": "0.6.2",
2154+
"download_url": "https://github.com/jfranc38/spec-kit-schedule/archive/refs/tags/v0.6.2.zip",
2155+
"repository": "https://github.com/jfranc38/spec-kit-schedule",
2156+
"homepage": "https://github.com/jfranc38/spec-kit-schedule",
2157+
"documentation": "https://github.com/jfranc38/spec-kit-schedule/blob/main/README.md",
2158+
"changelog": "https://github.com/jfranc38/spec-kit-schedule/blob/main/CHANGELOG.md",
2159+
"license": "MIT",
2160+
"requires": {
2161+
"speckit_version": ">=0.4.0"
2162+
},
2163+
"provides": {
2164+
"commands": 5,
2165+
"hooks": 1
2166+
},
2167+
"tags": [
2168+
"scheduling",
2169+
"optimization",
2170+
"multi-agent",
2171+
"cp-sat",
2172+
"operations-research"
2173+
],
2174+
"verified": false,
2175+
"downloads": 0,
2176+
"stars": 0,
2177+
"created_at": "2026-05-06T22:35:00Z",
2178+
"updated_at": "2026-05-07T17:25:00Z"
2179+
},
21482180
"scope": {
21492181
"name": "Spec Scope",
21502182
"id": "scope",

src/specify_cli/__init__.py

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,8 @@ def _install_shared_infra(
769769
tracker: StepTracker | None = None,
770770
force: bool = False,
771771
invoke_separator: str = ".",
772+
refresh_managed: bool = False,
773+
refresh_hint: str | None = None,
772774
) -> bool:
773775
"""Install shared infrastructure files into *project_path*.
774776
@@ -780,9 +782,23 @@ def _install_shared_infra(
780782
placeholders using *invoke_separator* (``"."`` for markdown agents,
781783
``"-"`` for skills agents).
782784
783-
When *force* is ``True``, existing files are overwritten with the
784-
latest bundled versions. When ``False`` (default), only missing
785-
files are added and existing ones are skipped.
785+
Overwrite policy:
786+
787+
* ``force=True`` — overwrite every existing file (still skips symlinks
788+
to avoid following links outside the project root).
789+
* ``refresh_managed=True`` — overwrite only files whose on-disk hash
790+
still matches the previously recorded manifest hash (i.e. unmodified
791+
files installed by spec-kit). Files with diverging hashes are
792+
treated as user customizations and preserved with a warning.
793+
* Default — only add missing files; existing ones are skipped.
794+
795+
*refresh_hint* — caller-supplied rich-text fragment shown after the
796+
"Preserved customized files" warning to tell the user which flag/command
797+
they should re-run with to overwrite their customizations. Each caller
798+
passes the flag that's actually valid in its CLI surface (e.g.
799+
``--refresh-shared-infra`` for ``integration switch``,
800+
``--force`` for ``init``/``integration upgrade``). When ``None``, no
801+
remediation hint is printed for customizations.
786802
787803
Returns ``True`` on success.
788804
"""
@@ -795,6 +811,8 @@ def _install_shared_infra(
795811
console=console,
796812
force=force,
797813
invoke_separator=invoke_separator,
814+
refresh_managed=refresh_managed,
815+
refresh_hint=refresh_hint,
798816
)
799817

800818

@@ -804,6 +822,8 @@ def _install_shared_infra_or_exit(
804822
tracker: StepTracker | None = None,
805823
force: bool = False,
806824
invoke_separator: str = ".",
825+
refresh_managed: bool = False,
826+
refresh_hint: str | None = None,
807827
) -> bool:
808828
try:
809829
return _install_shared_infra(
@@ -812,6 +832,8 @@ def _install_shared_infra_or_exit(
812832
tracker=tracker,
813833
force=force,
814834
invoke_separator=invoke_separator,
835+
refresh_managed=refresh_managed,
836+
refresh_hint=refresh_hint,
815837
)
816838
except (ValueError, OSError) as exc:
817839
console.print(f"[red]Error:[/red] Failed to install shared infrastructure: {exc}")
@@ -2583,7 +2605,8 @@ def integration_uninstall(
25832605
def integration_switch(
25842606
target: str = typer.Argument(help="Integration key to switch to"),
25852607
script: str | None = typer.Option(None, "--script", help="Script type: sh or ps (default: from init-options.json or platform default)"),
2586-
force: bool = typer.Option(False, "--force", help="Force removal of modified files during uninstall"),
2608+
force: bool = typer.Option(False, "--force", help="Force removal of modified files during uninstall of the previous integration"),
2609+
refresh_shared_infra: bool = typer.Option(False, "--refresh-shared-infra", help="Also overwrite shared infrastructure files even if you customized them (otherwise customizations are preserved)"),
25872610
integration_options: str | None = typer.Option(None, "--integration-options", help='Options for the target integration'),
25882611
):
25892612
"""Switch from the current integration to a different one."""
@@ -2754,14 +2777,27 @@ def integration_switch(
27542777
target_integration, current, target, integration_options
27552778
)
27562779

2757-
# Ensure shared infrastructure is present (safe to run unconditionally;
2758-
# _install_shared_infra merges missing files without overwriting).
2780+
# Refresh shared infrastructure to the current CLI version. Switching
2781+
# integrations is exactly when stale vendored shared scripts (e.g.
2782+
# update-agent-context.sh that pre-dates the target integration's
2783+
# supported-agent list) would silently break the new integration.
2784+
#
2785+
# Use refresh_managed=True so only files that match their previously
2786+
# recorded hash are overwritten — user customizations are detected via
2787+
# hash divergence and preserved with a warning. Pass
2788+
# --refresh-shared-infra to overwrite customizations as well. See #2293.
27592789
_install_shared_infra_or_exit(
27602790
project_root,
27612791
selected_script,
2792+
force=refresh_shared_infra,
2793+
refresh_managed=True,
27622794
invoke_separator=_invoke_separator_for_integration(
27632795
target_integration, current, target, parsed_options
27642796
),
2797+
refresh_hint=(
2798+
"To overwrite customizations, re-run with "
2799+
"[cyan]specify integration switch ... --refresh-shared-infra[/cyan]."
2800+
),
27652801
)
27662802
if os.name != "nt":
27672803
ensure_executable_scripts(project_root)

0 commit comments

Comments
 (0)