Rewritten the code-breaker submits guess feature because the use of background and scenario outline is not working properly
Code-breaker submits guess (step 1 - red)
Feature: Code-breaker submits guess
Scenario: All
Step: the secret code is "<code>" - red

it's time to face the first step `the secret code is "<code>"`, so lets add this code to the `FeatureContext` file

    public function theSecretCodeIs($secret)
    {
        $this->command = (new CodebreakerCommand())
            ->setSecret($secret);
    }

If we run behat we will find a fatal error becouse `setSecret` method is undefined but that is the expected outcome, we will define it later using phpspec

    bin/behat features/code-breaker_submits_guess.feature
CodebreakerCommand (example 5 - red)
Feature: Code-breaker submits guess
Scenario: All
Step: the secret code is "<code>" - red
Specification: CodebreakerCommand
Example: it_should_set_a_secret - red

For the next step we need to change to phpspec and create the behaviour the command should set a secret inside the `CodebreakerCommandSpec` class

    function it_should_set_a_secret()
    {
        $this->setSecret('1234');
        $this->getSecret()->shouldReturn('1234');
    }

Now if we run phpspec several time it will create the method `setSecret` and `getSecret` and finally we will have a failing example

    bin/phpspec run spec/Aleherse/Codebreaker/CodebreakerCommandSpec.php
CodebreakerCommand (example 5 - green) / Code-breaker submits guess (step 1 - green)
Feature: Code-breaker submits guess
Scenario: All
Step: the secret code is "<code>" - green
Specification: CodebreakerCommand
Example: it_should_set_a_secret - green

And making this example pass is as easy is add these lines to the `CodebreakerCommand` class

    protected $secret = '0000';

    public function setSecret($secret)
    {
        $this->secret = $secret;

        return $this;
    }

    public function getSecret()
    {
        return $this->secret;
    }

If we run phpspec now the example is passing but also if we run behat we find that 14 steps are passing, this is because the first step is also the first in the 14 scenarios
Code-breaker submits guess (step 2 - red)
Feature: Code-breaker submits guess
Scenario: All
Step: I guess "<guess>" - red

First step done, lets move to the second one `I guess "<guess>"`, the code we need to add is very simple

    public function iGuess($guess)
    {
        $this->command->guess($guess);
    }

And like with the previous one we encounter a fatal error
CodebreakerCommand (example 6 - green) / Code-breaker submits guess (step 2 - green)
Feature: Code-breaker submits guess
Scenario: All
Step: I guess "<guess>" - green
Specification: CodebreakerCommand
Example: it_should_receive_a_guess - green

And like with the previous one we encounter a fatal error so it's time to change to phpspec again and add this behaviour to the `CodebreakerCommand`

    function it_should_receive_a_guess()
    {
        $this->guess('5555');
    }

Like before running phpspec two times will create the `guess` method and as different from the previous step this time the example is passing without adding any code and also the second step in behat is passing

Maybe this situation looks weird at first because the step is passing but we didn't actually add any code, but it's ok that was the intended behaviour
Refactor: FeatureContext

So lets move to the third step `the mark should be "<mark>"` and everything will make sense.

In this step we need to check the mark and the mark depends on the guess so the expected behaviour is that the method `guess` should return the calculated mark, so we need to refactor the `iGuess` method in `FeatureContext` class

    protected $mark;

    public function iGuess($guess)
    {
        $this->mark = $this->command->guess($guess);
    }

Executing behat and phpspec we'll see that everything is working as before so we didn't introduce any error, great
Code-breaker submits guess (step 3 - red)
Feature: Code-breaker submits guess
Scenario: All
Step: the mark should be "<mark>" - red

Thanks to the refactor now we can check the returned mark in the `theMarkShouldBe` method and the code to do that is

    public function theMarkShouldBe($mark)
    {
        if($mark !== $this->mark) {
            throw new Exception(sprintf('Expected mark %s but got %s', $mark, $this->mark));
        }
    }

If we run behat we have 14 failing scenarios because of this third step
CodebreakerCommand (example 7 - red)
Feature: Code-breaker submits guess
Scenario: no matches
Step: the mark should be "<mark>" - red
Specification: CodebreakerCommand
Example: it_returns_an_empty_mark_with_a_guess_with_no_matches - red

