Skip to content

feat(audience): add pull, push, and validate commands#728

Closed
meryldakin wants to merge 1 commit intomeryldakin/audience-read-commandsfrom
meryldakin/audience-filesystem-commands
Closed

feat(audience): add pull, push, and validate commands#728
meryldakin wants to merge 1 commit intomeryldakin/audience-read-commandsfrom
meryldakin/audience-filesystem-commands

Conversation

@meryldakin
Copy link
Contributor

Summary

  • Add audience pull: Download audiences from Knock to local filesystem
  • Add audience push: Upload audiences from filesystem to Knock
  • Add audience validate: Validate local audience files against API
  • Add audience marshal layer (processor, reader, writer, helpers)
  • Add audience directory detection in run-context loader
  • Add audience to project config resource directories
  • Update pull/push commands to handle audience resource type
  • Add audience factory for tests

Stack

This is PR 3 of 4 in the audience resource implementation stack:

  1. Foundation - Types, API methods, resource infrastructure
  2. Read Commands - list, get, open commands
  3. Filesystem Commands (this PR) - pull, push, validate commands + marshal layer
  4. Creation/Deletion - new, archive commands + generator

Depends on: #727

Test Plan

  • Tests included for all commands
  • Linting passes

🤖 Generated with Claude Code

Copy link
Contributor Author

meryldakin commented Mar 9, 2026

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.


await Promise.all(writeAudienceDirPromises);
} catch (error) {
console.log(error);
Copy link

Choose a reason for hiding this comment

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

Debug console.log left in error handler

Medium Severity

A console.log(error) statement is left in the catch block of writeAudiencesIndexDir. The equivalent writeWorkflowsIndexDir function in workflow/writer.ts does not have this, and the error is already re-thrown on the next line. This will leak raw error objects to stdout in production when a write failure occurs during a bulk pull operation.

Fix in Cursor Fix in Web

@meryldakin meryldakin marked this pull request as draft March 9, 2026 14:10
@meryldakin meryldakin force-pushed the meryldakin/audience-read-commands branch from a72033c to f2d954f Compare March 9, 2026 14:13
@meryldakin meryldakin force-pushed the meryldakin/audience-filesystem-commands branch from e88e4ae to 48a559a Compare March 9, 2026 14:13
@meryldakin meryldakin marked this pull request as ready for review March 9, 2026 14:13
}

return undefined;
};
Copy link

Choose a reason for hiding this comment

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

Exported validateAudienceKey function is never used

Low Severity

validateAudienceKey is exported from helpers.ts (and re-exported via index.ts) but is never called anywhere in the codebase. A grep for validateAudienceKey returns only its definition. This is dead code in the current PR, likely intended for the next PR in the stack (PR 4: new command), but adds unused surface area.

Fix in Cursor Fix in Web

@meryldakin meryldakin force-pushed the meryldakin/audience-read-commands branch from f2d954f to 38cdfb4 Compare March 9, 2026 14:20
@meryldakin meryldakin force-pushed the meryldakin/audience-filesystem-commands branch from 48a559a to dfca967 Compare March 9, 2026 14:20
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.


const promises = dirents.map(async (dirent) => {
const direntName = dirent.name.toLowerCase();
const direntPath = path.resolve(indexDirCtx.abspath, direntName);
Copy link

Choose a reason for hiding this comment

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

Lowercased path breaks pruning on case-sensitive filesystems

Medium Severity

In pruneAudiencesIndexDir, dirent.name is lowercased before constructing direntPath. On case-sensitive filesystems (Linux), if a directory has mixed-case naming (e.g., "VIP-Users"), direntPath points to a non-existent lowercased path. This causes isAudienceDir to check the wrong path and fs.remove to target a path that doesn't exist, meaning directories that should be pruned survive, and valid audience directories might not be recognized.

Fix in Cursor Fix in Web

Add filesystem-based audience commands:
- audience pull: Download audiences from Knock to local filesystem
- audience push: Upload audiences from filesystem to Knock
- audience validate: Validate local audience files against API

Supporting changes:
- Add audience marshal layer (processor, reader, writer, helpers)
- Add audience directory detection in run-context loader
- Add audience to project config resource directories
- Update pull/push commands to handle audience resource type
- Add audience factory for tests

Includes full test coverage for all commands.
@meryldakin meryldakin force-pushed the meryldakin/audience-read-commands branch from 38cdfb4 to 765af13 Compare March 9, 2026 14:32
@meryldakin meryldakin force-pushed the meryldakin/audience-filesystem-commands branch from dfca967 to d7d638b Compare March 9, 2026 14:32
@meryldakin
Copy link
Contributor Author

Superseded by #730 (combined PR)

@meryldakin meryldakin closed this Mar 9, 2026
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.

1 participant