Skip to content

fix: preserve decisions.md and team.md content during export/import - #1130

Merged
bradygaster merged 4 commits into
devfrom
bradygaster/squad-1122-fix-export-blank-files
May 18, 2026
Merged

bradygaster merged 4 commits into
devfrom
bradygaster/squad-1122-fix-export-blank-files

Conversation

@bradygaster

@bradygaster bradygaster commented May 18, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Fixes #1122 — Squad export/import was producing blank decisions.md and team.md files.

Root Cause

  1. Export never included decisions.md or team.md content in the manifest JSON
  2. Import explicitly wrote empty strings to both files (storage.writeSync(path.join(squadDir, 'decisions.md'), ''))

Fix

  • Export: Now reads and includes decisions.md and team.md content in the manifest under decisions and team fields
  • Import: Writes manifest content back (falls back to empty string for backward compatibility with older manifests that lack these fields)
  • Validation: Import validates that decisions and team fields are strings (if present), emitting a clear fatal error otherwise
  • Version: Export now uses getPackageVersion() instead of hard-coded '0.6.0'
  • Warning message: Updated to mention decisions/team content alongside agent histories
  • Bonus: Fixed a duplicate const hasForce declaration in index.cjs that caused a SyntaxError at runtime

Testing

  • All 8 skills-export-import tests pass (5 existing + 3 new)
  • New tests cover:
    • decisions.md and team.md fields present in exported manifest
    • Content round-trips correctly on import
    • Older manifests without these fields still import successfully

Copilot AI added 2 commits May 18, 2026 09:49
Export now includes decisions.md and team.md content in the manifest,
and import writes that content back instead of empty strings.

Also fixes a duplicate 'hasForce' variable declaration in index.cjs
that caused a SyntaxError at runtime.

Closes #1122

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes Squad CLI export/import so .squad/decisions.md and .squad/team.md content is preserved across round-trips, addressing the regression reported in #1122.

Changes:

  • Export now includes decisions.md and team.md content in the JSON manifest.
  • Import now restores decisions.md and team.md from the manifest (with backward-compatible fallbacks).
  • Fixes a duplicate const hasForce declaration in index.cjs that could cause a runtime SyntaxError.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
packages/squad-cli/src/cli/commands/import.ts Adds optional manifest fields and writes restored decisions.md / team.md during import.
packages/squad-cli/src/cli/commands/export.ts Reads decisions.md / team.md and includes them in the export manifest.
index.cjs Mirrors the export/import manifest updates in the legacy entrypoint and removes the duplicate hasForce.
.changeset/fix-export-import-blank-files.md Adds a patch changeset for the CLI fix.
Comments suppressed due to low confidence (3)

packages/squad-cli/src/cli/commands/export.ts:53

  • Export now includes additional project-specific content (decisions.md and team.md), but the post-export warning only mentions agent histories. Consider updating the warning/output to also call out decisions/team content so users reviewing the export know what else may contain sensitive info.
  // Read top-level squad files (decisions.md, team.md)
  const decisionsMd = path.join(squadInfo.path, 'decisions.md');
  const decisionsContent = storage.readSync(decisionsMd);
  if (decisionsContent !== undefined) {
    manifest.decisions = decisionsContent;
  }
  const teamContent = storage.readSync(teamMd);
  if (teamContent !== undefined) {
    manifest.team = teamContent;
  }

index.cjs:1161

  • Import writes manifest.decisions/team without validating their types. Since manifest is user-provided JSON, consider verifying decisions/team are strings when present (otherwise fatal with a clear error) to avoid fs.writeFileSync throwing a TypeError at runtime.
  // Write project-specific files from manifest (fall back to empty if not present)
  fs.writeFileSync(path.join(aiTeamDir, 'decisions.md'), manifest.decisions || '');
  fs.writeFileSync(path.join(aiTeamDir, 'team.md'), manifest.team || '');

packages/squad-cli/src/cli/commands/export.ts:53

  • These new reads of decisions.md/team.md aren’t wrapped in the try/catch pattern used for casting/agents/skills reads. FSStorageProvider.readSync returns undefined for ENOENT but will throw for other I/O errors (e.g., permissions), which would now abort export. Consider catching errors here and emitting a warning so export can still succeed when these files are unreadable.
  // Read top-level squad files (decisions.md, team.md)
  const decisionsMd = path.join(squadInfo.path, 'decisions.md');
  const decisionsContent = storage.readSync(decisionsMd);
  if (decisionsContent !== undefined) {
    manifest.decisions = decisionsContent;
  }
  const teamContent = storage.readSync(teamMd);
  if (teamContent !== undefined) {
    manifest.team = teamContent;
  }

Comment thread index.cjs Resolved
- Add validation that manifest.decisions and manifest.team are strings
- Replace hard-coded squad_version '0.6.0' with getPackageVersion()
- Update export warning to mention decisions/team content
- Add test coverage for decisions.md/team.md round-trip and backward
  compatibility with older manifests

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bradygaster