lets move again to phpspec, but now this is not a trivial example because depending on the guess we have different resulting marks and of course different scenarios to choose, so the best practice here is going to the easiest scenario

In this case it is the no matches scenario so the expected behaviour is that `guess` should return an empty mark with no matches and this is the example

    function it_returns_an_empty_mark_with_a_guess_with_no_matches()
    {
        $this->setSecret('1234');
        $this->guess('5555')->shouldReturn('');
    }

As expected the example is failing
Code-breaker submits guess (1 out of 14)
Feature: Code-breaker submits guess
Scenario: no matches
Step: the mark should be "<mark>" - green

To make it pass we only need to return an empty string in the `guess` method of `CodebreakerCommand`

    public function guess($guess)
    {
        return '';
    }

So now 1 scenario out of 14 is working
CodebreakerCommand (example 8 - red)
Feature: Code-breaker submits guess
Scenario: 1 number correct
Step: the mark should be "<mark>" - red
Specification: CodebreakerCommand
Example: it_returns_a_minus_mark_with_a_guess_with_one_number_match - red

The next easier scenario is when one number is correct because of a number match and this is the behaviour we are expecting

    function it_returns_a_minus_mark_with_a_guess_with_one_number_match()
    {
        $this->setSecret('1234');
        $this->guess('25555')->shouldReturn('-');
    }

As always the example is failing
CodebreakerCommand (example 8 - green) / Submits guess (2 out of 14)
Feature: Code-breaker submits guess
Scenario: 1 number correct
Step: the mark should be "<mark>" 1 out of 2
Specification: CodebreakerCommand
Example: it_returns_a_minus_mark_with_a_guess_with_one_number_match - green

To make the example pass the logic we need is

    public function guess($guess)
    {
        $mark = '';

        if (strpos($this->getSecret(), $guess[0])) {
            $mark .= '-';
        } else {
            $mark .= '';
        }

        return $mark;
    }

I am sure you know a better implementation of the algorithm or at least something to make it pass several scenario at once, but the objective of BDD is do the minimun effort to make the actual step/example pass. My point here is that as you get experience in this methodology if you are confidence enough you can make bigger and bigger steps

With the previous code all the phpspec examples are working and in behat we have 2 scenarios out of 14 running
CodebreakerCommand (example 9 - red)
Feature: Code-breaker submits guess
Scenario: 1 number correct
Step: the mark should be "<mark>" - 1 out of 2
Specification: CodebreakerCommand
Example: it_returns_a_plus_mark_with_a_guess_with_one_exact_match - red

It's time to move to the behaviour when we find an exact match and then test that the example is failing

    function it_returns_a_plus_mark_with_a_guess_with_one_exact_match()
    {
        $this->setSecret('1234');
        $this->guess('15555')->shouldReturn('+');
    }
CodebreakerCommand (example 9 - green) / Submits guess (3 out of 14)
Feature: Code-breaker submits guess
Scenario: 1 number correct
Step: the mark should be "<mark>" - 2 out of 2
Specification: CodebreakerCommand
Example: it_returns_a_plus_mark_with_a_guess_with_one_exact_match - green

The modification of the `guess` method to make the example pass is the next one and after the change we also have 3 scenarios out of 14 working

    public function guess($guess)
    {
        $mark = '';

        if (0 === strpos($this->getSecret(), $guess[0]) ) {
            $mark .= '+';
        } else if (0 < strpos($this->getSecret(), $guess[0]) ) {
            $mark .= '-';
        }

        return $mark;
    }
Refactor: CodebreakerCommand

We are on fire but before moving to another scenario it's time to refactor our code a bit because the method `guess` is getting bigger so lets rewrite it to this

    public function guess($guess)
    {
        $mark = '';

        if ($this->exactMatch($guess, 0)) {
            $mark .= '+';
        } elseif ($this->numberMatch($guess, 0)) {
            $mark .= '-';
        }

        return $mark;
    }

    protected function exactMatch($guess, $index)
    {
        return $this->getSecret()[$index] == $guess[$index];
    }

    protected function numberMatch($guess, $index)
    {
        return false !== strpos($this->getSecret(), $guess[$index]);
    }

