Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
.rspec_status

# Personal, private notes kept locally and excluded from the repo
# (e.g. the development diary "how-i-created-my-first-ruby-gem-with-kiro.md").
/private-notes/

# Built gem artifacts
Expand All @@ -20,3 +19,13 @@
# Gems should not commit their lockfile (Bundler resolves it per environment).
# Committing it here pinned Bundler 4.x, which breaks CI on Ruby < 3.2.
/Gemfile.lock

# Local example consumer project: Bundler resolves its lockfile per environment
# (same reasoning as the root Gemfile.lock above), so it is not committed.
/examples/local-consumer/Gemfile.lock
/examples/local-consumer/.bundle/
graphify-out/
.graphify-cache/

# Custom File
hermes-run.sh
14 changes: 13 additions & 1 deletion .kiro/steering/structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## Directory layout

```
password_forge/
password-forge-ruby-gem/ # repo root
├── lib/
│ ├── password_forge.rb # Entry point: requires all components
│ └── password_forge/
Expand All @@ -19,7 +19,16 @@ password_forge/
│ ├── charset_spec.rb
│ ├── validation_spec.rb
│ └── generator_spec.rb
├── examples/ # Runnable local demos (not packaged)
│ ├── smoke_test.rb # Loads the gem from source and prints samples
│ └── local-consumer/ # Mini "external" project using the gem via path:
│ ├── Gemfile
│ └── run.rb
├── docs/ # Extended documentation (not packaged)
│ ├── README.md # Docs index
│ └── local-testing.md # How to try the gem locally
├── sig/ # RBS type signatures
├── bin/ # setup + console helper scripts
├── .github/workflows/
│ ├── main.yml # CI: RSpec matrix + RuboCop
│ └── release.yml # Trusted Publishing on v* tags
Expand All @@ -33,6 +42,9 @@ password_forge/
└── LICENSE.txt
```

`Gemfile.lock` is generated per environment and git-ignored (see Tech), so it is
not part of the tracked tree above.

## Architecture

The internal design mirrors the original C# separation of concerns while
Expand Down
2 changes: 1 addition & 1 deletion .kiro/steering/tech.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The gem has **no runtime dependencies**.

## Common commands

Run from the `password_forge/` directory:
Run from the repository root (`password-forge-ruby-gem/`):

```bash
bundle install # install development dependencies
Expand Down
24 changes: 23 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.0.2] - 2026-09-05

### Added

- `examples/` folder with runnable local demos: `smoke_test.rb` (loads the gem
from source and prints sample passwords) and `local-consumer/` (a minimal
external project that depends on the gem via a `path:` reference).
- `docs/` folder with a documentation index (`docs/README.md`) and a
local-testing guide (`docs/local-testing.md`).
- "Trying it locally" section in the README linking to the examples and docs.

### Changed

- Excluded `examples/` and `docs/` from the packaged gem.

### Fixed

- Corrected the directory tree and command paths in the Kiro steering docs
(`structure.md`, `tech.md`), which still referenced a nested `password_forge/`
root left over from an older project layout.

## [0.0.1] - 2026-09-05

### Added
Expand All @@ -22,5 +43,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `PasswordForge.generate` convenience wrapper.
- RSpec test suite, RuboCop configuration and README.

[Unreleased]: https://github.com/devandreacarratta/password-forge-ruby-gem/compare/v0.0.1...HEAD
[Unreleased]: https://github.com/devandreacarratta/password-forge-ruby-gem/compare/v0.0.2...HEAD
[0.0.2]: https://github.com/devandreacarratta/password-forge-ruby-gem/compare/v0.0.1...v0.0.2
[0.0.1]: https://github.com/devandreacarratta/password-forge-ruby-gem/releases/tag/v0.0.1
34 changes: 29 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ categories are enabled by default, and a clear error is raised if you disable
every one of them. Randomness is provided by Ruby's `SecureRandom`.

This gem is also a showcase for building and shipping a Ruby gem the **Kiro
way**: it ships with Kiro skills, project steering, hooks and an MCP server (see
the [Roadmap](#roadmap)).
way**. Kiro skills, project steering, hooks and an MCP server are being added
incrementally (see the [Roadmap](#roadmap)).

## Installation

Install the gem and add it to the application's Gemfile by executing:
> **Not on RubyGems yet.** The first public release is planned for 0.1.0 (see
> the [Roadmap](#roadmap)). Until then, see [Trying it
> locally](#trying-it-locally) to run the gem from source or via a local path
> dependency.

Once published, install the gem and add it to the application's Gemfile by
executing:

```bash
bundle add password_forge
Expand Down Expand Up @@ -97,11 +103,26 @@ A non-positive or non-integer `length` raises `ArgumentError`.
| `numeric_case` | `0`–`9` |
| `special_case` | `` !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ `` |