Copy link
Copy Markdown
Collaborator Author

@copilot resolve the merge conflicts in this pull request

Co-authored-by: bradygaster <41929050+bradygaster@users.noreply.github.com>

Copilot AI commented May 18, 2026 •

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Resolved. I merged the latest origin/dev, fixed the conflicts in packages/squad-cli/src/cli/commands/export.ts and packages/squad-cli/src/cli/commands/import.ts, validated with lint + targeted tests, and pushed merge commit ffe4d8a2.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • aka.ms
    • Triggering command: /usr/bin/../../opt/az/bin/python3 /usr/bin/../../opt/az/bin/python3 -Im azure.cli boards work-item type list --org REDACTED --project no-proj --output json get --global /home/REDACTED/.co--project credential.usern/usr/local/bin/node (dns block)
    • Triggering command: /usr/bin/../../opt/az/bin/python3 /usr/bin/../../opt/az/bin/python3 -Im azure.cli boards work-item type list --org REDACTED --project nonexistent-project --output json Sync}=require(&#39;fs&#39;);rmSync(&#39;dist/presets/builtin&#39;,{recursive:true,force:true});cpSync(&#39;src/presecat d-1122-fix-export-blank-files nfig/composer/vendor/bin/git (dns block)
    • Triggering command: /usr/bin/../../opt/az/bin/python3 /usr/bin/../../opt/az/bin/python3 -Im azure.cli boards work-item type list --org REDACTED --project no-proj --output json le.encode(&#39;utf-8&#39;)); (dns block)
  • app.aladdin.microsoft.com
    • Triggering command: /usr/bin/../../opt/az/bin/python3 /usr/bin/../../opt/az/bin/python3 -Im azure.cli boards work-item type list --org REDACTED --project no-proj --output json le.encode(&#39;utf-8&#39;)); (dns block)
    • Triggering command: /usr/bin/../../opt/az/bin/python3 /usr/bin/../../opt/az/bin/python3 -Im azure.cli boards work-item type list --org REDACTED --project no-proj --output json get --global /home/REDACTED/.co--project credential.usern/usr/local/bin/node (dns block)
    • Triggering command: /usr/bin/../../opt/az/bin/python3 /usr/bin/../../opt/az/bin/python3 -Im azure.cli boards work-item type list --org REDACTED --project no-proj --output json get --local rgo/bin/node pSync(&#39;src/presegetopt (dns block)
  • azcliprod.blob.core.windows.net
    • Triggering command: /usr/bin/../../opt/az/bin/python3 /usr/bin/../../opt/az/bin/python3 -Im azure.cli boards work-item type list --org REDACTED --project no-proj --output json le.encode(&#39;utf-8&#39;)); (dns block)
    • Triggering command: /usr/bin/../../opt/az/bin/python3 /usr/bin/../../opt/az/bin/python3 -Im azure.cli boards work-item type list --org REDACTED --project no-proj --output json get --global /home/REDACTED/.co--project credential.usern/usr/local/bin/node (dns block)
    • Triggering command: /usr/bin/../../opt/az/bin/python3 /usr/bin/../../opt/az/bin/python3 -Im azure.cli boards work-item type list --org REDACTED --project nonexistent-project --output json Sync}=require(&#39;fs&#39;);rmSync(&#39;dist/presets/builtin&#39;,{recursive:true,force:true});cpSync(&#39;src/presecat d-1122-fix-export-blank-files nfig/composer/vendor/bin/git (dns block)
  • https://api.github.com/user
    • Triggering command: /usr/bin/gh gh api user -q .login get-url origin ode_modules/npm/node_modules/@npmcli/run-script/lib/node-gyp-bin/git name &#34;Test User&#34;grep -shared /usr/bin/uniq git remo�� d&#34; | sort | uniq | wc -l origin /usr/sbin/git r/work/squad/squ/bin/sh -lutil /usr/bin/grep git (http block)
    • Triggering command: /usr/bin/gh gh api user -q .login --show-toplevel sh git node scripts/possort git /git git remo�� get-url origin p/bin/git in/git git ules/.bin/git git (http block)

If you need me to access, download, or install something from one of these locations, you can either:

@bradygaster
bradygaster merged commit c8c3cb6 into dev May 18, 2026
6 checks passed
@tamirdresher

Copy link
Copy Markdown
Collaborator

@bradygaster I think we need to make the decisions export optional. It might contain personal/private info in some repos (especially to HQ squads) and you might want to export only the core squad data.

Also, idea, should we have the squads go over the decision file to make sure it generic enough to be exported. Some of the decision are inky relevent to the repo they were created in and sharing them might cause problem when brought to another repo

@bradygaster
bradygaster deleted the bradygaster/squad-1122-fix-export-blank-files branch August 8, 2026 08:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Squad Export/Import: blank decisions.md, blank team.md.

5 participants