Now the intention behind the `guess` method is really clear reading the actual code and also the scenarios and examples are working as before
CodebreakerCommand (example 10 - red)
Feature: Code-breaker submits guess
Scenario: 2 numbers correct - 0 out of 3
Step: the mark should be "<mark>"
Specification: CodebreakerCommand
Example: it_returns_2_minus_marks_with_a_guess_with_2_number_match - red

lets go for the next easier scenario, it has to return two minus marks with two numbers match

    function it_returns_2_minus_marks_with_a_guess_with_2_number_match()
    {
        $this->setSecret('1234');
        $this->guess('2355')->shouldReturn('--');
    }
CodebreakerCommand (example 10 - green) / Submits guess (11 out of 14)
Feature: Code-breaker submits guess
Scenario: 2 numbers correct - 2 out of 3
Step: the mark should be "<mark>"
Specification: CodebreakerCommand
Example: it_returns_2_minus_marks_with_a_guess_with_2_number_match - green

To make this example pass we only need to modify the `guess` method to iterate through all the numbers of the guess

    public function guess($guess)
    {
        $mark = '';

        for ($i = 0; $i < 4; $i++) {
            if ($this->exactMatch($guess, $i)) {
                $mark .= '+';
            } elseif ($this->numberMatch($guess, $i)) {
                $mark .= '-';
            }
        }

        return $mark;
    }

To our surprise we have jumped from 3 scenarios out 14 to eleven passing scenarios
CodebreakerCommand (example 11 - red)
Feature: Code-breaker submits guess
Scenario: 2 numbers correct - 2 out of 3
Step: the mark should be "<mark>"
Specification: CodebreakerCommand
Example: it_returns_a_plus_and_a_minus_mark_with_a_number_match_and_an_exact_match - red

It is time to see why we have three failing scenarios left, if we read the error message `Expected mark +-- but got --+` we can easily see that our solution is given the correct mark but not in the expected order so lets write a new example the ammend the problem

    function it_returns_a_plus_and_a_minus_mark_with_a_number_match_and_an_exact_match()
    {
        $this->setSecret('1234');
        $this->guess('2535')->shouldReturn('+-');
    }
CodebreakerCommand (example 11 - green) / Submits guess (14 out of 14)
Feature: Code-breaker submits guess
Scenario: All - green
Step: the mark should be "<mark>"
Specification: CodebreakerCommand
Example: it_returns_a_plus_and_a_minus_mark_with_a_number_match_and_an_exact_match - green

We can make this example pass checking for the exact match before and then for the number match and concatenate the results

    public function guess($guess)
    {
        $mark = '';

        for ($i = 0; $i < 4; $i++) {
            if ($this->exactMatch($guess, $i)) {
                $mark .= '+';
            }
        }

        for ($i = 0; $i < 4; $i++) {
            if ($this->numberMatch($guess, $i)) {
                $mark .= '-';
            }
        }

        return $mark;
    }

But the example is still failing and also now we have go down to 5 scenario out of 14. So lets see what is happening The error message is `expected "+-", but got "+--"`, we now realize that the problem is that an exact match is also counted as a number match so we need to rewrite the `numberMatch` method to not return a mark if it is also an exact match

    protected function numberMatch($guess, $index)
    {
        $pos = strpos($this->getSecret(), $guess[$index]);

        return false !== $pos && $pos != $index;
    }

Great now all the examples and scenarios are passing!
Refactor: CodebreakerCommand

Now we can refactor several times and after each modification run behat and phpspec the check if everything is working as expected

The first refactor we can do is clarify the nature of the guess method

    public function guess($guess)
    {
        $exactMatchCount = 0;
        $numberMatchCount = 0;

        for ($i = 0; $i < 4; $i++) {
            if ($this->exactMatch($guess, $i)) {
                $exactMatchCount++;
            }
        }

        for ($i = 0; $i < 4; $i++) {
            if ($this->numberMatch($guess, $i)) {
                $numberMatchCount++;
            }
        }

        return str_repeat('+', $exactMatchCount) . str_repeat('-', $numberMatchCount);
    }