## Trying it locally

You can run the gem without installing it from RubyGems:

- **From this repository:** `ruby examples/smoke_test.rb` prints a few sample
passwords straight from the source tree.
- **From another project:** add `gem "password_forge", path:
"/path/to/password-forge-ruby-gem"` to that project's `Gemfile`, run `bundle
install`, then `require "password_forge"`. See
[`examples/local-consumer/`](examples/local-consumer) for a working example.

Full instructions, including the interactive console and building a local
`.gem`, are in [docs/local-testing.md](docs/local-testing.md).

## Roadmap

`PasswordForge` is developed in incremental, tagged releases:

- **0.0.1** — Core generator, character sets, validation, tests, docs.
- **0.0.2** — Local-testing examples (`examples/`) and documentation (`docs/`).
- **0.1.0** — First public release on RubyGems.org via Trusted Publishing.
- **0.2.0** — Kiro skills for gem authors (feature TDD, version bump, release).
- **0.3.0** — Project `.kiro/` folder with steering and conventions.
Expand All @@ -113,9 +134,12 @@ A non-positive or non-integer `length` raises `ArgumentError`.

After checking out the repo, run `bin/setup` to install dependencies. Then run
`bundle exec rake` to run the tests and the linter. You can also run
`bin/console` for an interactive prompt to experiment.
`bin/console` for an interactive prompt to experiment, or
`ruby examples/smoke_test.rb` for a quick check straight from source.

To install this gem onto your local machine, run `bundle exec rake install`.
To install this gem onto your local machine, run `bundle exec rake install`. For
the full local workflow — including running it from a separate project and
uninstalling — see [docs/local-testing.md](docs/local-testing.md).

## Contributing

Expand Down
14 changes: 14 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# PasswordForge documentation

Extended documentation for the `password_forge` gem. This folder is not shipped
in the published gem; it lives in the repository for contributors and curious
readers.

## Contents

- [Local testing](local-testing.md) — how to try the gem locally, both from
this repository and from a separate project that depends on it via a local
path.

More guides will be added here as the project grows (see the roadmap in the
[main README](../README.md)).
132 changes: 132 additions & 0 deletions docs/local-testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Trying PasswordForge locally

This guide shows how to run the gem without publishing it, both from inside this
repository and from a separate project that depends on it via a local path.

All commands assume you start from the repository root
(`password-forge-ruby-gem/`) unless stated otherwise.

## 1. From this folder

### Run the smoke test

The quickest check. It loads the gem straight from `lib/` (no install needed)
and prints a few sample passwords:

```bash
ruby examples/smoke_test.rb
```

You should see a default password, a numeric PIN, a letters-only password, and
the `NoCharsetSelectedError` being raised on purpose.

### Use the interactive console

`bin/console` boots an IRB session with the gem already required:

```bash
bin/console
```

```ruby
PasswordForge.generate
PasswordForge::Generator.new(length: 32).generate
```

### Install it onto your machine

To install the current checkout as a normal gem on your system:

```bash
bundle exec rake install
```

After that, `require "password_forge"` works from any Ruby project on the same
machine.

## 2. From a different project (local path dependency)

This is how you consume the gem from another application while developing it,
without pushing anything to RubyGems.

In the other project's `Gemfile`, point Bundler at your checkout:

```ruby
# Gemfile of your other project
source "https://rubygems.org"

gem "password_forge", path: "/absolute/path/to/password-forge-ruby-gem"
```

Then, from that project:

```bash
bundle install
```

```ruby
require "password_forge"

PasswordForge.generate
```

Bundler resolves the gem from the given path, so a plain `require` works as if
the gem had been installed from RubyGems. Any edit you make in the gem source is
picked up on the next run — no reinstall needed.

### Ready-made example

A working example of this setup lives in
[`examples/local-consumer/`](../examples/local-consumer). It is a minimal
project whose `Gemfile` references the gem with a relative path (`../..`):

```bash
cd examples/local-consumer
bundle install
bundle exec ruby run.rb
```

## 3. Alternative: build and install a .gem

If you prefer to test the packaged artifact rather than a path dependency:

```bash
gem build password_forge.gemspec
gem install ./password_forge-0.0.2.gem
```

This installs the exact files that would ship to RubyGems (the `examples/` and
`docs/` folders are intentionally excluded from the package).

## 4. Uninstalling / switching to the published gem

If you installed the gem locally (via `rake install` or `gem install`) and want
to remove it, use `gem uninstall` rather than deleting files by hand:

```bash
gem uninstall password_forge
```

To see what is installed, or to target a specific version:

```bash
gem list password_forge
gem uninstall password_forge -v 0.0.2
```

Once the gem is published, switching to the RubyGems release is a plain
uninstall followed by a normal install:

```bash
gem uninstall password_forge
gem install password_forge
```

> **Note:** `password_forge` is not on RubyGems yet (the first public release is
> planned for 0.1.0 — see the roadmap in the [main README](../README.md)). Until
> then, `gem install password_forge` will not find it, so the local install and
> path-dependency approaches above are the way to try it.
>
> While developing, the path dependency in section 2 is usually the most
> convenient: there is nothing to install or uninstall, and source edits are
> picked up on the next run.
13 changes: 13 additions & 0 deletions examples/local-consumer/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

# Minimal "external" project that consumes password_forge from local source.
#
# The path is relative to this Gemfile: two levels up is the gem repo root,
# where password_forge.gemspec lives. In a real project you would point this
# at wherever you checked out the gem, e.g.:
#
# gem "password_forge", path: "/absolute/path/to/password-forge-ruby-gem"
#
source "https://rubygems.org"

gem "password_forge", path: "../.."
17 changes: 17 additions & 0 deletions examples/local-consumer/run.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

# Demo entry point for the local-consumer example project.
#
# This mimics an external application that depends on password_forge. Bundler
# resolves the gem from the local path declared in the Gemfile, so a plain
# `require "password_forge"` loads it as if it had been installed normally.
#
# Run it from this directory:
#
# bundle install
# bundle exec ruby run.rb
#
require "password_forge"

puts "Using password_forge v#{PasswordForge::VERSION} from a local path dependency."
puts "Generated password: #{PasswordForge.generate}"
38 changes: 38 additions & 0 deletions examples/smoke_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

# Smoke test for PasswordForge.
#
# Loads the gem straight from the local source tree (no install required) and
# prints a few sample passwords so you can eyeball that everything works.
#
# Run it from the repository root:
#
# ruby examples/smoke_test.rb
#
require_relative "../lib/password_forge"

puts "PasswordForge v#{PasswordForge::VERSION} — smoke test"
puts "-" * 48

puts "Default (all sets, length 16):"
puts " #{PasswordForge.generate}"

puts "Numeric PIN (length 4):"
puts " #{PasswordForge::Generator.new(
upper_case: false, lower_case: false, numeric_case: true, special_case: false, length: 4
).generate}"

puts "Letters only (length 24):"
puts " #{PasswordForge::Generator.new(
numeric_case: false, special_case: false, length: 24
).generate}"

puts "No character set selected (expected error):"
begin
PasswordForge::Generator.new(
upper_case: false, lower_case: false, numeric_case: false, special_case: false
)
rescue PasswordForge::NoCharsetSelectedError => e
puts " raised #{e.class}: #{e.message}"
end
2 changes: 1 addition & 1 deletion lib/password_forge/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module PasswordForge
VERSION = "0.0.1"
VERSION = "0.0.2"
end
Loading